Although I have successfully utilized stb_image/CImg/lodepng open source to get a char array, the memory usage is too huge that I can't implement it in a low power embedded system.
Therefore, I try to use libpng to read a png type image, and get a char array.
However, I am completely not familiar with libpng......
Anyone can help?
According to some website sample programs, I write the following function. But I encounter Segmentation Fault, I think that I have problem dealing with the variables, raw_pointers and image. Anyone can review my code and give me some suggestions?
unsigned char* read_png_file(const char *filename)
{
FILE *fp = fopen(filename, "rb");
int bit_depth;
int color_type;
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png_infop info = png_create_info_struct(png);
png_init_io(png, fp);
png_read_info(png, info);
width = png_get_image_width(png, info);
height = png_get_image_height(png, info);
color_type = png_get_color_type(png, info);
bit_depth = png_get_bit_depth(png, info);
int numchan = 4;
// Set up row pointers
row_pointers = (unsigned char**) malloc(sizeof(unsigned char) * height);
for (int y=0; y<height; y++)
row_pointers[y] = (unsigned char*) malloc(sizeof(unsigned char) * width);
png_read_image(png, row_pointers);
// Put row pointers data into image
unsigned char * image = (unsigned char *) malloc (numchan*width*height);
for (unsigned int i=0;i<height;i++)
for (unsigned int j=0;j<width;i++)
*image++ = row_pointers[j][i];
fclose(fp);
cout << height << ", " << width << ", " << bit_depth << ", " << numchan << endl;
return image;
}
I successfully use libpng to get a char array.
However, the memory usage is up to 915.1KB which is higher than stb_image !!! (Use Valgrind)
Ah... Could anyone tell me some directions to optimize the memory usage?
unsigned char* read_png_file(const char *filename)
{
FILE *fp = fopen(filename, "rb");
png_byte bit_depth;
png_byte color_type;
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png_infop info = png_create_info_struct(png);
png_init_io(png, fp);
png_read_info(png, info);
width = png_get_image_width(png, info);
height = png_get_image_height(png, info);
color_type = png_get_color_type(png, info);
bit_depth = png_get_bit_depth(png, info);
if(color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png);
if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
png_set_expand_gray_1_2_4_to_8(png);
if(png_get_valid(png, info, PNG_INFO_tRNS))
png_set_tRNS_to_alpha(png);
if(color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE)
png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png);
png_read_update_info(png, info);
int numchan = 4;
// Set up row pointer
png_bytep *row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height);
unsigned int i, j;
for (i = 0; i < height; i++)
row_pointers[i] = (png_bytep)malloc(png_get_rowbytes(png,info));
png_read_image(png, row_pointers);
// Put row pointers data into image
unsigned char *image = (unsigned char *) malloc (numchan*width*height);
int count = 0;
for (i = 0 ; i < height ; i++)
{
for (j = 0 ; j < numchan*width ; j++)
{
image[count] = row_pointers[i][j];
count += 1;
}
}
fclose(fp);
for (i = 0; i < height; i++)
free(row_pointers[i]) ;
free(row_pointers) ;
return image;
}