C从数字数组创建png/位图

新手上路,请多包涵

所以我找到了这个关于我的问题的链接,但它适用于 c#

从字节数组创建 PNG

我有一个可变的 int 数字数组。我将它称为“pix[]”,现在它可以是从 3 到 256 的任何大小,以后可能更大。

我现在要做的是将其转换为像素图像。我仍然是一个noobin c++,所以请原谅。我尝试下载一些使使用 libpng 更容易的库,但它们似乎不起作用(ubuntu,code::blocks)所以我有以下问题:

1)你如何创建一个新的位图(哪些库,哪个命令)?

  1. 我如何用“pix[]”中的信息填充它?

3)我如何保存它?

如果它是一个问题的转贴,我也对链接感到高兴;)

这是我到目前为止的工作,感谢您的帮助。

 int main(){
 FILE *imageFile;
 int x,y,pixel,height=2,width=3;

 imageFile=fopen("image.pgm","wb");
 if(imageFile==NULL){
  perror("ERROR: Cannot open output file");
  exit(EXIT_FAILURE);
 }

 fprintf(imageFile,"P3\n");           // P3 filetype
 fprintf(imageFile,"%d %d\n",width,height);   // dimensions
 fprintf(imageFile,"255\n");          // Max pixel
  int pix[100] {200,200,200, 100,100,100, 0,0,0, 255,0,0, 0,255,0, 0,0,255};

       fwrite(pix,1,18,imageFile);

fclose(imageFile);
}

我还没有完全理解它的作用。我可以打开输出图像,但它不是数组的正确表示。

如果我改变一些东西,例如制作一个二维数组,那么图像查看器会告诉我“预期为整数”并且不会显示图像。

到目前为止,一切都很好。因为我在图像之前有数组,所以我创建了一个函数 aufrunden 向上舍入到下一个整数,因为我想创建一个方形图像。

 int aufrunden (double h)
{
int i =h;
if (h-i == 0)
  {
  return i;
  }
else
  {
  i = h+1;
  return i;
  }
}

此函数用于创建图像。如果图像大于数组提供的信息,如下所示( a 是数组的长度)

 double h;
h= sqrt(a/3.0);
int i = aufrunden(h);
FILE *imageFile;
int height=i,width=i;

现在可能会发生,该数组是 a=24 长。 aufrunden 使图像为 3x3,因此它有 27 个值…意味着它缺少 1 个像素的值。或更糟糕的是,它只有 a=23 长。还创建一个 3x3 图像。

fwrite(pix,1,18,imageFile); 会在这些像素中写入什么信息?如果剩余的值只是 0,那将是最好的。

*编辑没关系,我只会在数组的末尾添加 0 直到它填满整个正方形……对不起

原文由 busssard 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 931
1 个回答

下面的代码将像素颜色的整数数组作为输入,并将其写入 .bmp 位图文件,或者相反,读取 .bmp 位图文件并将其图像内容存储为 int 数组。它只需要 <fstream> 库。 The input parameter path can be for example C:/path/to/your/image.bmp and data is formatted as data[x+y*width]=(red<<16)|(green<<8)|blue; , whereby red , greenblue0-255 范围内的整数,像素位置是 (x,y)

 #include <string>
#include <fstream>
using namespace std;
typedef unsigned int uint;
int* read_bmp(const string path, uint& width, uint& height) {
    ifstream file(path, ios::in|ios::binary);
    if(file.fail()) println("\rError: File \""+filename+"\" does not exist!");
    uint w=0, h=0;
    char header[54];
    file.read(header, 54);
    for(uint i=0; i<4; i++) {
        w |= (header[18+i]&255)<<(8*i);
        h |= (header[22+i]&255)<<(8*i);
    }
    const int pad=(4-(3*w)%4)%4, imgsize=(3*w+pad)*h;
    char* img = new char[imgsize];
    file.read(img, imgsize);
    file.close();
    int* data = new int[w*h];
    for(uint y=0; y<h; y++) {
        for(uint x=0; x<w; x++) {
            const int i = 3*x+y*(3*w+pad);
            data[x+(h-1-y)*w] = (img[i]&255)|(img[i+1]&255)<<8|(img[i+2]&255)<<16;
        }
    }
    delete[] img;
    width = w;
    height = h;
    return data;
}
void write_bmp(const string path, const uint width, const uint height, const int* const data) {
    const int pad=(4-(3*width)%4)%4, filesize=54+(3*width+pad)*height; // horizontal line must be a multiple of 4 bytes long, header is 54 bytes
    char header[54] = { 'B','M', 0,0,0,0, 0,0,0,0, 54,0,0,0, 40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,24,0 };
    for(uint i=0; i<4; i++) {
        header[ 2+i] = (char)((filesize>>(8*i))&255);
        header[18+i] = (char)((width   >>(8*i))&255);
        header[22+i] = (char)((height  >>(8*i))&255);
    }
    char* img = new char[filesize];
    for(uint i=0; i<54; i++) img[i] = header[i];
    for(uint y=0; y<height; y++) {
        for(uint x=0; x<width; x++) {
            const int color = data[x+(height-1-y)*width];
            const int i = 54+3*x+y*(3*width+pad);
            img[i  ] = (char)( color     &255);
            img[i+1] = (char)((color>> 8)&255);
            img[i+2] = (char)((color>>16)&255);
        }
        for(uint p=0; p<pad; p++) img[54+(3*width+p)+y*(3*width+pad)] = 0;
    }
    ofstream file(path, ios::out|ios::binary);
    file.write(img, filesize);
    file.close();
    delete[] img;
}

代码片段的灵感来自 https://stackoverflow.com/a/47785639/9178992

对于 .png 图像,使用 lodepng.cpplodepng.h

 #include <string>
#include <vector>
#include <fstream>
#include "lodepng.h"
using namespace std;
typedef unsigned int uint;
int* read_png(const string path, uint& width, uint& height) {
    vector<uchar> img;
    lodepng::decode(img, width, height, path, LCT_RGB);
    int* data = new int[width*height];
    for(uint i=0; i<width*height; i++) {
        data[i] = img[3*i]<<16|img[3*i+1]<<8|img[3*i+2];
    }
    return data;
}
void write_png(const string path, const uint width, const uint height, const int* const data) {
    uchar* img = new uchar[3*width*height];
    for(uint i=0; i<width*height; i++) {
        const int color = data[i];
        img[3*i  ] = (color>>16)&255;
        img[3*i+1] = (color>> 8)&255;
        img[3*i+2] =  color     &255;
    }
    lodepng::encode(path, img, width, height, LCT_RGB);
    delete[] img;
}

原文由 ProjectPhysX 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏