使用 libpng 从内存中的数字数组创建 png 图像
Create png image from array of numbers in memory using libpng
我想转换存储在内存中的字节,如
// pix is array of bytes with format format R, G, B, A, R, G, B, A, ...
// further image is going to be 250x300, so size is 250*300*4
char pix[250*300*4] = {
0, 255, 0, 0, //1
0, 255, 0, 0, //2
...
0, 255, 0, 0 //250*300
} // green image
在 libpng 的帮助下 到 png 图像。
但我还没有找到任何合适的功能来做到这一点。所以,我正在寻找类似的功能
png_bitmap_to_png(void *bitmap, void* png_raw_bytes)
。
如果您有其他关于如何将字节数组转换为 png 图像的想法,我很高兴听到他们的意见,但如果没有必要,请不要提供其他库或转换器(如 ImageMagick)的使用。
我知道怎么做了。我使用 row_pointers
存储我的颜色编号而不是 pix
数组,如果需要,您可以创建一些函数将 pix 数组转换为 row_pointers。这是我的代码,希望对您有所帮助
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <png.h>
#define IMAGE_HEIGHT 250
#define IMAGE_WIDTH 300
#define IMAGE_RED_COLOR 0
#define IMAGE_GREEN_COLOR 255
#define IMAGE_BLUE_COLOR 0
#define IMAGE_ALPHA_CHANNEL 255
void write_png_image(char* filename)
{
png_byte** row_pointers; // pointer to image bytes
FILE* fp; // file for image
do // one time do-while to properly free memory and close file after error
{
row_pointers = (png_byte**)malloc(sizeof(png_byte*) * IMAGE_HEIGHT);
if (!row_pointers)
{
printf("Allocation failed\n");
break;
}
for (int i = 0; i < IMAGE_HEIGHT; i++)
{
row_pointers[i] = (png_byte*)malloc(4*IMAGE_WIDTH);
if (!row_pointers[i])
{
printf("Allocation failed\n");
break;
}
}
// fill image with color
for (int y = 0; y < IMAGE_HEIGHT; y++)
{
for (int x = 0; x < IMAGE_WIDTH*4; x+=4)
{
row_pointers[y][x] = IMAGE_RED_COLOR; //r
row_pointers[y][x + 1] = IMAGE_GREEN_COLOR; //g
row_pointers[y][x + 2] = IMAGE_BLUE_COLOR; //b
row_pointers[y][x + 3] = IMAGE_ALPHA_CHANNEL; //a
}
}
//printf("%d %d %d %d\n", row_pointers[0][0], row_pointers[0][1], row_pointers[0][2], row_pointers[0][3]);
fp = fopen(filename, "wb"); //create file for output
if (!fp)
{
printf("Open file failed\n");
break;
}
png_struct* png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); //create structure for write
if (!png)
{
printf("Create write struct failed\n");
break;
}
png_infop info = png_create_info_struct(png); // create info structure
if (!info)
{
printf("Create info struct failed\n");
break;
}
if (setjmp(png_jmpbuf(png))) // this is some routine for errors?
{
printf("setjmp failed\n");
}
png_init_io(png, fp); //initialize file output
png_set_IHDR( //set image properties
png, //pointer to png_struct
info, //pointer to info_struct
IMAGE_WIDTH, //image width
IMAGE_HEIGHT, //image height
8, //color depth
PNG_COLOR_TYPE_RGBA, //color type
PNG_INTERLACE_NONE, //interlace type
PNG_COMPRESSION_TYPE_DEFAULT, //compression type
PNG_FILTER_TYPE_DEFAULT //filter type
);
png_write_info(png, info); //write png image information to file
png_write_image(png, row_pointers); //the thing we gathered here for
png_write_end(png, NULL);
printf("Image was created successfully\nCheck %s file\n", filename);
} while(0);
//close file
if (fp)
{
fclose(fp);
}
//free allocated memory
for (int i = 0; i < IMAGE_HEIGHT; i++)
{
if (row_pointers[i])
{
free(row_pointers[i]);
}
}
if (row_pointers)
{
free(row_pointers);
}
}
int main(int argc, char* argv[])
{
if(argc == 2)
{
write_png_image(argv[1]);
}
else
{
printf("Usage: %s pngfile.png\n", argv[0]);
}
return 0;
}
我想转换存储在内存中的字节,如
// pix is array of bytes with format format R, G, B, A, R, G, B, A, ...
// further image is going to be 250x300, so size is 250*300*4
char pix[250*300*4] = {
0, 255, 0, 0, //1
0, 255, 0, 0, //2
...
0, 255, 0, 0 //250*300
} // green image
在 libpng 的帮助下 到 png 图像。
但我还没有找到任何合适的功能来做到这一点。所以,我正在寻找类似的功能
png_bitmap_to_png(void *bitmap, void* png_raw_bytes)
。
如果您有其他关于如何将字节数组转换为 png 图像的想法,我很高兴听到他们的意见,但如果没有必要,请不要提供其他库或转换器(如 ImageMagick)的使用。
我知道怎么做了。我使用 row_pointers
存储我的颜色编号而不是 pix
数组,如果需要,您可以创建一些函数将 pix 数组转换为 row_pointers。这是我的代码,希望对您有所帮助
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <png.h>
#define IMAGE_HEIGHT 250
#define IMAGE_WIDTH 300
#define IMAGE_RED_COLOR 0
#define IMAGE_GREEN_COLOR 255
#define IMAGE_BLUE_COLOR 0
#define IMAGE_ALPHA_CHANNEL 255
void write_png_image(char* filename)
{
png_byte** row_pointers; // pointer to image bytes
FILE* fp; // file for image
do // one time do-while to properly free memory and close file after error
{
row_pointers = (png_byte**)malloc(sizeof(png_byte*) * IMAGE_HEIGHT);
if (!row_pointers)
{
printf("Allocation failed\n");
break;
}
for (int i = 0; i < IMAGE_HEIGHT; i++)
{
row_pointers[i] = (png_byte*)malloc(4*IMAGE_WIDTH);
if (!row_pointers[i])
{
printf("Allocation failed\n");
break;
}
}
// fill image with color
for (int y = 0; y < IMAGE_HEIGHT; y++)
{
for (int x = 0; x < IMAGE_WIDTH*4; x+=4)
{
row_pointers[y][x] = IMAGE_RED_COLOR; //r
row_pointers[y][x + 1] = IMAGE_GREEN_COLOR; //g
row_pointers[y][x + 2] = IMAGE_BLUE_COLOR; //b
row_pointers[y][x + 3] = IMAGE_ALPHA_CHANNEL; //a
}
}
//printf("%d %d %d %d\n", row_pointers[0][0], row_pointers[0][1], row_pointers[0][2], row_pointers[0][3]);
fp = fopen(filename, "wb"); //create file for output
if (!fp)
{
printf("Open file failed\n");
break;
}
png_struct* png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); //create structure for write
if (!png)
{
printf("Create write struct failed\n");
break;
}
png_infop info = png_create_info_struct(png); // create info structure
if (!info)
{
printf("Create info struct failed\n");
break;
}
if (setjmp(png_jmpbuf(png))) // this is some routine for errors?
{
printf("setjmp failed\n");
}
png_init_io(png, fp); //initialize file output
png_set_IHDR( //set image properties
png, //pointer to png_struct
info, //pointer to info_struct
IMAGE_WIDTH, //image width
IMAGE_HEIGHT, //image height
8, //color depth
PNG_COLOR_TYPE_RGBA, //color type
PNG_INTERLACE_NONE, //interlace type
PNG_COMPRESSION_TYPE_DEFAULT, //compression type
PNG_FILTER_TYPE_DEFAULT //filter type
);
png_write_info(png, info); //write png image information to file
png_write_image(png, row_pointers); //the thing we gathered here for
png_write_end(png, NULL);
printf("Image was created successfully\nCheck %s file\n", filename);
} while(0);
//close file
if (fp)
{
fclose(fp);
}
//free allocated memory
for (int i = 0; i < IMAGE_HEIGHT; i++)
{
if (row_pointers[i])
{
free(row_pointers[i]);
}
}
if (row_pointers)
{
free(row_pointers);
}
}
int main(int argc, char* argv[])
{
if(argc == 2)
{
write_png_image(argv[1]);
}
else
{
printf("Usage: %s pngfile.png\n", argv[0]);
}
return 0;
}