static FtkBitmap* load_png (const char *filename) { FtkColor bg = {0}; unsigned int x = 0; unsigned int y = 0; png_byte bit_depth = 0; unsigned int width = 0; unsigned int height = 0; int number_of_passes = 0; png_byte color_type = 0; png_infop info_ptr = NULL; png_structp png_ptr = NULL; png_bytep * row_pointers = NULL; char header[8]; // 8 is the maximum size that can be checked int rowbytes = 0; FtkColor* dst = NULL; unsigned char* src = NULL; FtkBitmap* bitmap = NULL; FILE *fp = fopen(filename, "rb"); return_val_if_fail(fp, NULL); bg.a = 0xff; fread(header, 1, 8, fp); return_val_if_fail(png_sig_cmp(header, 0, 8) == 0, NULL); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); return_val_if_fail(png_ptr, NULL); info_ptr = png_create_info_struct(png_ptr); return_val_if_fail(info_ptr, NULL); return_val_if_fail(setjmp(png_jmpbuf(png_ptr)) == 0, NULL); png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); number_of_passes = png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); return_val_if_fail(setjmp(png_jmpbuf(png_ptr)) == 0, NULL); rowbytes = png_get_rowbytes(png_ptr,info_ptr); row_pointers = (png_bytep*) FTK_ZALLOC(sizeof(png_bytep) * height); for (y=0; y<height; y++) { row_pointers[y] = (png_byte*) FTK_ZALLOC(rowbytes); } png_read_image(png_ptr, row_pointers); fclose(fp); bitmap = ftk_bitmap_create(width, height, bg); dst = ftk_bitmap_lock(bitmap); if (color_type == PNG_COLOR_TYPE_RGBA) { unsigned int w = width; unsigned int h = height; for(y = 0; y < h; y++) { src = row_pointers[y]; for(x = 0; x < w; x++) { if(src[3]) { dst->r = src[0]; dst->g = src[1]; dst->b = src[2]; dst->a = src[3]; } else { dst->r = 0xff; dst->g = 0xff; dst->b = 0xff; dst->a = 0; } src +=4; dst++; } } } else if(color_type == PNG_COLOR_TYPE_RGB) { unsigned int w = width; unsigned int h = height; for(y = 0; y < h; y++) { src = row_pointers[y]; for(x = 0; x < w; x++) { dst->r = src[0]; dst->g = src[1]; dst->b = src[2]; dst->a = 0xff; src += 3; dst++; } } } else { assert(!"not supported."); } for(y = 0; y < height; y++) { FTK_FREE(row_pointers[y]); } FTK_FREE(row_pointers); return bitmap; }
png_bytep readpng_get_image(png_structp* png_ptr, png_infop* info_ptr, png_infop* end_ptr) { //test for if(setjmp(png_jmpbuf(*png_ptr))) { png_destroy_read_struct(png_ptr, info_ptr, NULL); std::cerr << "error during setjmp" << std::endl; return NULL; } png_uint_32 width, height; int bit_depth, color_type; png_uint_32 numrowbytes; png_bytep dataBlock; // gamma correction start (optional) double display_exponent = 2.2; //standard in most systems + standard in imageprocessing int envGamma = 0; if(envGamma) display_exponent = (double)envGamma; double gamma; if(png_get_gAMA(*png_ptr, *info_ptr, &gamma)) png_set_gamma(*png_ptr, display_exponent, gamma); // gamma correction end png_get_IHDR(*png_ptr, *info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); //transform the png to a standard format if(color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand(*png_ptr); if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand(*png_ptr); if(png_get_valid(*png_ptr, *info_ptr, PNG_INFO_tRNS)) png_set_expand(*png_ptr); if(bit_depth == 16) png_set_strip_16(*png_ptr); if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(*png_ptr); png_read_update_info(*png_ptr, *info_ptr); //end //proccessing for the dataBlock (pixeldata) numrowbytes = png_get_rowbytes(*png_ptr, *info_ptr); png_bytep row_pointers[height]; dataBlock = (png_bytep)malloc(sizeof(png_byte)*numrowbytes*height); for(png_uint_32 i = 0; i<height; i++) row_pointers[i] = dataBlock + i*numrowbytes; png_read_image(*png_ptr, row_pointers); //end //optional reading of end in end_ptr and test for consistence png_read_end(*png_ptr, NULL); return dataBlock; }
pictw_t * spng_read(session_t *ps, const char *path) { assert(path); char sig[SPNG_SIGBYTES] = ""; pictw_t *pictw = NULL; png_structp png_ptr = NULL; png_infop info_ptr = NULL; FILE *fp = fopen(path, "rb"); bool need_premultiply = false; if (unlikely(!fp)) { printfef("(\"%s\"): Failed to open file.", path); goto spng_read_end; } if (unlikely(SPNG_SIGBYTES != fread(&sig, 1, SPNG_SIGBYTES, fp))) { printfef("(\"%s\"): Failed to read %d-byte signature.", path, SPNG_SIGBYTES); goto spng_read_end; } if (unlikely(png_sig_cmp((png_bytep) sig, 0, SPNG_SIGBYTES))) { printfef("(\"%s\"): PNG signature invalid.", path); goto spng_read_end; } png_ptr = allocchk(png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)); info_ptr = allocchk(png_create_info_struct(png_ptr)); if (setjmp(png_jmpbuf(png_ptr))) goto spng_read_end; png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, SPNG_SIGBYTES); png_read_info(png_ptr, info_ptr); png_uint_32 width = 0, height = 0; // Set transformations int bit_depth = 0, color_type = 0; { int interlace_type = 0; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); // Scale or strip 16-bit colors if (bit_depth == 16) { printfdf("(\"%s\"): Scaling 16-bit colors.", path); #if PNG_LIBPNG_VER >= 10504 png_set_scale_16(png_ptr); #else png_set_strip_16(png_ptr); #endif bit_depth = 8; } /* if (bit_depth < 8) png_set_packing(png_ptr); */ // No idea why this is needed... png_set_bgr(png_ptr); // Convert palette to RGB if (color_type == PNG_COLOR_TYPE_PALETTE) { printfdf("(\"%s\"): Converting palette PNG to RGB.", path); png_set_palette_to_rgb(png_ptr); color_type = PNG_COLOR_TYPE_RGB; } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { printfdf("(\"%s\"): Converting rDNS to full alpha.", path); png_set_tRNS_to_alpha(png_ptr); } if (color_type == PNG_COLOR_TYPE_GRAY || PNG_COLOR_TYPE_GRAY_ALPHA == color_type) { printfdf("(\"%s\"): Converting gray (+ alpha) PNG to RGB.", path); png_set_gray_to_rgb(png_ptr); if (PNG_COLOR_TYPE_GRAY == color_type) color_type = PNG_COLOR_TYPE_RGB; else color_type = PNG_COLOR_TYPE_RGB_ALPHA; } /* if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { printfdf("(\"%s\"): Converting 1/2/4 bit gray PNG to 8-bit.", path); #if PNG_LIBPNG_VER >= 10209 png_set_expand_gray_1_2_4_to_8(png_ptr); #else png_set_gray_1_2_4_to_8(png_ptr); #endif bit_depth = 8; } */ // Somehow XImage requires 24-bit visual to use 32 bits per pixel if (color_type == PNG_COLOR_TYPE_RGB) { printfdf("(\"%s\"): Appending filler alpha values.", path); png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); } // Premultiply alpha if (PNG_COLOR_TYPE_RGB_ALPHA == color_type) { #if PNG_LIBPNG_VER >= 10504 png_set_alpha_mode(png_ptr, PNG_ALPHA_STANDARD, 1.0); #else need_premultiply = true; #endif } /* int number_passes = 1; #ifdef PNG_READ_INTERLACING_SUPPORTED number_passes = png_set_interlace_handling(png_ptr); #endif */ if (PNG_INTERLACE_NONE != interlace_type) png_set_interlace_handling(png_ptr); } png_read_update_info(png_ptr, info_ptr); int depth = 0; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); switch (color_type) { case PNG_COLOR_TYPE_GRAY: depth = 1 * bit_depth; break; case PNG_COLOR_TYPE_RGB: depth = 3 * bit_depth; break; case PNG_COLOR_TYPE_RGB_ALPHA: depth = 4 * bit_depth; break; default: assert(0); break; } // Read data and fill to Picture { int rowbytes = png_get_rowbytes(png_ptr, info_ptr); png_bytep row_pointers[height]; memset(row_pointers, 0, sizeof(row_pointers)); row_pointers[0] = png_malloc(png_ptr, rowbytes * height); for (int row = 1; row < height; row++) row_pointers[row] = row_pointers[row - 1] + rowbytes; png_read_image(png_ptr, row_pointers); if (need_premultiply) for (int row = 0; row < height; row++) simg_data32_premultiply(row_pointers[row], width); if (unlikely(!(pictw = simg_data_to_pictw(ps, width, height, depth, row_pointers[0], rowbytes)))) { printfef("(\"%s\"): Failed to create Picture.", path); goto spng_read_end; } } spng_read_end: if (png_ptr) png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (fp) fclose(fp); return pictw; }
int loadpng (char *file_name, int *w, int *h, unsigned int ***buf) { FILE *fp; png_uint_32 width, height; int bit_depth, color_type, interlace_type, compression_type, filter_type; int rowbytes; png_structp png_ptr; png_infop info_ptr; png_infop end_info; int x, y; unsigned int **row_pointers; /* OUVERTURE DU FICHIER */ fp = fopen (file_name, "rb"); if (!fp) { // fprintf (stderr, "Couldn't open file\n"); return 1; } /* CREATION DES STRUCTURES */ png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, (png_voidp) NULL, NULL, NULL); if (!png_ptr) { fprintf (stderr, "Memory error\n"); return 1; } info_ptr = png_create_info_struct (png_ptr); if (!info_ptr) { png_destroy_read_struct (&png_ptr, (png_infopp) NULL, (png_infopp) NULL); fprintf (stderr, "Read error 1\n"); return 1; } end_info = png_create_info_struct (png_ptr); if (!end_info) { png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL); fprintf (stderr, "Read error 2\n"); return 1; } /* CHARGEMENT DE L'IMAGE */ if (setjmp (png_ptr->jmpbuf)) { png_destroy_read_struct (&png_ptr, &info_ptr, &end_info); fclose (fp); fprintf (stderr, "Erreur de chargement\n"); return 1; } png_init_io (png_ptr, fp); png_set_read_status_fn (png_ptr, NULL); png_read_info (png_ptr, info_ptr); png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type); /* printf ("taille : %dx%d\n",width,height); printf ("depth : %d\n",bit_depth); printf ("color type : "); switch (color_type) { case PNG_COLOR_TYPE_GRAY: printf ("PNG_COLOR_TYPE_GRAY (bit depths 1, 2, 4, 8, 16)\n"); break; case PNG_COLOR_TYPE_GRAY_ALPHA: printf ("PNG_COLOR_TYPE_GRAY_ALPHA (bit depths 8, 16)\n"); break; case PNG_COLOR_TYPE_PALETTE: printf ("PNG_COLOR_TYPE_PALETTE (bit depths 1, 2, 4, 8)\n"); break; case PNG_COLOR_TYPE_RGB: printf ("PNG_COLOR_TYPE_RGB (bit_depths 8, 16)\n"); break; case PNG_COLOR_TYPE_RGB_ALPHA: printf ("PNG_COLOR_TYPE_RGB_ALPHA (bit_depths 8, 16)\n"); break; } */ // printf ("PNG_COLOR_MASK_ALPHA : %x\n", PNG_COLOR_MASK_ALPHA); // printf ("PNG_COLOR_MASK_COLOR : %x\n", PNG_COLOR_MASK_COLOR); // printf ("PNG_COLOR_MASK_PALETTE : %x\n", PNG_COLOR_MASK_PALETTE); if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) png_set_palette_to_rgb (png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8 (png_ptr); else if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb (png_ptr); if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha (png_ptr); png_read_update_info (png_ptr, info_ptr); // printf ("channels : %d\n", png_get_channels (png_ptr, info_ptr)); rowbytes = png_get_rowbytes (png_ptr, info_ptr); // printf ("rowbytes : %d\n", rowbytes); row_pointers = (unsigned int **) malloc (height * sizeof (unsigned int *)); for (y = 0; y < height; y++) row_pointers[y] = (unsigned int *) malloc (4 * width); png_read_image (png_ptr, (png_bytepp) row_pointers); // for (y=0;y<height;y++) { // for (x=0;x<width;x++) { // if (row_pointers[y][x] & 0xf000) // printf ("%x ",(((unsigned int**)row_pointers)[y][x])&0xf); // else // printf (" "); // } // printf ("\n"); // } png_read_end (png_ptr, end_info); png_destroy_read_struct (&png_ptr, &info_ptr, &end_info); (*buf) = (unsigned int **) malloc (height * sizeof (void *)); for (y = 0; y < height; y++) { (*buf)[y] = (unsigned int *) malloc (width * 4); for (x = 0; x < width; x++) (*buf)[y][x] = row_pointers[y][x]; } *w = width; *h = height; return 0; }
TextureReturn png_texture_load(const char * file_name, int * width, int * height) { // This function was originally written by David Grayson for // https://github.com/DavidEGrayson/ahrs-visualizer png_byte header[8]; FILE *fp = fopen(file_name, "rb"); if (fp == 0) { perror(file_name); return TextureReturn(); } // read the header fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) { fprintf(stderr, "error: %s is not a PNG.\n", file_name); fclose(fp); return TextureReturn(); } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fprintf(stderr, "error: png_create_read_struct returned 0.\n"); fclose(fp); return TextureReturn(); } // create png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fclose(fp); return TextureReturn(); } // create png info struct png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); fclose(fp); return TextureReturn(); } // the code in this if statement gets called if libpng encounters an error if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "error from libpng\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return TextureReturn(); } // init png reading png_init_io(png_ptr, fp); // let libpng know you already read the first 8 bytes png_set_sig_bytes(png_ptr, 8); // read all the info up to the image data png_read_info(png_ptr, info_ptr); // variables to pass to get info int bit_depth, color_type; png_uint_32 temp_width, temp_height; // get info about png png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type, NULL, NULL, NULL); if (width){ *width = temp_width; } if (height){ *height = temp_height; } //printf("%s: %lux%lu %d\n", file_name, temp_width, temp_height, color_type); if (bit_depth != 8) { fprintf(stderr, "%s: Unsupported bit depth %d. Must be 8.\n", file_name, bit_depth); return TextureReturn(); } GLint format; switch(color_type) { case PNG_COLOR_TYPE_RGB: format = GL_RGB; break; case PNG_COLOR_TYPE_RGB_ALPHA: format = GL_RGBA; break; default: fprintf(stderr, "%s: Unknown libpng color type %d.\n", file_name, color_type); return TextureReturn(); } // Update the png info struct. png_read_update_info(png_ptr, info_ptr); // Row size in bytes. int rowbytes = png_get_rowbytes(png_ptr, info_ptr); // glTexImage2d requires rows to be 4-byte aligned rowbytes += 3 - ((rowbytes-1) % 4); // Allocate the image_data as a big block, to be given to opengl png_byte * image_data = (png_byte *)malloc(rowbytes * temp_height * sizeof(png_byte)+15); if (image_data == NULL) { fprintf(stderr, "error: could not allocate memory for PNG image data\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return TextureReturn(); } // row_pointers is for pointing to image_data for reading the png with libpng png_byte ** row_pointers = (png_byte **)malloc(temp_height * sizeof(png_byte *)); if (row_pointers == NULL) { fprintf(stderr, "error: could not allocate memory for PNG row pointers\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); free(image_data); fclose(fp); return TextureReturn(); } // set the individual row_pointers to point at the correct offsets of image_data for (unsigned int i = 0; i < temp_height; i++) { row_pointers[temp_height - 1 - i] = image_data + i * rowbytes; } // read the png into image_data through row_pointers png_read_image(png_ptr, row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); *width = temp_width; *height = temp_height; TextureReturn thing; thing.format = format; thing.pixels = image_data; return thing;/* // Generate the OpenGL texture object GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, format, temp_width, temp_height, 0, format, GL_UNSIGNED_BYTE, image_data); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // clean up free(row_pointers); return texture;*/ }
int image_png_load(MediaScanImage *i) { int bit_depth, color_type, num_passes, x, y; int ofs; volatile unsigned char *ptr = NULL; // volatile = won't be rolled back if longjmp is called PNGData *p = (PNGData *)i->_png; if (setjmp(png_jmpbuf(p->png_ptr))) { if (ptr != NULL) free((void *)ptr); image_png_destroy(i); return 0; } // XXX If reusing the object a second time, we need to completely create a new png struct bit_depth = png_get_bit_depth(p->png_ptr, p->info_ptr); color_type = png_get_color_type(p->png_ptr, p->info_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_expand(p->png_ptr); // png_set_palette_to_rgb(p->png_ptr); i->channels = 4; } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand(p->png_ptr); // png_set_expand_gray_1_2_4_to_8(p->png_ptr); else if (png_get_valid(p->png_ptr, p->info_ptr, PNG_INFO_tRNS)) png_set_expand(p->png_ptr); // png_set_tRNS_to_alpha(p->png_ptr); if (bit_depth == 16) png_set_strip_16(p->png_ptr); else if (bit_depth < 8) png_set_packing(p->png_ptr); // Make non-alpha RGB/Palette 32-bit and Gray 16-bit for easier handling if (!(color_type & PNG_COLOR_MASK_ALPHA)) { png_set_add_alpha(p->png_ptr, 0xFF, PNG_FILLER_AFTER); } num_passes = png_set_interlace_handling(p->png_ptr); LOG_DEBUG("png bit_depth %d, color_type %d, channels %d, num_passes %d\n", bit_depth, color_type, i->channels, num_passes); png_read_update_info(p->png_ptr, p->info_ptr); image_alloc_pixbuf(i, i->width, i->height); ptr = (unsigned char *)malloc(png_get_rowbytes(p->png_ptr, p->info_ptr)); ofs = 0; if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { // Grayscale (Alpha) if (num_passes == 1) { // Non-interlaced for (y = 0; y < i->height; y++) { png_read_row(p->png_ptr, (unsigned char *)ptr, NULL); for (x = 0; x < i->width; x++) { i->_pixbuf[ofs++] = COL_FULL(ptr[x * 2], ptr[x * 2], ptr[x * 2], ptr[x * 2 + 1]); } } } else if (num_passes == 7) { // Interlaced image_png_interlace_pass_gray(i, (unsigned char *)ptr, 0, 8, 0, 8); image_png_interlace_pass_gray(i, (unsigned char *)ptr, 0, 8, 4, 8); image_png_interlace_pass_gray(i, (unsigned char *)ptr, 4, 8, 0, 4); image_png_interlace_pass_gray(i, (unsigned char *)ptr, 0, 4, 2, 4); image_png_interlace_pass_gray(i, (unsigned char *)ptr, 2, 4, 0, 2); image_png_interlace_pass_gray(i, (unsigned char *)ptr, 0, 2, 1, 2); image_png_interlace_pass_gray(i, (unsigned char *)ptr, 1, 2, 0, 1); } } else { // RGB(A) if (num_passes == 1) { // Non-interlaced for (y = 0; y < i->height; y++) { png_read_row(p->png_ptr, (unsigned char *)ptr, NULL); for (x = 0; x < i->width; x++) { i->_pixbuf[ofs++] = COL_FULL(ptr[x * 4], ptr[x * 4 + 1], ptr[x * 4 + 2], ptr[x * 4 + 3]); } } } else if (num_passes == 7) { // Interlaced // The first pass will return an image 1/8 as wide as the entire image // (every 8th column starting in column 0) // and 1/8 as high as the original (every 8th row starting in row 0) image_png_interlace_pass(i, (unsigned char *)ptr, 0, 8, 0, 8); // The second will be 1/8 as wide (starting in column 4) // and 1/8 as high (also starting in row 0) image_png_interlace_pass(i, (unsigned char *)ptr, 0, 8, 4, 8); // The third pass will be 1/4 as wide (every 4th pixel starting in column 0) // and 1/8 as high (every 8th row starting in row 4) image_png_interlace_pass(i, (unsigned char *)ptr, 4, 8, 0, 4); // The fourth pass will be 1/4 as wide and 1/4 as high // (every 4th column starting in column 2, and every 4th row starting in row 0) image_png_interlace_pass(i, (unsigned char *)ptr, 0, 4, 2, 4); // The fifth pass will return an image 1/2 as wide, // and 1/4 as high (starting at column 0 and row 2) image_png_interlace_pass(i, (unsigned char *)ptr, 2, 4, 0, 2); // The sixth pass will be 1/2 as wide and 1/2 as high as the original // (starting in column 1 and row 0) image_png_interlace_pass(i, (unsigned char *)ptr, 0, 2, 1, 2); // The seventh pass will be as wide as the original, and 1/2 as high, // containing all of the odd numbered scanlines. image_png_interlace_pass(i, (unsigned char *)ptr, 1, 2, 0, 1); } else { FATAL("Unsupported PNG interlace type (%d passes)\n", num_passes); } } free((void *)ptr); // This is not required, so we can save some time by not reading post-image chunks //png_read_end(p->png_ptr, p->info_ptr); return 1; }
int APIENTRY pngLoadRawF(FILE *fp, pngRawInfo *pinfo) { unsigned char header[8]; png_structp png; png_infop info; png_infop endinfo; png_bytep data; png_bytep *row_p; double fileGamma; png_uint_32 width, height; int depth, color; png_uint_32 i; if (pinfo == NULL) return 0; fread(header, 1, 8, fp); if (!png_check_sig(header, 8)) return 0; png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info = png_create_info_struct(png); endinfo = png_create_info_struct(png); // DH: added following lines if (setjmp(png->jmpbuf)) { png_destroy_read_struct(&png, &info, &endinfo); return 0; } // ~DH png_init_io(png, fp); png_set_sig_bytes(png, 8); png_read_info(png, info); png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); pinfo->Width = width; pinfo->Height = height; pinfo->Depth = depth; /*--GAMMA--*/ checkForGammaEnv(); if (png_get_gAMA(png, info, &fileGamma)) png_set_gamma(png, screenGamma, fileGamma); else png_set_gamma(png, screenGamma, 1.0/2.2); png_read_update_info(png, info); data = (png_bytep) malloc(png_get_rowbytes(png, info)*height); row_p = (png_bytep *) malloc(sizeof(png_bytep)*height); for (i = 0; i < height; i++) { if (StandardOrientation) row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i]; else row_p[i] = &data[png_get_rowbytes(png, info)*i]; } png_read_image(png, row_p); free(row_p); if (color == PNG_COLOR_TYPE_PALETTE) { int cols; png_get_PLTE(png, info, (png_colorp *) &pinfo->Palette, &cols); } else { pinfo->Palette = NULL; } if (color&PNG_COLOR_MASK_ALPHA) { if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY_ALPHA) pinfo->Components = 2; else pinfo->Components = 4; pinfo->Alpha = 8; } else { if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY) pinfo->Components = 1; else pinfo->Components = 3; pinfo->Alpha = 0; } pinfo->Data = data; png_read_end(png, endinfo); png_destroy_read_struct(&png, &info, &endinfo); return 1; }
/** * @brief Gets the pitch of a png. */ int npng_pitch( npng_t *npng ) { /* Make sure loaded info. */ return png_get_rowbytes( npng->png_ptr, npng->info_ptr ); }
void PngReader::read(unsigned x0, unsigned y0,ImageData32& image) { FILE *fp=fopen(fileName_.c_str(),"r"); if (!fp) throw ImageReaderException("cannot open image file "+fileName_); png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { fclose(fp); throw ImageReaderException("failed to allocate png_ptr"); } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr,0,0); fclose(fp); throw ImageReaderException("failed to create info_ptr"); } png_init_io(png_ptr, fp); png_read_info(png_ptr, info_ptr); if (color_type_ == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); if (color_type_ == PNG_COLOR_TYPE_GRAY && bit_depth_ < 8) png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); if (bit_depth_ == 16) png_set_strip_16(png_ptr); if (color_type_ == PNG_COLOR_TYPE_GRAY || color_type_ == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); // quick hack -- only work in >=libpng 1.2.7 png_set_add_alpha(png_ptr,1,1); double gamma; if (png_get_gAMA(png_ptr, info_ptr, &gamma)) png_set_gamma(png_ptr, 2.2, gamma); png_read_update_info(png_ptr, info_ptr); //START read image rows unsigned w=std::min((unsigned)image.width(),width_); unsigned h=std::min((unsigned)image.height(),height_); unsigned rowbytes=png_get_rowbytes(png_ptr, info_ptr); unsigned char* row= new unsigned char[rowbytes]; for (unsigned i=0; i<height_; ++i) { png_read_row(png_ptr,row,0); if (i>=y0 && i<h) { image.setRow(i-y0,(unsigned*) &row[x0],w); } } //END delete [] row; png_read_end(png_ptr,0); png_destroy_read_struct(&png_ptr, &info_ptr,0); fclose(fp); }
uint8_t* ImageDecoder::decodePNGImpl(png_structp pngPtr, uint32_t* width, uint32_t* height, bool* hasAlpha) { png_bytep* rowPtrs = NULL; uint8_t* outData = NULL; png_infop infoPtr = png_create_info_struct(pngPtr); if (!infoPtr) { LOG(LOG_ERROR,"Couldn't initialize png info struct"); png_destroy_read_struct(&pngPtr, (png_infopp)0, (png_infopp)0); return NULL; } if (setjmp(png_jmpbuf(pngPtr))) { png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0); if (rowPtrs != NULL) delete [] rowPtrs; if (outData != NULL) delete [] outData; LOG(LOG_ERROR,"error during reading of the png file"); return NULL; } png_read_info(pngPtr, infoPtr); *width = png_get_image_width(pngPtr, infoPtr); *height = png_get_image_height(pngPtr, infoPtr); //bits per CHANNEL! note: not per pixel! png_uint_32 bitdepth = png_get_bit_depth(pngPtr, infoPtr); //Number of channels png_uint_32 channels = png_get_channels(pngPtr, infoPtr); //Color type. (RGB, RGBA, Luminance, luminance alpha... palette... etc) png_uint_32 color_type = png_get_color_type(pngPtr, infoPtr); // Transform everything into 24 bit RGB switch (color_type) { case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(pngPtr); break; case PNG_COLOR_TYPE_GRAY: if (bitdepth < 8) png_set_gray_to_rgb(pngPtr); break; } if (bitdepth == 16) { png_set_strip_16(pngPtr); } *hasAlpha = (channels > 3); // Update the infoPtr to reflect the transformations set // above. Read new values by calling png_get_* again. png_read_update_info(pngPtr, infoPtr); //bitdepth = png_get_bit_depth(pngPtr, infoPtr); //color_type = png_get_color_type(pngPtr, infoPtr); const unsigned int stride = png_get_rowbytes(pngPtr, infoPtr); outData = new uint8_t[(*height) * stride]; rowPtrs = new png_bytep[(*height)]; for (size_t i = 0; i < (*height); i++) { rowPtrs[i] = (png_bytep)outData + i* stride; } png_read_image(pngPtr, rowPtrs); png_read_end(pngPtr, NULL); png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0); delete[] (png_bytep)rowPtrs; return outData; }
char* Model::load_png(std::string fileName, int *width, int *height) { fileName = "Resources/" + fileName; FILE *png_file = fopen(fileName.c_str(), "rb"); //assert(png_file.open); uint8_t header[PNG_SIG_BYTES]; fread(header, 1, PNG_SIG_BYTES, png_file); assert(!png_sig_cmp(header, 0, PNG_SIG_BYTES)); png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); assert(png_ptr); png_infop info_ptr = png_create_info_struct(png_ptr); assert(info_ptr); png_infop end_info = png_create_info_struct(png_ptr); assert(end_info); assert(!setjmp(png_jmpbuf(png_ptr))); png_init_io(png_ptr, png_file); png_set_sig_bytes(png_ptr, PNG_SIG_BYTES); png_read_info(png_ptr, info_ptr); *width = png_get_image_width(png_ptr, info_ptr); *height = png_get_image_height(png_ptr, info_ptr); png_uint_32 bit_depth, color_type; bit_depth = png_get_bit_depth(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); // if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) // png_set_gray_1_2_4_to_8(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); else if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); else png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); png_read_update_info(png_ptr, info_ptr); png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr); png_uint_32 numbytes = rowbytes * (*height); png_byte* pixels = (png_byte*) malloc(numbytes); png_byte** row_ptrs = (png_byte**) malloc((*height) * sizeof (png_byte*)); int i; for (i = 0; i < (*height); i++) row_ptrs[i] = pixels + ((*height) - 1 - i) * rowbytes; png_read_image(png_ptr, row_ptrs); free(row_ptrs); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(png_file); return (char *) pixels; }
unsigned char* LoadPNGJPGFromMemory(const unsigned char* buffer, int len, int* width, int* height) { const int number=8; // проверяем сигнатуру файла (первые number байт) if ( !png_check_sig((png_bytep)buffer, number) ) { // неизвестный формат return LoadJPGWithAlphaFromMemory(buffer, len, width, height); } // создаем внутреннюю структуру png для работы с файлом // последние параметры - структура, для функции обработки ошибок и варнинга (последн. 2 параметра) png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); // создаем структуру с информацией о файле png_infop info_ptr = png_create_info_struct(png_ptr); PNGBuffer pngBuffer; pngBuffer.data = (png_bytep)buffer; pngBuffer.position = 8; png_set_read_fn(png_ptr, (void*)&pngBuffer, PNGRead); // говорим библиотеке, что мы уже прочли number байт, когда проверяли сигнатуру png_set_sig_bytes(png_ptr, number); // читаем всю информацию о файле png_read_info(png_ptr, info_ptr); // Эта функция возвращает инфу из info_ptr png_uint_32 w = 0, h = 0; // размер картинки в пикселях int bit_depth = 0; // глубина цвета (одного из каналов, может быть 1, 2, 4, 8, 16) int color_type = 0; // описывает какие каналы присутствуют: // PNG_COLOR_TYPE_GRAY, PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, // PNG_COLOR_TYPE_RGB, PNG_COLOR_TYPE_RGB_ALPHA... // последние 3 параметра могут быть нулями и обозначают: тип фильтра, тип компрессии и тип смещения png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, 0, 0, 0); // png формат может содержать 16 бит на канал, но нам нужно только 8, поэтому сужаем канал if (bit_depth == 16) png_set_strip_16(png_ptr); // преобразуем файл если он содержит палитру в нормальный RGB if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) png_set_palette_to_rgb(png_ptr); // если в грэйскейле меньше бит на канал чем 8, то конвертим к нормальному 8-битному //if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr); // и добавляем полный альфа-канал if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); double gamma = 0.0f; // если есть информация о гамме в файле, то устанавливаем на 2.2 if ( png_get_gAMA(png_ptr, info_ptr, &gamma) ) png_set_gamma(png_ptr, 2.2, gamma); // иначе ставим дефолтную гамму для файла в 0.45455 (good guess for GIF images on PCs) else png_set_gamma(png_ptr, 2.2, 0.45455); // после всех трансформаций, апдейтим информацию в библиотеке png_read_update_info(png_ptr, info_ptr); // опять получаем все размеры и параметры обновленной картинки png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, 0, 0, 0); // определяем кол-во байт нужных для того чтобы вместить строку png_uint_32 row_bytes = png_get_rowbytes(png_ptr, info_ptr); // теперь, мы можем выделить память чтобы вместить картинку png_byte* data = new png_byte[row_bytes * h]; // выделяем память, для указателей на каждую строку png_byte **row_pointers = new png_byte * [h]; // сопоставляем массив указателей на строчки, с выделенными в памяти (res) // т.к. изображение перевернутое, то указатели идут снизу вверх for (unsigned int i = 0; i < h; i++) row_pointers[i] = data + i * row_bytes; // все, читаем картинку png_read_image(png_ptr, row_pointers); // освобождаем память от указателей на строки delete []row_pointers; // освобождаем память выделенную для библиотеки libpng png_destroy_read_struct(&png_ptr, &info_ptr, 0); *width=w; *height=h; return data; }
/* ReadPNG - Reads the contents of a PNG file and stores the contents into BMGImageStruct Inputs: filename - the name of the file to be opened Outputs: img - the BMGImageStruct containing the image data Returns: BMGError - if the file could not be read or a resource error occurred BMG_OK - if the file was read and the data was stored in img Limitations: None. Comments: 2-bit images are converted to 4-bit images. 16-bit images are converted to 8-bit images. gray scale images with alpha components are converted to 32-bit images */ BMGError ReadPNG( const char *filename, struct BMGImageStruct * volatile img ) { jmp_buf err_jmp; int error; FILE * volatile file = NULL; int BitDepth; int ColorType; int InterlaceType; unsigned char signature[8]; png_structp volatile png_ptr = NULL; png_infop volatile info_ptr = NULL; png_infop volatile end_info = NULL; png_color_16 *ImageBackground = NULL; png_bytep trns = NULL; int NumTrans = 0; int i, k; png_color_16p TransColors = NULL; png_uint_32 Width, Height; unsigned char *bits; unsigned char** volatile rows = NULL; BMGError tmp; /* error handler */ error = setjmp( err_jmp ); if (error != 0) { if (end_info != NULL) png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info); else if (info_ptr != NULL) png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, NULL); else if (png_ptr != NULL) png_destroy_read_struct((png_structp *) &png_ptr, NULL, NULL); if (rows) { if (rows[0]) free(rows[0]); free(rows); } if (img) FreeBMGImage(img); if (file) fclose(file); SetLastBMGError((BMGError) error); return (BMGError) error; } if ( img == NULL ) longjmp ( err_jmp, (int)errInvalidBMGImage ); file = fopen( filename, "rb" ); if ( !file || fread( signature, 1, 8, file ) != 8) longjmp ( err_jmp, (int)errFileOpen ); /* check the signature */ if ( png_sig_cmp( signature, 0, 8 ) != 0 ) longjmp( err_jmp, (int)errUnsupportedFileFormat ); /* create a pointer to the png read structure */ png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); if ( !png_ptr ) longjmp( err_jmp, (int)errMemoryAllocation ); /* create a pointer to the png info structure */ info_ptr = png_create_info_struct( png_ptr ); if ( !info_ptr ) longjmp( err_jmp, (int)errMemoryAllocation ); /* create a pointer to the png end-info structure */ end_info = png_create_info_struct(png_ptr); if (!end_info) longjmp( err_jmp, (int)errMemoryAllocation ); /* bamboozle the PNG longjmp buffer */ /*generic PNG error handler*/ /* error will always == 1 which == errLib */ // error = png_setjmp(png_ptr); error = setjmp( png_jmpbuf( png_ptr ) ); if ( error > 0 ) longjmp( err_jmp, error ); /* set function pointers in the PNG library, for read callbacks */ png_set_read_fn(png_ptr, (png_voidp) file, user_read_data); /*let the read functions know that we have already read the 1st 8 bytes */ png_set_sig_bytes( png_ptr, 8 ); /* read all PNG data up to the image data */ png_read_info( png_ptr, info_ptr ); /* extract the data we need to form the HBITMAP from the PNG header */ png_get_IHDR( png_ptr, info_ptr, &Width, &Height, &BitDepth, &ColorType, &InterlaceType, NULL, NULL); img->width = (unsigned int) Width; img->height = (unsigned int) Height; img->bits_per_pixel = (unsigned char)32; img->scan_width = Width * 4; /* convert 16-bit images to 8-bit images */ if (BitDepth == 16) png_set_strip_16(png_ptr); /* These are not really required per Rice format spec, * but is done just in case someone uses them. */ /* convert palette color to rgb color */ if (ColorType == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); ColorType = PNG_COLOR_TYPE_RGB; } /* expand 1,2,4 bit gray scale to 8 bit gray scale */ if (ColorType == PNG_COLOR_TYPE_GRAY && BitDepth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); /* convert gray scale or gray scale + alpha to rgb color */ if (ColorType == PNG_COLOR_TYPE_GRAY || ColorType == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); ColorType = PNG_COLOR_TYPE_RGB; } /* add alpha channel if any */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); ColorType = PNG_COLOR_TYPE_RGB_ALPHA; } /* convert rgb to rgba */ if (ColorType == PNG_COLOR_TYPE_RGB) { png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); ColorType = PNG_COLOR_TYPE_RGB_ALPHA; } png_set_bgr(png_ptr); /* set the background color if one is found */ if ( png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD) ) png_get_bKGD(png_ptr, info_ptr, &ImageBackground); /* get the transparent color if one is there */ if ( png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS ) ) png_get_tRNS( png_ptr, info_ptr, &trns, &NumTrans, &TransColors ); img->palette_size = (unsigned short)0; img->bytes_per_palette_entry = 4U; tmp = AllocateBMGImage( img ); if ( tmp != BMG_OK ) longjmp( err_jmp, (int)tmp ); png_read_update_info( png_ptr, info_ptr ); /* create buffer to read data to */ rows = (unsigned char **)malloc(Height*sizeof(unsigned char *)); if ( !rows ) longjmp( err_jmp, (int)errMemoryAllocation ); k = png_get_rowbytes( png_ptr, info_ptr ); rows[0] = (unsigned char *)malloc( Height*k*sizeof(char)); if ( !rows[0] ) longjmp( err_jmp, (int)errMemoryAllocation ); for ( i = 1; i < (int)Height; i++ ) rows[i] = rows[i-1] + k; /* read the entire image into rows */ png_read_image( png_ptr, rows ); bits = img->bits + (Height - 1) * img->scan_width; for ( i = 0; i < (int)Height; i++ ) { memcpy(bits, rows[i], 4*Width); bits -= img->scan_width; } free( rows[0] ); free( rows ); png_read_end( png_ptr, info_ptr ); png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info); fclose( file ); return BMG_OK; }
int PngDecoder::validate() { if (png_sig_cmp((png_bytep)buf->data(), 0, PNG_HEADER_SIZE)) { std::cout << "[PngDecoder] error: %s is not a PNG." << std::endl; return -1; } buf->drain(PNG_HEADER_SIZE); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { std::cout << "[PngDecoder] error: png_create_read_struct returned 0." << std::endl; return -1; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { std::cout << "[PngDecoder] error: png_create_info_struct returned 0." << std::endl; png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return -1; } end_info = png_create_info_struct(png_ptr); if (!end_info) { std::cout << "[PngDecoder] error: png_create_info_struct returned 0." << std::endl; png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); return -1; } if (setjmp(png_jmpbuf(png_ptr))) { std::cout << "[PngDecoder] error from libpng" << std::endl; png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return -1; } png_set_read_fn(png_ptr, buf, pngDecoderReadFunction); png_set_sig_bytes(png_ptr, PNG_HEADER_SIZE); png_read_info(png_ptr, info_ptr); png_set_expand(png_ptr); png_set_strip_16(png_ptr); png_set_gray_to_rgb(png_ptr); png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER); png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); imgInfo.width = png_get_image_width(png_ptr, info_ptr); imgInfo.height = png_get_image_height(png_ptr, info_ptr); imgInfo.color_type = png_get_color_type(png_ptr, info_ptr); imgInfo.channels = png_get_channels(png_ptr, info_ptr); imgInfo.bit_depth = png_get_bit_depth(png_ptr, info_ptr); imgInfo.interlance_type = png_get_interlace_type(png_ptr, info_ptr); imgInfo.rowbytes = png_get_rowbytes(png_ptr, info_ptr); #ifdef _PNGDECODER_DEBUG std::cout << "[PngDecoder] Extracted w=" << imgInfo.width << " h=" << imgInfo.height << " color_type=" << imgInfo.color_type << " bit_depth="<< imgInfo.bit_depth << " rowbytes="<< imgInfo.rowbytes << " channels="<< imgInfo.channels << " interlance_type="<< imgInfo.interlance_type << std::endl; #endif if (imgInfo.bit_depth != 8) { std::cout << "[PngDecoder] error: Unsupported bit depth=" << imgInfo.bit_depth <<". Must be 8." << std::endl; return -1; } switch(imgInfo.color_type) { case PNG_COLOR_TYPE_RGB: imgInfo.format = GL_RGB; break; case PNG_COLOR_TYPE_RGB_ALPHA: imgInfo.format = GL_RGBA; break; case PNG_COLOR_TYPE_PALETTE: if (imgInfo.color_type & PNG_COLOR_MASK_ALPHA) { imgInfo.format = GL_RGBA; } else if (imgInfo.color_type & PNG_COLOR_MASK_COLOR) { imgInfo.format = GL_RGB; } break; default: std::cout << "[PngDecoder] error: unknown libpng color type=" << imgInfo.color_type << " rgb=" << PNG_COLOR_TYPE_RGB << " rgba=" << PNG_COLOR_TYPE_RGBA << " palette=" << PNG_COLOR_TYPE_PALETTE << std::endl; return -1; } return 0; }
int fh_png_load(const char *name,unsigned char **buffer,int* /*xp*/,int* /*yp*/) { static const png_color_16 my_background = {0, 0, 0, 0, 0}; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; unsigned int i; int bit_depth, color_type, interlace_type; int number_passes,pass; png_byte * fbptr; FILE * fh; if(!(fh=fopen(name,"rb"))) return(FH_ERROR_FILE); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); if(png_ptr == NULL) { fclose(fh); return(FH_ERROR_FORMAT); } info_ptr = png_create_info_struct(png_ptr); if(info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fclose(fh); return(FH_ERROR_FORMAT); } if(setjmp(png_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fh); return(FH_ERROR_FORMAT); } png_init_io(png_ptr,fh); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,&interlace_type, NULL, NULL); if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); png_set_background(png_ptr, (png_color_16*)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); /* other possibility for png_set_background: use png_get_bKGD */ } if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); png_set_background(png_ptr, (png_color_16*)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); } /* this test does not trigger for 8bit-paletted PNGs with newer libpng (1.2.36 at least), but the data delivered is with alpha channel anyway, so always strip alpha for now */ #if PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR <= 2 && PNG_LIBPNG_VER_RELEASE < 36 if (color_type & PNG_COLOR_MASK_ALPHA) #endif png_set_strip_alpha(png_ptr); if (bit_depth < 8) png_set_packing(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); /* on Intel PC ?: if (bit_depth == 16) png_set_swap(png_ptr); */ number_passes = png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr,info_ptr); if (width * 3 != png_get_rowbytes(png_ptr, info_ptr)) { printf("[png.cpp]: Error processing %s - please report (including image).\n", name); printf(" width: %lu rowbytes: %lu\n", width, png_get_rowbytes(png_ptr, info_ptr)); fclose(fh); return(FH_ERROR_FORMAT); } for(pass = 0; pass < number_passes; pass++) { fbptr = (png_byte *)(*buffer); for (i = 0; i < height; i++, fbptr += width * 3) { png_read_row(png_ptr, fbptr, NULL); } } png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fh); return(FH_ERROR_OK); }
void save_png_buffer(buffer_t &buf, std::string filename) { png_structp png_ptr; png_infop info_ptr; png_bytep *row_pointers; png_byte color_type; int width, height, channels; width = buf.extent[0]; height = buf.extent[1]; channels = buf.extent[2]; //im.copy_to_host(); _assert(channels > 0 && channels < 5, "Can't write PNG files that have other than 1, 2, 3, or 4 channels\n"); png_byte color_types[4] = {PNG_COLOR_TYPE_GRAY, PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_RGB, PNG_COLOR_TYPE_RGB_ALPHA }; color_type = color_types[channels - 1]; // open file FILE *f = fopen(filename.c_str(), "wb"); _assert(f, "[write_png_file] File %s could not be opened for writing\n", filename.c_str()); // initialize stuff png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); _assert(png_ptr, "[write_png_file] png_create_write_struct failed\n"); info_ptr = png_create_info_struct(png_ptr); _assert(info_ptr, "[write_png_file] png_create_info_struct failed\n"); _assert(!setjmp(png_jmpbuf(png_ptr)), "[write_png_file] Error during init_io\n"); png_init_io(png_ptr, f); unsigned int bit_depth = 16; if (sizeof(uint8_t) == 1) { bit_depth = 8; } // write header _assert(!setjmp(png_jmpbuf(png_ptr)), "[write_png_file] Error during writing header\n"); png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); row_pointers = new png_bytep[height]; // im.copyToHost(); // in case the image is on the gpu int c_stride = (channels == 1) ? 0 : width*height; uint8_t *srcPtr = buf.host; for (int y = 0; y < height; y++) { row_pointers[y] = new png_byte[png_get_rowbytes(png_ptr, info_ptr)]; uint8_t *dstPtr = (uint8_t *)(row_pointers[y]); if (bit_depth == 16) { // convert to uint16_t for (int x = 0; x < width; x++) { for (int c = 0; c < channels; c++) { uint16_t out; convert(srcPtr[c*c_stride], out); *dstPtr++ = out >> 8; *dstPtr++ = out & 0xff; } srcPtr++; } } else if (bit_depth == 8) { // convert to uint8_t for (int x = 0; x < width; x++) { for (int c = 0; c < channels; c++) { uint8_t out; convert(srcPtr[c*c_stride], out); *dstPtr++ = out; } srcPtr++; } } else { _assert(bit_depth == 8 || bit_depth == 16, "We only support saving 8- and 16-bit images."); } }
//int APIENTRY pngLoadRawF(FILE *fp, pngRawInfo *pinfo) { int pngLoadRaw(const char* filename, pngRawInfo *pinfo, vsxf* filesystem) { unsigned char header[8]; png_structp png; png_infop info; png_infop endinfo; png_bytep data; png_bytep *row_p; double fileGamma; vsxf_info i_filesystem; png_uint_32 width, height; int depth, color; png_uint_32 i; if (pinfo == NULL) { printf("error in png loader: pinfo is NULL %d\n",__LINE__); return 0; } i_filesystem.filesystem = filesystem; i_filesystem.fp = filesystem->f_open(filename,"rb"); if (!i_filesystem.fp) { printf("error in png loader: i_filesystem.fp not valid on line %d\n",__LINE__); return 0; } filesystem->f_read(header, 8, i_filesystem.fp); if (!png_check_sig(header, 8)) { printf("error in %s on line %d\n",__FILE__,__LINE__); return 0; } png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) { printf("error in %s on line %d\n",__FILE__,__LINE__); return 0; } info = png_create_info_struct(png); if (!info) { png_destroy_read_struct(&png,(png_infopp)NULL,(png_infopp)NULL); printf("error in %s on line %d\n",__FILE__,__LINE__); return 0; } endinfo = png_create_info_struct(png); if (!endinfo) { png_destroy_read_struct(&png, &info, (png_infopp)NULL); printf("error in %s on line %d\n",__FILE__,__LINE__); return 0; } if (setjmp(png_jmpbuf(png))) { printf("error in png_jmpbuf %s on line %d\n",__FILE__,__LINE__); png_destroy_read_struct(&png, &info,&endinfo); filesystem->f_close(i_filesystem.fp); return 0; } png_set_read_fn(png, (png_bytep)(&i_filesystem), png_vsxf_read_data); png_set_sig_bytes(png, 8); png_read_info(png, info); png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); pinfo->Width = width; pinfo->Height = height; pinfo->Depth = depth; if (color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); if (color == PNG_COLOR_TYPE_PALETTE) png_set_expand(png); /*--GAMMA--*/ checkForGammaEnv(); if (png_get_gAMA(png, info, &fileGamma)) png_set_gamma(png, screenGamma, fileGamma); else png_set_gamma(png, screenGamma, 1.0/2.2); png_read_update_info(png, info); data = (png_bytep) malloc(png_get_rowbytes(png, info)*height); row_p = (png_bytep *) malloc(sizeof(png_bytep)*height); for (i = 0; i < height; i++) { if (StandardOrientation) row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i]; else row_p[i] = &data[png_get_rowbytes(png, info)*i]; } png_read_image(png, row_p); free(row_p); if (color == PNG_COLOR_TYPE_PALETTE) { int cols; png_get_PLTE(png, info, (png_colorp *) &pinfo->Palette, &cols); } else { pinfo->Palette = NULL; } if (color&PNG_COLOR_MASK_ALPHA) { if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY_ALPHA) pinfo->Components = 2; else pinfo->Components = 4; pinfo->Alpha = 8; } else { if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY) pinfo->Components = 1; else pinfo->Components = 3; pinfo->Alpha = 0; } pinfo->Data = data; png_read_end(png, endinfo); png_destroy_read_struct(&png, &info, &endinfo); filesystem->f_close(i_filesystem.fp); return 1; }
void load_png_buffer(std::string filename, buffer_t &buf) { png_byte header[8]; png_structp png_ptr; png_infop info_ptr; png_bytep *row_pointers; /* open file and test for it being a png */ FILE *f = fopen(filename.c_str(), "rb"); _assert(f, "File %s could not be opened for reading\n", filename.c_str()); _assert(fread(header, 1, 8, f) == 8, "File ended before end of header\n"); _assert(!png_sig_cmp(header, 0, 8), "File %s is not recognized as a PNG file\n", filename.c_str()); /* initialize stuff */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); _assert(png_ptr, "png_create_read_struct failed\n"); info_ptr = png_create_info_struct(png_ptr); _assert(info_ptr, "png_create_info_struct failed\n"); _assert(!setjmp(png_jmpbuf(png_ptr)), "Error during init_io\n"); png_init_io(png_ptr, f); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); int width = png_get_image_width(png_ptr, info_ptr); int height = png_get_image_height(png_ptr, info_ptr); int channels = png_get_channels(png_ptr, info_ptr); int bit_depth = png_get_bit_depth(png_ptr, info_ptr); // Expand low-bpp images to have only 1 pixel per byte (As opposed to tight packing) if (bit_depth < 8) { png_set_packing(png_ptr); } if (channels != 1) { buf.extent[0] = width; buf.extent[1] = height; buf.extent[2] = channels; buf.stride[0] = 1; buf.stride[1] = width; buf.stride[2] = width*height; } else { buf.extent[0] = width; buf.extent[1] = height; buf.stride[0] = 1; buf.stride[1] = width; } if (bit_depth == 8) { buf.elem_size = 1; } else { buf.elem_size = 2; } png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); // read the file _assert(!setjmp(png_jmpbuf(png_ptr)), "Error during read_image\n"); row_pointers = new png_bytep[height]; for (int y = 0; y < height; y++) { row_pointers[y] = new png_byte[png_get_rowbytes(png_ptr, info_ptr)]; } png_read_image(png_ptr, row_pointers); fclose(f); _assert((bit_depth == 8) || (bit_depth == 16), "Can only handle 8-bit or 16-bit pngs\n"); // convert the data to uint8_t int c_stride = (channels == 1) ? 0 : width*height; uint8_t *img = (uint8_t*)malloc(width*height*channels*sizeof(uint8_t)); uint8_t *ptr = img; _assert(ptr, "Error alocation memory for buffer."); if (bit_depth == 8) { for (int y = 0; y < height; y++) { uint8_t *srcPtr = (uint8_t *)(row_pointers[y]); for (int x = 0; x < width;x++) { for (int c = 0; c < channels; c++) { convert(*srcPtr++, ptr[c*c_stride]); } ptr++; } } } else if (bit_depth == 16) { for (int y = 0; y < height; y++) { uint8_t *srcPtr = (uint8_t *)(row_pointers[y]); for (int x = 0; x < width; x++) { for (int c = 0; c < channels; c++) { uint16_t hi = (*srcPtr++) << 8; uint16_t lo = hi | (*srcPtr++); convert(lo, ptr[c*c_stride]); } ptr++; } } } // Fill buffer_t buf.host = img; // clean up for (int y = 0; y < height; y++) { delete[] row_pointers[y]; } delete[] row_pointers; png_destroy_read_struct(&png_ptr, &info_ptr, NULL); buf.host_dirty = true; }
int image_png_compress(MediaScanImage *i, MediaScanThumbSpec *spec) { int j, x, y; int color_space = PNG_COLOR_TYPE_RGB_ALPHA; volatile unsigned char *ptr = NULL; png_structp png_ptr; png_infop info_ptr; Buffer *buf; if (!i->_pixbuf_size) { LOG_WARN("PNG compression requires pixbuf data (%s)\n", i->path); return 0; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { FATAL("Could not initialize libpng\n"); } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, NULL); FATAL("Could not initialize libpng\n"); } // Initialize buffer for compressed data buf = (Buffer *)malloc(sizeof(Buffer)); buffer_init(buf, BUF_SIZE); i->_dbuf = (void *)buf; png_set_write_fn(png_ptr, buf, image_png_write_buf, image_png_flush_buf); if (setjmp(png_jmpbuf(png_ptr))) { if (ptr != NULL) free((void *)ptr); return 0; } // Match output color space with input file switch (i->channels) { case 4: case 3: LOG_DEBUG("PNG output color space set to RGBA\n"); color_space = PNG_COLOR_TYPE_RGB_ALPHA; break; case 2: case 1: LOG_DEBUG("PNG output color space set to gray alpha\n"); color_space = PNG_COLOR_TYPE_GRAY_ALPHA; break; } png_set_IHDR(png_ptr, info_ptr, spec->width, spec->height, 8, color_space, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); ptr = (unsigned char *)malloc(png_get_rowbytes(png_ptr, info_ptr)); j = 0; if (color_space == PNG_COLOR_TYPE_GRAY_ALPHA) { for (y = 0; y < spec->height; y++) { for (x = 0; x < spec->width; x++) { ptr[x * 2] = COL_BLUE(i->_pixbuf[j]); ptr[x * 2 + 1] = COL_ALPHA(i->_pixbuf[j]); j++; } png_write_row(png_ptr, (png_bytep) ptr); } } else { // RGB for (y = 0; y < spec->height; y++) { for (x = 0; x < spec->width; x++) { ptr[x * 4] = COL_RED(i->_pixbuf[j]); ptr[x * 4 + 1] = COL_GREEN(i->_pixbuf[j]); ptr[x * 4 + 2] = COL_BLUE(i->_pixbuf[j]); ptr[x * 4 + 3] = COL_ALPHA(i->_pixbuf[j]); j++; } png_write_row(png_ptr, (png_bytep) ptr); } } free((void *)ptr); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; }
void initialize() { // Now it's time for some transformations. if( little_endian() ) { if( this->_info._bit_depth == 16 ) { // Swap bytes of 16 bit files to least significant byte first. png_set_swap( this->get()->_struct ); } if( this->_info._bit_depth < 8 ) { // swap bits of 1, 2, 4 bit packed pixel formats png_set_packswap( this->get()->_struct ); } } if( this->_info._color_type == PNG_COLOR_TYPE_PALETTE ) { png_set_palette_to_rgb( this->get()->_struct ); } if( this->_info._num_trans > 0 ) { png_set_tRNS_to_alpha( this->get()->_struct ); } // Tell libpng to handle the gamma conversion for you. The final call // is a good guess for PC generated images, but it should be configurable // by the user at run time by the user. It is strongly suggested that // your application support gamma correction. if( this->_settings._apply_screen_gamma ) { // png_set_gamma will change the image data! #ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED png_set_gamma( this->get()->_struct , this->_settings._screen_gamma , this->_info._file_gamma ); #else png_set_gamma( this->get()->_struct , this->_settings._screen_gamma , this->_info._file_gamma ); #endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED } // Interlaced images are not supported. this->_number_passes = png_set_interlace_handling( this->get()->_struct ); io_error_if( this->_number_passes != 1 , "scanline_read_iterator cannot read interlaced png images." ); // The above transformation might have changed the bit_depth and color type. png_read_update_info( this->get()->_struct , this->get()->_info ); this->_info._bit_depth = png_get_bit_depth( this->get()->_struct , this->get()->_info ); this->_info._num_channels = png_get_channels( this->get()->_struct , this->get()->_info ); this->_info._color_type = png_get_color_type( this->get()->_struct , this->get()->_info ); this->_scanline_length = png_get_rowbytes( this->get()->_struct , this->get()->_info ); }
int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) { GLint pack, unpack; unsigned char header[8]; png_structp png; png_infop info; png_infop endinfo; png_bytep data, data2; png_bytep *row_p; double fileGamma; png_uint_32 width, height, rw, rh; int depth, color; png_uint_32 i; fread(header, 1, 8, fp); if (!png_check_sig(header, 8)) return 0; png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info = png_create_info_struct(png); endinfo = png_create_info_struct(png); // DH: added following lines if (setjmp(png->jmpbuf)) { png_destroy_read_struct(&png, &info, &endinfo); return 0; } // ~DH png_init_io(png, fp); png_set_sig_bytes(png, 8); png_read_info(png, info); png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); if (pinfo != NULL) { pinfo->Width = width; pinfo->Height = height; pinfo->Depth = depth; } if (MaxTextureSize == 0) glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTextureSize); #ifdef SUPPORTS_PALETTE_EXT #ifdef _WIN32 if (PalettedTextures == -1) PalettedTextures = ExtSupported("GL_EXT_paletted_texture") && (strstr((const char *) glGetString(GL_VERSION), "1.1.0 3Dfx Beta") == NULL); if (PalettedTextures) { if (glColorTableEXT == NULL) { glColorTableEXT = (PFNGLCOLORTABLEEXTPROC) wglGetProcAddress("glColorTableEXT"); if (glColorTableEXT == NULL) PalettedTextures = 0; } } #endif #endif if (PalettedTextures == -1) PalettedTextures = 0; if (color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); if (color&PNG_COLOR_MASK_ALPHA && trans != PNG_ALPHA) { png_set_strip_alpha(png); color &= ~PNG_COLOR_MASK_ALPHA; } if (!(PalettedTextures && mipmap >= 0 && trans == PNG_SOLID)) if (color == PNG_COLOR_TYPE_PALETTE) png_set_expand(png); /*--GAMMA--*/ checkForGammaEnv(); if (png_get_gAMA(png, info, &fileGamma)) png_set_gamma(png, screenGamma, fileGamma); else png_set_gamma(png, screenGamma, 1.0/2.2); png_read_update_info(png, info); data = (png_bytep) malloc(png_get_rowbytes(png, info)*height); row_p = (png_bytep *) malloc(sizeof(png_bytep)*height); for (i = 0; i < height; i++) { if (StandardOrientation) row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i]; else row_p[i] = &data[png_get_rowbytes(png, info)*i]; } png_read_image(png, row_p); free(row_p); rw = SafeSize(width), rh = SafeSize(height); if (rw != width || rh != height) { const int channels = png_get_rowbytes(png, info)/width; data2 = (png_bytep) malloc(rw*rh*channels); /* Doesn't work on certain sizes */ /* if (gluScaleImage(glformat, width, height, GL_UNSIGNED_BYTE, data, rw, rh, GL_UNSIGNED_BYTE, data2) != 0) return 0; */ Resize(channels, data, width, height, data2, rw, rh); width = rw, height = rh; free(data); data = data2; } { /* OpenGL stuff */ glGetIntegerv(GL_PACK_ALIGNMENT, &pack); glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack); glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); #ifdef SUPPORTS_PALETTE_EXT if (PalettedTextures && mipmap >= 0 && trans == PNG_SOLID && color == PNG_COLOR_TYPE_PALETTE) { png_colorp pal; int cols; GLint intf; if (pinfo != NULL) pinfo->Alpha = 0; png_get_PLTE(png, info, &pal, &cols); switch (cols) { case 1<<1: intf = GL_COLOR_INDEX1_EXT; break; case 1<<2: intf = GL_COLOR_INDEX2_EXT; break; case 1<<4: intf = GL_COLOR_INDEX4_EXT; break; case 1<<8: intf = GL_COLOR_INDEX8_EXT; break; case 1<<12: intf = GL_COLOR_INDEX12_EXT; break; case 1<<16: intf = GL_COLOR_INDEX16_EXT; break; default: /*printf("Warning: Colour depth %i not recognised\n", cols);*/ return 0; } glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, cols, GL_RGB, GL_UNSIGNED_BYTE, pal); glTexImage2D(GL_TEXTURE_2D, mipmap, intf, width, height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data); } else #endif if (trans == PNG_SOLID || trans == PNG_ALPHA || color == PNG_COLOR_TYPE_RGB_ALPHA || color == PNG_COLOR_TYPE_GRAY_ALPHA) { GLenum glformat; GLint glcomponent; switch (color) { case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_PALETTE: glformat = GL_RGB; glcomponent = 3; if (pinfo != NULL) pinfo->Alpha = 0; break; case PNG_COLOR_TYPE_GRAY_ALPHA: case PNG_COLOR_TYPE_RGB_ALPHA: glformat = GL_RGBA; glcomponent = 4; if (pinfo != NULL) pinfo->Alpha = 8; break; default: /*puts("glformat not set");*/ return 0; } if (mipmap == PNG_BUILDMIPMAPS) Build2DMipmaps(glcomponent, width, height, glformat, data, 1); else if (mipmap == PNG_SIMPLEMIPMAPS) Build2DMipmaps(glcomponent, width, height, glformat, data, 0); else glTexImage2D(GL_TEXTURE_2D, mipmap, glcomponent, width, height, 0, glformat, GL_UNSIGNED_BYTE, data); } else { png_bytep p, endp, q; int r, g, b, a; p = data, endp = p+width*height*3; q = data2 = (png_bytep) malloc(sizeof(png_byte)*width*height*4); if (pinfo != NULL) pinfo->Alpha = 8; #define FORSTART \ do { \ r = *p++; /*red */ \ g = *p++; /*green*/ \ b = *p++; /*blue */ \ *q++ = r; \ *q++ = g; \ *q++ = b; #define FOREND \ q++; \ } while (p != endp); #define ALPHA *q switch (trans) { case PNG_CALLBACK: FORSTART ALPHA = AlphaCallback((unsigned char) r, (unsigned char) g, (unsigned char) b); FOREND break; case PNG_STENCIL: FORSTART if (r == StencilRed && g == StencilGreen && b == StencilBlue) ALPHA = 0; else ALPHA = 255; FOREND break; case PNG_BLEND1: FORSTART a = r+g+b; if (a > 255) ALPHA = 255; else ALPHA = a; FOREND break; case PNG_BLEND2: FORSTART a = r+g+b; if (a > 255*2) ALPHA = 255; else ALPHA = a/2; FOREND break; case PNG_BLEND3: FORSTART ALPHA = (r+g+b)/3; FOREND break; case PNG_BLEND4: FORSTART a = r*r+g*g+b*b; if (a > 255) ALPHA = 255; else ALPHA = a; FOREND break; case PNG_BLEND5: FORSTART a = r*r+g*g+b*b; if (a > 255*2) ALPHA = 255; else ALPHA = a/2; FOREND break; case PNG_BLEND6: FORSTART a = r*r+g*g+b*b; if (a > 255*3) ALPHA = 255; else ALPHA = a/3; FOREND break; case PNG_BLEND7: FORSTART a = r*r+g*g+b*b; if (a > 255*255) ALPHA = 255; else ALPHA = (int) sqrt(a); FOREND break; } #undef FORSTART #undef FOREND #undef ALPHA if (mipmap == PNG_BUILDMIPMAPS) Build2DMipmaps(4, width, height, GL_RGBA, data2, 1); else if (mipmap == PNG_SIMPLEMIPMAPS) Build2DMipmaps(4, width, height, GL_RGBA, data2, 0); else glTexImage2D(GL_TEXTURE_2D, mipmap, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2); free(data2); } glPixelStorei(GL_PACK_ALIGNMENT, pack); glPixelStorei(GL_UNPACK_ALIGNMENT, unpack); } /* OpenGL end */ png_read_end(png, endinfo); png_destroy_read_struct(&png, &info, &endinfo); free(data); return 1; }
bool PNGDecoder::LoadFile(const std::string &filename, DecodedFrames &frames) { png_byte header[8]; RGBAImage *ret = NULL; CFile fp; if (!fp.Open(filename)) { perror(filename.c_str()); return false; } // read the header fp.Read(header, 8); if (png_sig_cmp(header, 0, 8)) { fprintf(stderr, "error: %s is not a PNG.\n", filename.c_str()); return false; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fprintf(stderr, "error: png_create_read_struct returned 0.\n"); return false; } // create png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return false; } // create png info struct png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); return false; } // the code in this if statement gets called if libpng encounters an error if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "error from libpng\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return false; } // init png reading png_init_io(png_ptr, fp.getFP()); // let libpng know you already read the first 8 bytes png_set_sig_bytes(png_ptr, 8); // read all the info up to the image data png_read_info(png_ptr, info_ptr); // variables to pass to get info int bit_depth, color_type; png_uint_32 temp_width, temp_height; // get info about png png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type, NULL, NULL, NULL); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); } //set it to 32bit pixeldepth png_color_8 sig_bit; sig_bit.red = 32; sig_bit.green = 32; sig_bit.blue = 32; // if the image has an alpha channel then sig_bit.alpha = 32; png_set_sBIT(png_ptr, info_ptr, &sig_bit); /* Add filler (or alpha) byte (before/after each RGB triplet) */ png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) png_set_bgr(png_ptr); /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ //png_set_swap_alpha(png_ptr); // Update the png info struct. png_read_update_info(png_ptr, info_ptr); // Row size in bytes. int rowbytes = png_get_rowbytes(png_ptr, info_ptr); // glTexImage2d requires rows to be 4-byte aligned // rowbytes += 3 - ((rowbytes-1) % 4); // Allocate the image_data as a big block, to be given to opengl png_byte * image_data; image_data = (png_byte*)new png_byte[rowbytes * temp_height * sizeof(png_byte)+15]; if (image_data == NULL) { fprintf(stderr, "error: could not allocate memory for PNG image data\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return false; } // row_pointers is for pointing to image_data for reading the png with libpng png_bytep * row_pointers = (png_bytep*) new png_bytep[temp_height * sizeof(png_bytep)]; if (row_pointers == NULL) { fprintf(stderr, "error: could not allocate memory for PNG row pointers\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete [] image_data; return false; } // set the individual row_pointers to point at the correct offsets of image_data for (unsigned int i = 0; i < temp_height; i++) { row_pointers[i] = image_data + i * rowbytes; } // read the png into image_data through row_pointers png_read_image(png_ptr, row_pointers); frames.user = NULL; DecodedFrame frame; frame.rgbaImage.pixels = (char *)image_data; frame.rgbaImage.height = temp_height; frame.rgbaImage.width = temp_width; frame.rgbaImage.bbp = 32; frame.rgbaImage.pitch = 4 * temp_width; frames.frameList.push_back(frame); // clean up png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete [] row_pointers; return true; }
pdf_obj *start_png_image (FILE *file, char *res_name) { pdf_obj *result = NULL, *dict = NULL; png_structp png_ptr; png_infop info_ptr; unsigned long width, height; unsigned bit_depth, color_type; rewind (file); if (!(png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) || !(info_ptr = png_create_info_struct (png_ptr))) { fprintf (stderr, "\n\nLibpng failed to initialize\n"); if (png_ptr) png_destroy_read_struct(&png_ptr, NULL, NULL); return NULL; } png_init_io (png_ptr, file); /* png_set_sig_bytes (png_ptr, 0); */ /* Read PNG header */ png_read_info (png_ptr, info_ptr); { png_color_16 default_background; png_color_16p file_background; default_background.red=255; default_background.green=255; default_background.blue=255; default_background.gray=0; default_background.index = 0; width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); /* Convert paletted images to true color */ if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_expand(png_ptr); } /* Limit image component depth to 8 bits */ if (bit_depth == 16) { png_set_strip_16 (png_ptr); } if (png_get_bKGD(png_ptr, info_ptr, &file_background)) { png_set_background(png_ptr, file_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); } else { png_set_background(png_ptr, &default_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); } } { /* Read the image in raw RGB format */ int i, rowbytes, pdf_bit_depth; png_bytep *rows; png_read_update_info(png_ptr, info_ptr); rows = NEW (height, png_bytep); rowbytes = png_get_rowbytes(png_ptr, info_ptr); rows[0] = NEW (rowbytes*height, png_byte); for (i=1; i<height; i++) { rows[i] = rows[0] + rowbytes * i; } png_read_image(png_ptr, rows); result = pdf_new_stream(STREAM_COMPRESS); dict = pdf_stream_dict(result); pdf_add_dict (dict, pdf_new_name ("Width"), pdf_new_number(width)); pdf_add_dict (dict, pdf_new_name ("Height"), pdf_new_number(height)); if (color_type == PNG_COLOR_TYPE_GRAY) { pdf_bit_depth = bit_depth; } else { pdf_bit_depth = 8; } pdf_add_dict (dict, pdf_new_name ("BitsPerComponent"), pdf_new_number(pdf_bit_depth)); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { pdf_add_dict (dict, pdf_new_name ("ColorSpace"), pdf_new_name ("DeviceGray")); } else{ pdf_add_dict (dict, pdf_new_name ("ColorSpace"), pdf_new_name ("DeviceRGB")); } pdf_add_stream (result, (char *)rows[0], rowbytes*height); RELEASE (rows[0]); RELEASE (rows); } { /* Cleanup */ if (info_ptr) png_destroy_info_struct(png_ptr, &info_ptr); if (png_ptr) png_destroy_read_struct(&png_ptr, NULL, NULL); } return result; }
void png_reader::read(unsigned x0, unsigned y0,image_data_32& image) { FILE *fp=fopen(fileName_.c_str(),"rb"); if (!fp) throw image_reader_exception("cannot open image file "+fileName_); png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { fclose(fp); throw image_reader_exception("failed to allocate png_ptr"); } // catch errors in a custom way to avoid the need for setjmp png_set_error_fn(png_ptr, png_get_error_ptr(png_ptr), user_error_fn, user_warning_fn); png_infop info_ptr; try { info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr,0,0); fclose(fp); throw image_reader_exception("failed to create info_ptr"); } } catch (std::exception const& ex) { png_destroy_read_struct(&png_ptr,0,0); fclose(fp); throw; } png_set_read_fn(png_ptr, (png_voidp)fp, png_read_data); png_read_info(png_ptr, info_ptr); if (color_type_ == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); if (color_type_ == PNG_COLOR_TYPE_GRAY && bit_depth_ < 8) png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); if (bit_depth_ == 16) png_set_strip_16(png_ptr); if (color_type_ == PNG_COLOR_TYPE_GRAY || color_type_ == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); // quick hack -- only work in >=libpng 1.2.7 png_set_add_alpha(png_ptr,0xff,PNG_FILLER_AFTER); //rgba double gamma; if (png_get_gAMA(png_ptr, info_ptr, &gamma)) png_set_gamma(png_ptr, 2.2, gamma); if (x0 == 0 && y0 == 0 && image.width() >= width_ && image.height() >= height_) { if (png_get_interlace_type(png_ptr,info_ptr) == PNG_INTERLACE_ADAM7) { png_set_interlace_handling(png_ptr); // FIXME: libpng bug? // according to docs png_read_image // "..automatically handles interlacing, // so you don't need to call png_set_interlace_handling()" } png_read_update_info(png_ptr, info_ptr); // we can read whole image at once // alloc row pointers boost::scoped_array<png_byte*> rows(new png_bytep[height_]); for (unsigned i=0; i<height_; ++i) rows[i] = (png_bytep)image.getRow(i); png_read_image(png_ptr, rows.get()); } else { png_read_update_info(png_ptr, info_ptr); unsigned w=std::min(unsigned(image.width()),width_); unsigned h=std::min(unsigned(image.height()),height_); unsigned rowbytes=png_get_rowbytes(png_ptr, info_ptr); boost::scoped_array<png_byte> row(new png_byte[rowbytes]); //START read image rows for (unsigned i=0;i<height_;++i) { png_read_row(png_ptr,row.get(),0); if (i>=y0 && i<h) { image.setRow(i-y0,reinterpret_cast<unsigned*>(&row[x0]),w); } } //END } png_read_end(png_ptr,0); png_destroy_read_struct(&png_ptr, &info_ptr,0); fclose(fp); }
bool Texture::load2DPNG(const char *name, bool genMIPs) { ASSERT(name); png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int32_t bit_depth, color_type, stride; uint8_t *buffer, *data; png_bytep *row_pointers; uint32_t size; GLint internalFormat; GLenum format; if (!VFS::load(name, VFS_BINARY, &buffer, &size)) return false; if (size <= 8) { LOG_ERROR("Too small PNG file '%s'\n", name); delete[] buffer; return false; } if (png_sig_cmp((png_byte *)buffer, 0, 8)) { LOG_ERROR("Wrong PNG format '%s'\n", name); delete[] buffer; return false; } if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, PNGError, NULL)) == NULL) { LOG_ERROR("Failed to create PNG read struct\n"); delete[] buffer; return false; } if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) { LOG_ERROR("Failed to create PNG info struct\n"); png_destroy_read_struct(&png_ptr, NULL, NULL); delete[] buffer; return false; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); delete[] buffer; return false; } png_set_read_fn(png_ptr, (void *)(buffer + 8), PNGRead); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); png_set_strip_16(png_ptr); png_set_packing(png_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); //if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) // png_set_gray_to_rgb(png_ptr); png_read_update_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); switch (color_type) { case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_GRAY_ALPHA: internalFormat = GL_R8; format = GL_RED; break; case PNG_COLOR_TYPE_RGB: internalFormat = GL_RGB8; format = GL_RGB; break; case PNG_COLOR_TYPE_RGBA: internalFormat = GL_RGBA8; format = GL_RGBA; break; default: LOG_ERROR("Unknown PNG color type %d in '%s'\n", color_type, name); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); delete[] buffer; return false; } stride = png_get_rowbytes(png_ptr, info_ptr); row_pointers = new png_bytep[height]; ASSERT(row_pointers); data = new uint8_t[height * stride]; ASSERT(data); for (uint32_t i = 0; i < height; ++i) row_pointers[i] = (png_bytep)data + i * stride; png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); delete[] row_pointers; delete[] buffer; image2D(GL_PVOID(data), width, height, internalFormat, format, GL_UNSIGNED_BYTE, genMIPs); delete[] data; return true; }
/** Reads one PNG file. @param process Process the image data (0 for initial parameter determination) @returns -1 on failure, 1 on sucess */ int decode_png(const char *pngname, int process, parameters_t *param) { int num_pass = 1; int bit_depth, color_type; FILE *pngfile; //png_byte hdptr[8]; /* Now open this PNG file, and examine its header to retrieve the YUV4MPEG info that shall be written */ pngfile = fopen(pngname, "rb"); if (!pngfile) { perror("PNG file open failed:"); return -1; } //fread(hdptr, 1, 8, pngfile); #if 0 bool is_png = !png_sig_cmp(hdptr, 0, 8); if (!is_png) { mjpeg_error("%s is _no_ PNG file !\n"); return -1; } #endif png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) mjpeg_error_exit1("%s: Could not allocate PNG read struct !", pngname); png_init_io(png_ptr, pngfile); //png_set_sig_bytes(png_ptr, 8); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); mjpeg_error_exit1("%s: Could not allocate PNG info struct !", pngname); } end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); mjpeg_error_exit1("%s: Could not allocate PNG end info struct !", pngname); } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); mjpeg_error("%s: Corrupted PNG file !", pngname); return -1; } if (process) png_set_read_user_transform_fn(png_ptr, png_separation); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_STRIP_ALPHA, NULL); if (png_get_IHDR(png_ptr, info_ptr, ¶m->width, ¶m->height, &bit_depth, // &color_type, &interlace_type, &compression_type, &filter_type)) &color_type, NULL, NULL, NULL)) num_pass = png_set_interlace_handling(png_ptr); else mjpeg_error_exit1("PNG header reading failed !!\n"); #if 0 mjpeg_info("Reading info struct...\n"); png_read_info(png_ptr, info_ptr); mjpeg_info("Done...\n"); if (png_get_IHDR(png_ptr, info_ptr, ¶m->width, ¶m->height, &bit_depth, // &color_type, &interlace_type, &compression_type, &filter_type)) &color_type, NULL, NULL, NULL)) num_pass = png_set_interlace_handling(png_ptr); else mjpeg_error_exit1("PNG header reading failed !!\n"); if (process) { printf("%d passes needed\n\n", num_pass); if (bit_depth != 8 && bit_depth != 16) { mjpeg_error_exit1("Invalid bit_depth %d, only 8 and 16 bit allowed !!\n", bit_depth); } png_set_strip_16(png_ptr); // always has to strip the 16bit input, MPEG can't handle it png_set_strip_alpha(png_ptr); // Alpha can't be processed until Z/Alpha is integrated printf("\nAllocating row buffer..."); png_set_read_user_transform_fn(png_ptr, png_separation); png_bytep row_buf = (png_bytep)png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); for (int n=0; n < num_pass; n++) for (int y=0; y < sh_param->height; y++) { printf("Writing row data for pass %d\n", n); png_read_rows(png_ptr, (png_bytepp)&row_buf, NULL, 1); } png_free(png_ptr, row_buf); } png_read_end(png_ptr, info_ptr); #endif if (setjmp(png_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return 2; } fclose(pngfile); return 1; }
color_image_t * color_image_png_load( FILE* fp, const char* file_name ) { // read the header png_byte header[8]; fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) { err_printf( "error: %s is not a PNG.\n", file_name); fclose(fp); return 0; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { err_printf( "error: png_create_read_struct returned 0.\n"); fclose(fp); return 0; } // create png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { err_printf( "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fclose(fp); return 0; } // create png info struct png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { err_printf( "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); fclose(fp); return 0; } // the code in this if statement gets called if libpng encounters an error if (setjmp(png_jmpbuf(png_ptr))) { err_printf( "error from libpng\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return 0; } // init png reading png_init_io(png_ptr, fp); // let libpng know you already read the first 8 bytes png_set_sig_bytes(png_ptr, 8); // read all the info up to the image data png_read_info(png_ptr, info_ptr); // variables to pass to get info int bit_depth, color_type; png_uint_32 temp_width, temp_height; // get info about png png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type, NULL, NULL, NULL); // Update the png info struct. png_read_update_info(png_ptr, info_ptr); // Row size in bytes. int rowbytes = png_get_rowbytes(png_ptr, info_ptr); // Allocate the image_data as a big block, to be given to opengl png_byte * image_data; image_data = NEWA(png_byte, rowbytes * temp_height); assert(image_data!=NULL); // row_pointers is for pointing to image_data for reading the png with libpng png_bytep * row_pointers = NEWA(png_bytep, temp_height); assert(row_pointers!=NULL); // set the individual row_pointers to point at the correct offsets of image_data unsigned int i; for (i = 0; i <temp_height; i++) row_pointers[i] = image_data + i * rowbytes; // read the png into image_data through row_pointers png_read_image(png_ptr, row_pointers); // copy into color image color_image_t* image = color_image_new(temp_width,temp_height); if( color_type==0 ) { assert((unsigned)rowbytes == temp_width || !"error: not a proper gray png image"); for(i=0; i<temp_width*temp_height; i++) image->c1[i] = image->c2[i] = image->c3[i] = image_data[i]; } else if( color_type == 2 ) { assert((unsigned)rowbytes == 3*temp_width || !"error: not a proper color png image"); for(i=0; i<temp_width*temp_height; i++) { image->c1[i] = image_data[3*i+0]; image->c2[i] = image_data[3*i+1]; image->c3[i] = image_data[3*i+2]; } } else assert(!"error: unknown PNG color type" ); // clean up png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); free(row_pointers); free(image_data); return image; }
unsigned char *sdlgl_load_png_file(const char *filename, int *image_w, int *image_h) { /* -AJA- all these volatiles here may seem strange. They are needed * because the ANSI C standard (which GCC adheres to) says that when * setjmp/longjmp is being used, only volatile local variables are * guaranteed to keep their state if longjmp() gets called. */ FILE * volatile fp = NULL; unsigned char * volatile image_dat = NULL; png_bytep * volatile row_pointers = NULL; /* we take the address of these two, so we shouldn't need the * volatile. (GCC complains about discarding qualifiers if the * volatile is there). */ png_structp /*volatile*/ png_ptr = NULL; png_infop /*volatile*/ info_ptr = NULL; char sig_buf[CHECK_PNG_BYTES]; png_uint_32 width, height; int bit_depth, color_type, interlace_type; int row, stride; /* open the prospective PNG file */ #ifdef FILE_AREAS fp = fopen_datafile_area(FILE_AREA_SHARE, filename, RDBMODE, FALSE); #else fp = fopen_datafile(filename, RDBMODE, FALSE); #endif if (!fp) { sdlgl_warning("Failed to open file: %s\n", filename); return NULL; } /* read in some of the signature bytes */ if (fread(sig_buf, 1, CHECK_PNG_BYTES, fp) != CHECK_PNG_BYTES) { sdlgl_warning("Failed to read from file: %s\n", filename); goto failed; } /* compare the first CHECK_PNG_BYTES bytes of the signature */ if (png_sig_cmp(sig_buf, (png_size_t)0, CHECK_PNG_BYTES) != 0) { sdlgl_warning("File is not a PNG file: %s\n", filename); goto failed; } /* pass NULLs for the error functions -- thus use the setjump stuff */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { sdlgl_warning("Problem within LibPNG (no memory ?)\n"); goto failed; } /* allocate/initialize the memory for image information */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { sdlgl_warning("Out of memory with LibPNG\n"); goto failed; } /* set error handling since we are using the setjmp/longjmp method * (this is the normal method of doing things with libpng). */ if (setjmp(png_ptr->jmpbuf)) { sdlgl_warning("Problem within LibPNG (unknown)\n"); goto failed; } /* set up the input control since we're using standard C streams */ png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, CHECK_PNG_BYTES); /* the call to png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk) */ png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); *image_w = (int)width; *image_h = (int)height; /* tell libpng to strip 16 bit/color down to 8 bits/color */ png_set_strip_16(png_ptr); /* expand paletted colors into true RGB triplets */ if (color_type == PNG_COLOR_TYPE_PALETTE || color_type == PNG_COLOR_TYPE_GRAY || png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_expand(png_ptr); } /* set alpha position and filler value */ png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); /* let all the above calls take effect */ png_read_update_info(png_ptr, info_ptr); /* allocate the memory for the image */ stride = png_get_rowbytes(png_ptr, info_ptr); image_dat = (unsigned char *) alloc(height * stride); row_pointers = (png_bytep *) alloc(height * sizeof(png_bytep)); for (row=0; row < height; row++) { row_pointers[row] = image_dat + row * stride; } /* now read in the image. Yeah baby ! */ png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, info_ptr); /* free stuff & close the file */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); free(row_pointers); fclose(fp); return image_dat; /* -AJA- Normally I don't like gotos. In this situation where there * are lots of points of possible failure and a growing set of * things to be undone, it makes for nicer code. */ failed: if (image_dat) free(image_dat); if (png_ptr) { /* assume NULLs not allowed (png docs don't say, bad bad) */ if (info_ptr) png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); else png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); } if (row_pointers) free(row_pointers); if (fp) fclose(fp); return NULL; }
bool imagePNG( void const *inData, // input unsigned long inSize, // input void const *&pixData, // output unsigned short &width, // output unsigned short &height, // output void const *&alpha ) // output : 0 if none, delete [] when done { pixData = alpha = 0 ; width = height = 0 ; png_bytep pngData = (png_bytep)inData ; unsigned const pngLength = inSize ; if( 8 < pngLength ) { if( 0 == png_sig_cmp( pngData, 0, pngLength ) ) { png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ); { if( png_ptr ) { png_infop info_ptr = png_create_info_struct(png_ptr); if( info_ptr ) { png_infop end_info = png_create_info_struct(png_ptr); if( end_info ) { if( 0 == setjmp( png_jmpbuf( png_ptr ) ) ) { pngData_t pngFile ; pngFile.data_ = pngData ; pngFile.length_ = pngLength ; png_set_read_fn( png_ptr, &pngFile, pngRead ); png_read_info(png_ptr, info_ptr); #ifdef __STANDALONE__ dumpPNGInfo( info_ptr ); #endif int interlace_type, compression_type, filter_type; png_uint_32 lWidth, lHeight; int bit_depth, color_type; png_get_IHDR( png_ptr, info_ptr, &lWidth, &lHeight, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type); if( PNG_COLOR_MASK_PALETTE == ( PNG_COLOR_MASK_PALETTE & color_type ) ) png_set_palette_to_rgb( png_ptr ); png_read_update_info(png_ptr, info_ptr); png_bytep *const row_pointers = new png_bytep[lHeight]; unsigned const rowBytes = png_get_rowbytes( png_ptr, info_ptr ); for( unsigned row = 0; row < lHeight; row++ ) { row_pointers[row] = (png_bytep)png_malloc( png_ptr, rowBytes ); } png_read_image( png_ptr, row_pointers ); width = (unsigned short)lWidth ; height = (unsigned short)lHeight ; fbDevice_t &fb = getFB(); unsigned char *const alphaChannel = ( color_type & PNG_COLOR_MASK_ALPHA ) ? new unsigned char [ width*height ] : 0 ; unsigned short *const pixMap = new unsigned short [ width*height ]; for( unsigned row = 0 ; row < height ; row++ ) { unsigned char const *imgRow = row_pointers[row]; for( unsigned column = 0 ; column < width ; column++, imgRow += info_ptr->channels ) { pixMap[row*width+column] = fb.get16( imgRow[0], imgRow[1], imgRow[2] ); if( alphaChannel ) alphaChannel[row*width+column] = imgRow[3]; } } pixData = pixMap ; alpha = alphaChannel ; for( unsigned row = 0; row < lHeight ; row++ ) png_free( png_ptr, row_pointers[row] ); delete [] row_pointers ; } else fprintf( stderr, "Internal PNG error\n" ); png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ); } } else png_destroy_read_struct( &png_ptr, 0, 0 ); } } } else fprintf( stderr, "Not a PNG file\n" ); } else fprintf( stderr, "PNG too short!\n" ); return 0 != pixData ; }
bool ossimPngReader::initReader() { bool result = true; ossim_uint32 height = png_get_image_height(m_pngReadPtr, m_pngReadInfoPtr); ossim_uint32 width = png_get_image_width(m_pngReadPtr, m_pngReadInfoPtr); m_bitDepth = png_get_bit_depth(m_pngReadPtr, m_pngReadInfoPtr); m_pngColorType = png_get_color_type(m_pngReadPtr, m_pngReadInfoPtr); m_imageRect = ossimIrect(0, 0, width - 1, height - 1); if (m_bitDepth == 16) { // png_set_strip_16 (m_pngReadPtr); m_bytePerPixelPerBand = 2; m_outputScalarType = OSSIM_UINT16; } else { m_bytePerPixelPerBand = 1; } // Set the read mode from scalar and color type. if (m_outputScalarType == OSSIM_UINT8) { if ( (m_pngColorType == PNG_COLOR_TYPE_RGB_ALPHA) || (m_pngColorType == PNG_COLOR_TYPE_GRAY_ALPHA) ) { m_readMode = ossimPngRead8a; } else { m_readMode = ossimPngRead8; } } else { if ( (m_pngColorType == PNG_COLOR_TYPE_RGB_ALPHA) || (m_pngColorType == PNG_COLOR_TYPE_GRAY_ALPHA) ) { m_readMode = ossimPngRead16a; } else { m_readMode = ossimPngRead16; } // Set the swap flag. PNG stores data in network byte order(big endian). if(ossim::byteOrder() == OSSIM_LITTLE_ENDIAN) { m_swapFlag = true; } } //--- // If png_set_expand used: // Expand data to 24-bit RGB, or 8-bit grayscale, // with alpha if available. //--- bool expandFlag = false; if ( m_pngColorType == PNG_COLOR_TYPE_PALETTE ) { expandFlag = true; } if ( (m_pngColorType == PNG_COLOR_TYPE_GRAY) && (m_bitDepth < 8) ) { expandFlag = true; } if ( png_get_valid(m_pngReadPtr, m_pngReadInfoPtr, PNG_INFO_tRNS) ) { expandFlag = true; } //--- // If png_set_packing used: // Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ //--- bool packingFlag = false; if ( (m_bitDepth < 8) && (m_pngColorType == PNG_COLOR_TYPE_GRAY) ) { packingFlag = true; } if (expandFlag) { png_set_expand(m_pngReadPtr); } if (packingFlag) { png_set_packing(m_pngReadPtr); } // Gamma correction. // ossim_float64 gamma; // if (png_get_gAMA(m_pngReadPtr, m_pngReadInfoPtr, &gamma)) // { // png_set_gamma(png_ptr, display_exponent, gamma); // } //--- // Turn on interlace handling... libpng returns just 1 (ie single pass) // if the image is not interlaced //--- m_interlacePasses = png_set_interlace_handling (m_pngReadPtr); //--- // Update the info structures after the transformations take effect //--- png_read_update_info (m_pngReadPtr, m_pngReadInfoPtr); // TODO: // Add check for image offsets. // Add check for resolution. // Add check for colormap. switch (m_pngColorType) { case PNG_COLOR_TYPE_RGB: /* RGB */ { m_numberOfInputBands = 3; m_numberOfOutputBands = 3; break; } case PNG_COLOR_TYPE_RGB_ALPHA: /* RGBA */ { m_numberOfInputBands = 4; if (m_useAlphaChannelFlag) { m_numberOfOutputBands = 4; } else { m_numberOfOutputBands = 3; } break; } case PNG_COLOR_TYPE_GRAY: /* Grayscale */ { m_numberOfInputBands = 1; m_numberOfOutputBands = 1; break; } case PNG_COLOR_TYPE_GRAY_ALPHA: /* Grayscale + alpha */ { m_numberOfInputBands = 2; if (m_useAlphaChannelFlag) { m_numberOfOutputBands = 2; } else { m_numberOfOutputBands = 1; } break; } case PNG_COLOR_TYPE_PALETTE: /* Indexed */ { m_numberOfInputBands = 3; m_numberOfOutputBands = 3; break; } default: /* Unknown type */ { result = false; } } if ( result ) { m_lineBufferSizeInBytes = png_get_rowbytes(m_pngReadPtr, m_pngReadInfoPtr); // Set the max pixel value. setMaxPixelValue(); // Set to OSSIM_USHORT11 for use of specialized tile. if (m_maxPixelValue[0] == 2047.0) { m_outputScalarType = OSSIM_USHORT11; } // We're on row 0 or first line. m_currentRow = 0; if (traceDebug()) { ossimNotify(ossimNotifyLevel_DEBUG) << "ossimPngReader::initReader DEBUG:" << "\nm_imageRect: " << m_imageRect << "\nm_bitDepth: " << int(m_bitDepth) << "\nm_pngColorType: " << getPngColorTypeString().c_str() << "\nm_numberOfInputBands: " << m_numberOfInputBands << "\nm_numberOfOutputBands: " << m_numberOfOutputBands << "\nm_bytePerPixelPerBand: " << m_bytePerPixelPerBand << "\nm_lineBufferSizeInBytes: " << m_lineBufferSizeInBytes << "\nm_interlacePasses: " << m_interlacePasses << "\npalette expansion: " << (expandFlag?"on":"off") << "\npacking (1,2,4 bit to one byte): " << (packingFlag?"on":"off") << "\nm_readMode: " << m_readMode << "\nm_swapFlag: " << m_swapFlag << std::endl; for (ossim_uint32 band = 0; band < m_numberOfInputBands; ++band) { ossimNotify(ossimNotifyLevel_DEBUG) << "max[" << band << "]: " << m_maxPixelValue[band] << std::endl; } } } return result; } // End: ossimPngReader::initReader()