int main(int argc, char **argv) { if (argc != 4) { fprintf(stderr, "usage: %s <input.png> <output_basename> <jpeg-quality>\n", *argv); return 1; } const char *infile = argv[1]; const char *outfile = argv[2]; int jpeg_quality = atoi(argv[3]); FILE *fpin = fopen(infile, "rb"); if (!fpin) { perror(infile); return 1; } unsigned char header[8]; fread(header, 1, 8, fpin); if (png_sig_cmp(header, 0, 8)) { fprintf(stderr, "this is not a PNG file\n"); fclose(fpin); return 1; } png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); 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); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fpin); fprintf(stderr, "failed.\n"); return 1; } png_init_io(png_ptr, fpin); png_set_sig_bytes(png_ptr, 8); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0); png_bytep * row_pointers = png_get_rows(png_ptr, info_ptr); png_uint_32 width, height; int bit_depth, color_type; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) { fprintf(stderr, "input PNG must be RGB+Alpha\n"); fclose(fpin); return 1; } if (bit_depth != 8) { fprintf(stderr, "input bit depth must be 8bit!\n"); fclose(fpin); return 1; } printf("png is %ldx%ld\n", width, height); int channels = png_get_channels(png_ptr, info_ptr); if (channels != 4) { fprintf(stderr, "channels must be 4.\n"); fclose(fpin); return 1; } fclose(fpin); /* now write jpeg */ struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW jrow_pointer[1]; FILE *outfp; char filename[strlen(outfile) + 10]; strcpy(filename, outfile); strcat(filename, ".rgb.jpg"); outfp = fopen(filename, "wb"); if (!outfp) { perror(filename); return 1; } cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, outfp); cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, jpeg_quality, 1); jpeg_start_compress(&cinfo, 1); unsigned char *row = malloc(width * 3); while (cinfo.next_scanline < cinfo.image_height) { int x; jrow_pointer[0] = row; unsigned char *source = row_pointers[cinfo.next_scanline]; for (x = 0; x < width; ++x) { row[x * 3 + 0] = source[0]; row[x * 3 + 1] = source[1]; row[x * 3 + 2] = source[2]; source += 4; } jpeg_write_scanlines(&cinfo, jrow_pointer, 1); } jpeg_finish_compress(&cinfo); fclose(outfp); jpeg_destroy_compress(&cinfo); /* and write png */ strcpy(filename, outfile); strcat(filename, ".a.png"); outfp = fopen(filename, "wb"); if (!outfp) { perror(filename); return 1; } png_structp png_ptr_w = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); png_infop info_ptr_w = png_create_info_struct(png_ptr_w); if (setjmp(png_jmpbuf(png_ptr_w))) { png_destroy_write_struct(&png_ptr_w, &info_ptr_w); fclose(outfp); return 1; } png_init_io(png_ptr_w, outfp); png_set_IHDR(png_ptr_w, info_ptr_w, width, height, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* turn RGBA into A, in-place */ int x, y; for (y=0; y < height; ++y) { unsigned char *source = row_pointers[y]; unsigned char *dst = source; for (x=0; x < width; ++x) { *dst++ = source[3]; source += 4; } } png_set_rows(png_ptr_w, info_ptr_w, row_pointers); png_write_png(png_ptr_w, info_ptr_w, PNG_TRANSFORM_IDENTITY, 0); png_write_end(png_ptr_w, info_ptr_w); png_destroy_write_struct(&png_ptr_w, &info_ptr_w); fclose(outfp); return 0; }
bool CGLCG::loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData) { png_structp png_ptr; png_infop info_ptr; unsigned int sig_read = 0; int color_type, interlace_type; FILE *fp; if ((fp = _tfopen(name, TEXT("rb"))) == NULL) return false; /* Create and initialize the png_struct * with the desired error handler * functions. If you want to use the * default stderr and longjump method, * you can supply NULL for the last * three parameters. We also supply the * the compiler header file version, so * that we know if the application * was compiled with a compatible version * of the library. REQUIRED */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fclose(fp); return false; } /* Allocate/initialize the memory * for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return false; } /* Set error handling if you are * using the setjmp/longjmp method * (this is the normal method of * doing things with libpng). * REQUIRED unless you set up * your own error handlers in * the png_create_read_struct() * earlier. */ if (setjmp(png_jmpbuf(png_ptr))) { /* Free all of the memory associated * with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fp); /* If we get here, we had a * problem reading the file */ return false; } /* Set up the output control if * you are using standard C streams */ png_init_io(png_ptr, fp); /* If we have already * read some of the signature */ png_set_sig_bytes(png_ptr, sig_read); /* * If you have enough memory to read * in the entire image at once, and * you need to specify only * transforms that can be controlled * with one of the PNG_TRANSFORM_* * bits (this presently excludes * dithering, filling, setting * background, and doing gamma * adjustment), then you can read the * entire image (including pixels) * into the info structure with this * call * * PNG_TRANSFORM_STRIP_16 | * PNG_TRANSFORM_PACKING forces 8 bit * PNG_TRANSFORM_EXPAND forces to * expand a palette into RGB */ png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, (png_voidp)NULL); outWidth = png_get_image_width(png_ptr, info_ptr); outHeight = png_get_image_height(png_ptr, info_ptr); switch (png_get_color_type(png_ptr, info_ptr)) { case PNG_COLOR_TYPE_RGBA: outHasAlpha = true; break; case PNG_COLOR_TYPE_RGB: outHasAlpha = false; break; default: png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return false; } unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr); *outData = (unsigned char*) malloc(row_bytes * outHeight); png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr); for (int i = 0; i < outHeight; i++) { memcpy(*outData+(row_bytes * i), row_pointers[i], row_bytes); } /* Clean up after the read, * and free any memory allocated */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); /* Close the file */ fclose(fp); /* That's it */ return true; }
void PngLoader::PngLoad(){ int i,j; FILE *fp = fopen(filename,"rb"); png_structp png_sp; png_infop png_ip; if(!fp){ std::cout<<"Cannot open file:"<<filename<<std::endl; return; } png_sp = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); png_ip = png_create_info_struct(png_sp); if(setjmp(png_jmpbuf(png_sp))){ png_destroy_read_struct(&png_sp,&png_ip,NULL); return; } png_init_io(png_sp,fp); png_read_png(png_sp,png_ip,PNG_TRANSFORM_EXPAND,NULL); png_byte** raw_pointers = png_get_rows (png_sp,png_ip); width = 640; height = 480; bpp = 4; raw_data = new unsigned char[width*height*bpp]; for(j = 0; j < height; j++){ for(i = 0; i < width; i++){ //テクスチャにAlpha値を入れる場合 raw_data[j*width*4+(i*4)+0] = raw_pointers[height-j-1][i*3]; raw_data[j*width*4+(i*4)+1] = raw_pointers[height-j-1][i*3+1]; raw_data[j*width*4+(i*4)+2] = raw_pointers[height-j-1][i*3+2]; raw_data[j*width*4+(i*4)+3] = 255; if(raw_data[j*width*4+(i*4)+0] == 255 && raw_data[j*width*4+(i*4)+1] == 255 && raw_data[j*width*4+(i*4)+2] == 255){ raw_data[j*width*4+(i*4)+3] = 0; } /* if(raw_data[j*width*4+(i*4)+0] == 0 && raw_data[j*width*4+(i*4)+1] == 0 && raw_data[j*width*4+(i*4)+2] == 0){ raw_data[j*width*4+(i*4)+3] = 0; } */ /* if(i%4 == 0) raw_data[j*width*4+i] = 0; else if(i%4 == 1) raw_data[j*width*4+i] = 255; else if(i%4 == 2) raw_data[j*width*4+i] = 0; else raw_data[j*width*4+i] = 128.0; //これより低い値では表示しない */ } } /* Alpha値がない場合はこれでいい for(j = 0; j < height; j++){ for(i = 0; i < width*3; i++){ raw_data[j*width*3+i] = raw_pointers[height-j-1][i]; } } for(i = 0; i < height; i++){ memcpy(raw_data+(i*width*bpp),raw_pointers[height-i-1],width*bpp); } */ fclose(fp); png_destroy_read_struct(&png_sp,&png_ip,NULL); }
void image::load_png(const std::string filename) { #ifdef HAVE_LIBPNG FILE *fp = fopen(filename.c_str(), "rb"); if (!fp) throw image_file_exception("image::load_png - could not open file: " + filename); char header[8]; fread(header,1,8,fp); bool is_png= !png_sig_cmp((png_byte*)header,0,8); if (!is_png) throw image_read_exception("image::load_png - File is not in PNG format: " + filename); png_structp png_ptr = png_create_read_struct ( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); if(!png_ptr) throw image_read_exception("image::load_png - Couldnt create PNG read structure"); png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) throw image_read_exception("image::load_png - Couldnt create PNG info struct 1"); png_infop end_info = png_create_info_struct(png_ptr); if(!end_info) throw image_read_exception("image::load_png - Couldnt create PNG info struct 2"); if(setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); throw image_read_exception("image::load_png - PNG error"); } png_init_io(png_ptr,fp); png_set_sig_bytes(png_ptr,8); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND,NULL); unsigned long width,height,bit_depth; width=png_get_image_width(png_ptr,info_ptr); height=png_get_image_height(png_ptr,info_ptr); bit_depth=png_get_bit_depth(png_ptr,info_ptr); INFO("Read PNG: width " << width << " height " << height << " depth " << bit_depth ); int bytes_per_pixel = png_get_channels(png_ptr,info_ptr); INFO("PNG file has " << bytes_per_pixel << " Bytes per Pixel"); png_bytep* row_pointers = png_get_rows(png_ptr, info_ptr); offscreen_surface = onscreen_surface->create_surface(rectangle(0, 0, width, height)); graphics_context::ptr gc=graphics_context::create(); offscreen_surface->gc(gc); gc->alpha_blend(false); // We want the image data with its alpha channel to be in // the offscreen surface verbatim, not blended offscreen_surface->clip_rect(rectangle(0, 0, width, height)); for (unsigned int y = 0; y < height; y++) { for (unsigned int x = 0; x < width; x++) { char r = row_pointers[y][(x*bytes_per_pixel)+0]; char g = row_pointers[y][(x*bytes_per_pixel)+1]; char b = row_pointers[y][(x*bytes_per_pixel)+2]; char a = 255; // FIXME we need acces to stk::opaque here if (bytes_per_pixel > 3) a = row_pointers[y][(x*bytes_per_pixel)+3]; color pixel_color = offscreen_surface->gen_color(r, g, b, a); offscreen_surface->draw_pixel(x, y, pixel_color); } } gc->alpha_blend(true); // If the user draws the image, he should get alpha blending by default // png_read_end(png_ptr, end_info); INFO("Destroying png read struct"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); #else throw image_read_exception("image::load_png() No support for loading PNG files compiled in!"); #endif }
// Load PNG for texture int LoadPNG (char *filename) // Loads A PNG File Into Memory { char header[8]; GLuint bytesPerPixel; // Holds Number Of Bytes Per Pixel Used In The TGA File GLuint imageSize; // Used To Store The Image Size When Setting Aside Ram GLuint temp; // Temporary Variable GLuint type = GL_RGBA; // Set The Default GL Mode To RBGA (32 BPP) GLuint i; GLuint pos = 0; unsigned char value[4]; FILE *file = fopen(filename, "rb"); // Open The TGA File if ( file==NULL ) return 0; // Check if this is indeed a PNG file fread(header, 1, 8, file); if (png_sig_cmp(header, 0, 8)) { fclose(file); return 0; } // Initialise PNG structures png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fclose(file); return 0; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { fclose(file); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return 0; } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { fclose(file); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return 0; } // Init PNG file i/o png_init_io(png_ptr, file); // We've already read the header (8 bytes) png_set_sig_bytes(png_ptr, 8); // Read the image into memory png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); g_overlay.width = png_ptr->width; // Determine The PNG Width g_overlay.height = png_ptr->height; // Determine The PNG Height if( g_overlay.width <=0 || // Is The Width Less Than Or Equal To Zero g_overlay.height <=0) // Is The Height Less Than Or Equal To Zero { fclose(file); // If Anything Failed, Close The File return 0; // Return False } g_overlay.bpp = png_ptr->bit_depth * png_ptr->channels; // Bits per pixel (24 or 32) bytesPerPixel = g_overlay.bpp/8; // Divide By 8 To Get The Bytes Per Pixel imageSize = g_overlay.width*g_overlay.height*bytesPerPixel; // Calculate The Memory Required For The TGA Data //g_overlay.upsideDown = (header[17] & 0x20) ? 0 : 1; // If TGA origin is bottom-left g_overlay.imageData = (GLubyte *)png_ptr->row_buf[0]; // Reserve Memory To Hold The TGA Data //if ( 2 == tgaType ) //{ // // uncompressed RGB (24 or 32-bit) // g_overlay.imageData=(GLubyte *)malloc(imageSize); // Reserve Memory To Hold The TGA Data // if( g_overlay.imageData==NULL || // Does The Storage Memory Exist? // fread(g_overlay.imageData, 1, imageSize, file)!=imageSize) // Does The Image Size Match The Memory Reserved? // { // if(g_overlay.imageData!=NULL) // Was Image Data Loaded // free(g_overlay.imageData); // If So, Release The Image Data // fclose(file); // Close The File // return 0; // Return False // } // for (i=0; i < imageSize; i += bytesPerPixel) // { // temp = g_overlay.imageData[i]; // Temporarily Store The Value At Image Data 'i' // g_overlay.imageData[i] = g_overlay.imageData[i + 2]; // Set The 1st Byte To The Value Of The 3rd Byte // g_overlay.imageData[i + 2] = temp; // Set The 3rd Byte To The Value In 'temp' (1st Byte Value) // } //} //else if (10 == tgaType) //{ // // RLE compressed RGB (24 or 32-bit) // g_overlay.imageData=(GLubyte *)malloc(imageSize); // Reserve Memory To Hold The TGA Data // pos = 0; // while(1) // { // // read packet header // unsigned char ph; // = fgetc(file); // if (fread(&ph, 1, 1, file)!=1) // { // fclose(file); // return 0; // } // // packet type // if (ph & 0x80) // { // // run-length packet // unsigned int len = (ph & 0x7F) + 1; // fread(value, 1, bytesPerPixel, file); // for (i=0; i<len; i++) // { // g_overlay.imageData[pos] = value[2]; // g_overlay.imageData[pos+1] = value[1]; // g_overlay.imageData[pos+2] = value[0]; // pos += bytesPerPixel; // } // } // else // { // // "raw" packet // unsigned int len = (ph & 0x7F) + 1; // for (i=0; i<len; i++) // { // fread(value, 1, bytesPerPixel, file); // g_overlay.imageData[pos] = value[2]; // g_overlay.imageData[pos+1] = value[1]; // g_overlay.imageData[pos+2] = value[0]; // pos += bytesPerPixel; // } // } // if (pos >= imageSize) // break; // } //} fclose (file); // Close The File // resize if neccessary if (g_overlay.width != 512 || g_overlay.height != 512) { GLubyte* newImageData = (GLubyte *)malloc(512*512*bytesPerPixel); // Reserve Memory To Hold The RGB Data gluScaleImage(GL_RGB, g_overlay.width, g_overlay.height, GL_UNSIGNED_BYTE, g_overlay.imageData, 512, 512, GL_UNSIGNED_BYTE, newImageData); free(g_overlay.imageData); g_overlay.imageData = newImageData; g_overlay.width = 512; g_overlay.height = 512; } // Build A Texture From The Data glGenTextures(1, &g_overlay.texID); // Generate OpenGL texture IDs glBindTexture(GL_TEXTURE_2D, g_overlay.texID); // Bind Our Texture glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Linear Filtered glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtered glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); if (g_overlay.bpp==24) // Was The TGA 24 Bits { type=GL_RGB; // If So Set The 'type' To GL_RGB } glTexImage2D(GL_TEXTURE_2D, 0, type, g_overlay.width, g_overlay.height, 0, type, GL_UNSIGNED_BYTE, g_overlay.imageData); return 1; // Texture Building Went Ok, Return True }
unsigned char *PngLoad(FILE *fp, int *widthptr, int *heightptr, int *alphaptr) { unsigned char buf[PNG_BYTES_TO_CHECK]; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height, j; int color_type, row_bytes; unsigned char **imageData, *rgb; /* Check signature */ if (fread(buf, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK) return NULL; if (png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) return NULL; /* Not a PNG image */ /* Initialize data structures */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); if (png_ptr == NULL) { return NULL; /* Out of memory */ } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, NULL, NULL); return NULL; } /* Error handling code */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } /* Set the I/O method */ png_init_io(png_ptr, fp); /* Undo the fact that we read some data to detect the PNG file */ png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); /* Read the PNG in memory at once */ png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); /* Get image info */ 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); if (color_type != PNG_COLOR_TYPE_RGB && color_type != PNG_COLOR_TYPE_RGB_ALPHA) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } /* Get the image data */ imageData = png_get_rows(png_ptr, info_ptr); row_bytes = png_get_rowbytes(png_ptr, info_ptr); rgb = malloc(row_bytes*height); if (!rgb) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } for (j = 0; j < height; j++) { unsigned char *dst = rgb+(j*width*3); unsigned char *src = imageData[j]; unsigned int i; for (i = 0; i < width; i++) { dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; dst += 3; src += (color_type == PNG_COLOR_TYPE_RGB_ALPHA) ? 4 : 3; } } /* Free the image and resources and return */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); *widthptr = width; *heightptr = height; *alphaptr = (color_type == PNG_COLOR_TYPE_RGB_ALPHA); return rgb; }
/* Read a PNG file. You may want to return an error code if the read * fails (depending upon the failure). There are two "prototypes" given * here - one where we are given the filename, and we need to open the * file, and the other where we are given an open file (possibly with * some or all of the magic bytes read - see comments above). */ #ifdef open_file /* prototype 1 */ void read_png(char *file_name) /* We need to open the file */ { png_structp png_ptr; png_infop info_ptr; unsigned int sig_read = 0; png_uint_32 width, height; int bit_depth, color_type, interlace_type; FILE *fp; if ((fp = fopen(file_name, "rb")) == NULL) return; #else no_open_file /* prototype 2 */ void read_png(FILE *fp, unsigned int sig_read) /* file is already open */ { png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int bit_depth, color_type, interlace_type; #endif no_open_file /* only use one prototype! */ /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also supply the * the compiler header file version, so that we know if the application * was compiled with a compatible version of the library. REQUIRED */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp user_error_ptr, user_error_fn, user_warning_fn); if (png_ptr == NULL) { fclose(fp); return; } /* Allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return; } /* Set error handling if you are using the setjmp/longjmp method (this is * the normal method of doing things with libpng). REQUIRED unless you * set up your own error handlers in the png_create_read_struct() earlier. */ #ifndef PNG_JMPBUF_SUPPORTED /* Old interface */ if (setjmp(png_ptr->jmpbuf)) #else /* New interface */ if (png_setjmp(png_ptr)) #endif { /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fp); /* If we get here, we had a problem reading the file */ return; } /* One of the following I/O initialization methods is REQUIRED */ #ifdef streams /* PNG file I/O method 1 */ /* Set up the input control if you are using standard C streams */ png_init_io(png_ptr, fp); #else no_streams /* PNG file I/O method 2 */ /* If you are using replacement read functions, instead of calling * png_init_io() here you would call: */ png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn); /* where user_io_ptr is a structure you want available to the callbacks */ #endif no_streams /* Use only one I/O method! */ /* If we have already read some of the signature */ png_set_sig_bytes(png_ptr, sig_read); #ifdef hilevel /* * If you have enough memory to read in the entire image at once, * and you need to specify only transforms that can be controlled * with one of the PNG_TRANSFORM_* bits (this presently excludes * dithering, filling, setting background, and doing gamma * adjustment), then you can read the entire image (including * pixels) into the info structure with this call: */ png_read_png(png_ptr, info_ptr, png_transforms, NULL); #else /* OK, you're doing it the hard way, with the lower-level functions */ /* The call to png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). REQUIRED */ png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); /**** Set up the data transformations you want. Note that these are all **** optional. Only call them if you want/need them. Many of the **** transformations only work on specific types of images, and many **** are mutually exclusive. ****/ /* tell libpng to strip 16 bit/color files down to 8 bits/color */ png_set_strip_16(png_ptr); /* Strip alpha bytes from the input data without combining with the * background (not recommended). */ png_set_strip_alpha(png_ptr); /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ png_set_packing(png_ptr); /* Change the order of packed pixels to least significant bit first * (not useful if you are using png_set_packing). */ png_set_packswap(png_ptr); /* Expand paletted colors into true RGB triplets */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand(png_ptr); /* Expand paletted or RGB images with transparency to full alpha channels * so the data will be available as RGBA quartets. */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); /* Set the background color to draw transparent and alpha images over. * It is possible to set the red, green, and blue components directly * for paletted images instead of supplying a palette index. Note that * even if the PNG file supplies a background, you are not required to * use it - you should use the (solid) application background if it has one. */ png_color_16 my_background, *image_background; if (png_get_bKGD(png_ptr, info_ptr, &image_background)) png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); else png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); /* Some suggestions as to how to get a screen gamma value */ /* Note that screen gamma is the display_exponent, which includes * the CRT_exponent and any correction for viewing conditions */ if (/* We have a user-defined screen gamma value */) { screen_gamma = user-defined screen_gamma; } /* This is one way that applications share the same screen gamma value */ else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
/*! * pixReadStreamPng() * * Input: stream * Return: pix, or null on error * * Notes: * (1) If called from pixReadStream(), the stream is positioned * at the beginning of the file. * (2) To do sequential reads of png format images from a stream, * use pixReadStreamPng() */ PIX * pixReadStreamPng(FILE *fp) { l_uint8 rval, gval, bval; l_int32 i, j, k; l_int32 wpl, d, spp, cindex; l_uint32 png_transforms; l_uint32 *data, *line, *ppixel; int num_palette, num_text; png_byte bit_depth, color_type, channels; png_uint_32 w, h, rowbytes; png_uint_32 xres, yres; png_bytep rowptr; png_bytep *row_pointers; png_structp png_ptr; png_infop info_ptr, end_info; png_colorp palette; png_textp text_ptr; /* ptr to text_chunk */ PIX *pix; PIXCMAP *cmap; PROCNAME("pixReadStreamPng"); if (!fp) return (PIX *)ERROR_PTR("fp not defined", procName, NULL); pix = NULL; /* Allocate the 3 data structures */ if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL)) == NULL) return (PIX *)ERROR_PTR("png_ptr not made", procName, NULL); if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return (PIX *)ERROR_PTR("info_ptr not made", procName, NULL); } if ((end_info = png_create_info_struct(png_ptr)) == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return (PIX *)ERROR_PTR("end_info not made", procName, NULL); } /* Set up png setjmp error handling */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return (PIX *)ERROR_PTR("internal png error", procName, NULL); } png_init_io(png_ptr, fp); /* ---------------------------------------------------------- * * Set the transforms flags. Whatever happens here, * NEVER invert 1 bpp using PNG_TRANSFORM_INVERT_MONO. * ---------------------------------------------------------- */ /* To strip 16 --> 8 bit depth, use PNG_TRANSFORM_STRIP_16 */ if (var_PNG_STRIP_16_TO_8 == 1) /* our default */ png_transforms = PNG_TRANSFORM_STRIP_16; else png_transforms = PNG_TRANSFORM_IDENTITY; /* To remove alpha channel, use PNG_TRANSFORM_STRIP_ALPHA */ if (var_PNG_STRIP_ALPHA == 1) /* our default */ png_transforms |= PNG_TRANSFORM_STRIP_ALPHA; /* Read it */ png_read_png(png_ptr, info_ptr, png_transforms, NULL); row_pointers = png_get_rows(png_ptr, info_ptr); w = png_get_image_width(png_ptr, info_ptr); h = png_get_image_height(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); rowbytes = png_get_rowbytes(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); channels = png_get_channels(png_ptr, info_ptr); spp = channels; if (spp == 1) d = bit_depth; else if (spp == 2) { d = 2 * bit_depth; L_WARNING("there shouldn't be 2 spp!", procName); } else /* spp == 3 (rgb), spp == 4 (rgba) */ d = 4 * bit_depth; /* Remove if/when this is implemented for all bit_depths */ if (spp == 3 && bit_depth != 8) { fprintf(stderr, "Help: spp = 3 and depth = %d != 8\n!!", bit_depth); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return (PIX *)ERROR_PTR("not implemented for this depth", procName, NULL); } if (color_type == PNG_COLOR_TYPE_PALETTE || color_type == PNG_COLOR_MASK_PALETTE) { /* generate a colormap */ png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); cmap = pixcmapCreate(d); /* spp == 1 */ for (cindex = 0; cindex < num_palette; cindex++) { rval = palette[cindex].red; gval = palette[cindex].green; bval = palette[cindex].blue; pixcmapAddColor(cmap, rval, gval, bval); } } else cmap = NULL; if ((pix = pixCreate(w, h, d)) == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return (PIX *)ERROR_PTR("pix not made", procName, NULL); } wpl = pixGetWpl(pix); data = pixGetData(pix); pixSetColormap(pix, cmap); if (spp == 1) { /* copy straight from buffer to pix */ for (i = 0; i < h; i++) { line = data + i * wpl; rowptr = row_pointers[i]; for (j = 0; j < rowbytes; j++) { SET_DATA_BYTE(line, j, rowptr[j]); } } } else { /* spp == 3 or spp == 4 */ for (i = 0; i < h; i++) { ppixel = data + i * wpl; rowptr = row_pointers[i]; for (j = k = 0; j < w; j++) { SET_DATA_BYTE(ppixel, COLOR_RED, rowptr[k++]); SET_DATA_BYTE(ppixel, COLOR_GREEN, rowptr[k++]); SET_DATA_BYTE(ppixel, COLOR_BLUE, rowptr[k++]); if (spp == 4) SET_DATA_BYTE(ppixel, L_ALPHA_CHANNEL, rowptr[k++]); ppixel++; } } } #if DEBUG if (cmap) { for (i = 0; i < 16; i++) { fprintf(stderr, "[%d] = %d\n", i, ((l_uint8 *)(cmap->array))[i]); } } #endif /* DEBUG */ /* If there is no colormap, PNG defines black = 0 and * white = 1 by default for binary monochrome. Therefore, * since we use the opposite definition, we must invert * the image colors in either of these cases: * (i) there is no colormap (default) * (ii) there is a colormap which defines black to * be 0 and white to be 1. * We cannot use the PNG_TRANSFORM_INVERT_MONO flag * because that flag (since version 1.0.9) inverts 8 bpp * grayscale as well, which we don't want to do. * (It also doesn't work if there is a colormap.) * If there is a colormap that defines black = 1 and * white = 0, we don't need to do anything. * * How do we check the polarity of the colormap? * The colormap determines the values of black and * white pixels in the following way: * if black = 1 (255), white = 0 * 255, 255, 255, 0, 0, 0, 0, 0, 0 * if black = 0, white = 1 (255) * 0, 0, 0, 0, 255, 255, 255, 0 * So we test the first byte to see if it is 0; * if so, invert the colors. * * If there is a colormap, after inverting the pixels it is * necessary to destroy the colormap. Otherwise, if someone were * to call pixRemoveColormap(), this would cause the pixel * values to be inverted again! */ if (d == 1 && (!cmap || (cmap && ((l_uint8 *)(cmap->array))[0] == 0x0))) { /* fprintf(stderr, "Inverting binary data on png read\n"); */ pixInvert(pix, pix); pixDestroyColormap(pix); } xres = png_get_x_pixels_per_meter(png_ptr, info_ptr); yres = png_get_y_pixels_per_meter(png_ptr, info_ptr); pixSetXRes(pix, (l_int32)((l_float32)xres / 39.37 + 0.5)); /* to ppi */ pixSetYRes(pix, (l_int32)((l_float32)yres / 39.37 + 0.5)); /* to ppi */ /* Get the text if there is any */ png_get_text(png_ptr, info_ptr, &text_ptr, &num_text); if (num_text && text_ptr) pixSetText(pix, text_ptr->text); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return pix; }
/*Loads a png image*/ bool Engine::loadImage(char *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData) { png_structp pngPtr; png_infop infoPtr; unsigned int sigRead = 0; int colorType, interlaceType; FILE *file; if ((file = fopen(name, "rb")) == NULL) return false; pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (pngPtr == NULL) { fclose(file); return false; } infoPtr = png_create_info_struct(pngPtr); if (infoPtr == NULL) { fclose(file); png_destroy_read_struct(&pngPtr, png_infopp_NULL, png_infopp_NULL); return false; } if (setjmp(png_jmpbuf(pngPtr))) { png_destroy_read_struct(&pngPtr, &infoPtr, png_infopp_NULL); fclose(file); return false; } png_init_io(pngPtr, file); png_set_sig_bytes(pngPtr, sigRead); png_read_png(pngPtr, infoPtr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, png_voidp_NULL); outWidth = infoPtr->width; outHeight = infoPtr->height; switch (infoPtr->color_type) { case PNG_COLOR_TYPE_RGBA: outHasAlpha = true; break; case PNG_COLOR_TYPE_RGB: outHasAlpha = false; break; default: cout << "Color type " << infoPtr->color_type << " not supported" << endl; png_destroy_read_struct(&pngPtr, &infoPtr, NULL); fclose(file); return false; } unsigned int rowBytes = png_get_rowbytes(pngPtr, infoPtr); *outData = (unsigned char*) malloc(rowBytes*outHeight); png_bytepp rowPointers = png_get_rows(pngPtr, infoPtr); for (int i = 0; i < outHeight; i++) memcpy(*outData+(rowBytes*(outHeight-1-i)), rowPointers[i], rowBytes); png_destroy_read_struct(&pngPtr, &infoPtr, png_infopp_NULL); fclose(file); return true; }
static void read_png_file(const char* file_name, png_image_data_t *png_image_data, int max_width, int max_height) { png_structp png_ptr; png_infop info_ptr; png_bytep *row_pointers; char header[8]; // 8 is the maximum size that can be checked int y; char* dest; /* open file and test for it being a png */ FILE *fp = fopen(file_name, "rb"); if (!fp) abort_("[read_png_file] File %s could not be opened for reading", file_name); fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) abort_("[read_png_file] File %s is not recognized as a PNG file", file_name); /* initialize stuff */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) abort_("[read_png_file] png_create_read_struct failed"); if (max_width > 0 && max_height > 0) png_set_user_limits(png_ptr, max_width, max_height); info_ptr = png_create_info_struct(png_ptr); if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during init_io"); png_init_io(png_ptr, fp); if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during init_io"); png_set_sig_bytes(png_ptr, sizeof(header)); if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during init_io"); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_ALPHA, png_voidp_NULL); if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during init_io"); row_pointers = png_get_rows(png_ptr, info_ptr); png_image_data->height = png_get_image_height(png_ptr, info_ptr); png_image_data->width = png_get_image_width(png_ptr, info_ptr); png_image_data->image4c = (void*)qemu_malloc(png_image_data->width * png_image_data->height * 4); dest = (char*)png_image_data->image4c; /* transform this from 3 channels to a (fake for now) 4 channels */ for (y=0; y < png_image_data->height; y++) { char* src = row_pointers[y]; int x; for (x = 0; x < png_image_data->width; x++) { *dest = *src; dest++, src++; *dest = *src; dest++, src++; *dest = *src; dest++, src++; *dest = 0; dest++; /* alpha channel ignored */ } } png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(fp); }
PingPNG (const std::string& aPath) : File(0), PngPtr(0), InfoPtr(0), RowPointers(0), Width(0), Height(0), Valid(false) { File = fopen(aPath.c_str(), "rb"); if(File) { fread(Header, 1, 8, File); if(!png_sig_cmp(Header, 0, 8)) { PngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(PngPtr) { InfoPtr = png_create_info_struct(PngPtr); if(InfoPtr) { if(setjmp(png_jmpbuf(PngPtr))) { es_log->AppendLine("PNG Reader: Error during init_io. [File: %s]", aPath.c_str()); return; } png_init_io(PngPtr, File); png_set_sig_bytes(PngPtr, 8); if(setjmp(png_jmpbuf(PngPtr))) { es_log->AppendLine("PNG Reader: Error during read_png. [File: %s]", aPath.c_str()); return; } png_read_png(PngPtr, InfoPtr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_SWAP_ALPHA, 0); RowPointers = png_get_rows(PngPtr, InfoPtr); if(!RowPointers) { es_log->AppendLine("PNG Reader: Failed to get pixels. [File: %s]", aPath.c_str()); return; } Width = png_get_image_width(PngPtr, InfoPtr); Height = png_get_image_height(PngPtr, InfoPtr); Valid = true; return; } else { es_log->AppendLine("PNG Reader: png_create_info_struct failed. [File: %s]", aPath.c_str()); return; } } else { es_log->AppendLine("PNG Reader: png_create_read_struct failed. [File: %s]", aPath.c_str()); return; } } else { es_log->AppendLine("PNG Reader: File not recognized as a PNG file. [File: %s]", aPath.c_str()); return; } } else { es_log->AppendLine("PNG Reader: File could not be opened for reading. [File: %s]", aPath.c_str()); return; } }
ImageReader::ImageHandle ImageReader::getImage(text::string_hash id) { if (hasProduct(id)) return getProduct(id); // Image is not in cache, load it. const std::string& url = text::get(id); INFO_OUT(TAG, "Loading image %s", url.c_str()); FILE* fp = fopen(url.c_str(), "rb"); if (fp == NULL) throw ResourceException("Cannot open file."); if ( !isPNGFile(fp) ) { fclose(fp); throw ResourceException("File is not PNG."); } png_structp pngStruct = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (!pngStruct) { fclose(fp); throw ResourceException("[LIBPNG] Error creating read struct."); } png_infop pngInfo = png_create_info_struct(pngStruct); if (!pngInfo) { png_destroy_read_struct(&pngStruct, nullptr, nullptr); fclose(fp); throw ResourceException("[LIBPNG] Error creating info struct."); } if ( setjmp(png_jmpbuf(pngStruct)) ) { png_destroy_read_struct(&pngStruct, &pngInfo, nullptr); fclose(fp); throw ResourceException("Error while reading file."); } png_init_io(pngStruct, fp); png_set_sig_bytes(pngStruct, pngHeaderCheckSize); // FIXME Write directly to buffer, don't copy. png_read_png(pngStruct, pngInfo, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL); struct { png_uint_32 width; png_uint_32 height; png_byte bitsPerPixel; png_byte colorType; png_size_t rowSize; } imageData; imageData.width = png_get_image_width(pngStruct, pngInfo); imageData.height = png_get_image_height(pngStruct, pngInfo); imageData.bitsPerPixel = png_get_bit_depth(pngStruct, pngInfo); imageData.colorType = png_get_color_type(pngStruct, pngInfo); imageData.rowSize = png_get_rowbytes(pngStruct, pngInfo); // FIXME Let PixelFormat decide what format is suitable. gr::PixelFormat fmt; if (imageData.colorType == PNG_COLOR_TYPE_RGBA) fmt = gr::PixelFormat::R8G8B8A8; else fmt = gr::PixelFormat::R8G8B8; unsigned char* pixels = new unsigned char[imageData.rowSize * imageData.height]; png_bytepp rowPointers = png_get_rows(pngStruct, pngInfo); for (unsigned int i = 0; i < imageData.height; i++) memcpy(pixels + (imageData.rowSize * (imageData.height - 1 - i)), rowPointers[i], imageData.rowSize); png_destroy_read_struct(&pngStruct, &pngInfo, NULL); fclose(fp); return addProduct(id, gr::Image((unsigned int) imageData.width, (unsigned int) imageData.height, fmt, 1u, pixels)); }
Texture PNGFile::Load(std::string _path) { Texture tex; // png specifics png_structp png_ptr = NULL; png_infop info_ptr = NULL, end_info = NULL; png_bytep *row_pointers = NULL; png_byte sig[8]; // the rest FILE *pngFile = NULL; GLubyte *pixels = NULL; GLuint glformat = 0; int components, rowsize; tex.path = _path; pngFile = fopen(_path.c_str(), "rb"); if (!pngFile) { Log->Print("File \"%s\" not found.", tex.path.c_str()); return Texture(); } if (fread(&sig, sizeof(png_byte), 8, pngFile) < 8) { Log->Print("Header of the file \"%s\" couldn't be fully read!", tex.path.c_str()); fclose(pngFile); return Texture(); } if (png_sig_cmp(sig, 0, 8)) { Log->Print("File \"%s\" is not a valid png file!", tex.path.c_str()); fclose(pngFile); return Texture(); } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); if (!png_ptr) { fclose(pngFile); return Texture(); } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); fclose(pngFile); return Texture(); } end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(pngFile); return Texture(); } // safety first. :) if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(pngFile); return Texture(); } // init io and tell libpng we've already read the sig. png_init_io(png_ptr, pngFile); png_set_sig_bytes(png_ptr, 8); // If we've got tRNS on an RGB image, it's a color key. Make this RGBA. if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); // filler for keys png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); // read the file png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); tex.width = png_get_image_width(png_ptr,info_ptr); tex.height = png_get_image_height(png_ptr,info_ptr); rowsize = png_get_rowbytes(png_ptr,info_ptr); components = png_get_channels(png_ptr,info_ptr); row_pointers = png_get_rows(png_ptr, info_ptr); pixels = new GLubyte[rowsize * tex.height]; for (unsigned int i = 0; i < tex.height; i++) memcpy(&pixels[i*rowsize], row_pointers[i], rowsize); // prepare texture for uploading to GPU glGenTextures(1, &tex.ptr); // make it glBindTexture(GL_TEXTURE_2D, tex.ptr); // bind it glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); switch(components) { case 1: glformat = GL_LUMINANCE; break; case 2: glformat = GL_LUMINANCE_ALPHA; break; // case 3 would be converted to 4, above. case 4: glformat = GL_RGBA; break; default: glformat = 0; // this shouldn't happen. break; } // log some stats Log->Print("Uploading texture (res = %dx%d, channels = %d)", tex.width, tex.height, components); // finally upload the texture glTexImage2D(GL_TEXTURE_2D, 0, components, tex.width, tex.height, 0, glformat, GL_UNSIGNED_BYTE, pixels); // cleanup png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete[] pixels; fclose(pngFile); return tex; }
/** * @brief pngloader loads texture from png file * @param filename is name of file * @param alpha is amount of blending */ pngloader::pngloader(const char* filename, float alpha) { unsigned int sig_read = 0; #ifdef ZIP_ARCHIVE file = zip_fopen(APKArchive, prefix(filename), 0); #else fp = fopen(prefix(filename), "rb"); #endif png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_infop info_ptr = png_create_info_struct(png_ptr); setjmp(png_jmpbuf(png_ptr)); png_set_read_fn(png_ptr, NULL, png_read); png_set_sig_bytes(png_ptr, sig_read); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16, NULL); int bit_depth, color_type, interlace_type; png_uint_32 width, height; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); switch (color_type) { case PNG_COLOR_TYPE_RGBA: alpha = true; break; case PNG_COLOR_TYPE_RGB: alpha = false; break; } unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr); GLubyte *outData = new GLubyte[row_bytes * height]; png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr); for (unsigned int i = 0; i < height; i++) { memcpy(outData+(row_bytes * (height-1-i)), row_pointers[i], row_bytes); } /* Clean up after the read, * and free any memory allocated */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); #ifdef ZIP_ARCHIVE zip_fclose(file); #else fclose(fp); #endif /// transform data transparent = alpha; glGenTextures(1, &textureID); glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textureID); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR ); if (alpha) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, outData); } else { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, outData); } delete[] outData; }
void png_loader::read_image( const char* filename ) { ld_.reset(new LibpngData); if ( filename == NULL ) { throw image_load_error("png_loader: invalid filename, it is NULL"); } FILE *fp = fopen( filename, "rb" ); if ( !fp ) { throw image_load_error(std::string("png_loader: unable to open file ") + filename); } png_byte sig[8]; if (fread( sig, 1, 8, fp ) != 8) { fclose( fp ); throw image_load_error(std::string("png_loader: error reading file ") + filename); } if ( png_sig_cmp( sig, 0, 8 ) != 0 ) { fclose( fp ); throw image_load_error(std::string("png_loader: format error in file ") + filename); } ld_->png_ptr_ = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, &png_loader_user_error_fn_silent, &png_loader_user_warning_fn_silent ); if ( ld_->png_ptr_ == NULL ) { fclose( fp ); throw image_load_error(std::string("png_loader: parse error in file ") + filename); } ld_->info_ptr_ = png_create_info_struct( ld_->png_ptr_ ); if ( ld_->info_ptr_ == NULL ) { fclose( fp ); png_destroy_read_struct( &( ld_->png_ptr_ ), ( png_infopp )NULL, ( png_infopp )NULL ); throw image_load_error(std::string("png_loader: parse error in file ") + filename); } ld_->end_info_ = png_create_info_struct( ld_->png_ptr_ ); if ( ld_->end_info_ == NULL ) { fclose( fp ); png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), ( png_infopp )NULL ); throw image_load_error(std::string("png_loader: parse error in file ") + filename); } if (setjmp(png_jmpbuf(ld_->png_ptr_))) { // If we get here, we had a problem writing the file fclose(fp); png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) ); throw image_load_error(std::string("png_loader: parse error in file ") + filename); } png_set_palette_to_rgb(ld_->png_ptr_); png_init_io( ld_->png_ptr_, fp ); png_set_sig_bytes( ld_->png_ptr_, 8 ); // flags force one byte per channel output byte_orderer bo; int png_transforms = PNG_TRANSFORM_PACKING; if (bo.host_is_little_endian()) png_transforms |= PNG_TRANSFORM_SWAP_ENDIAN; png_read_png( ld_->png_ptr_, ld_->info_ptr_, png_transforms, NULL ); height_ = png_get_image_height( ld_->png_ptr_, ld_->info_ptr_ ); width_ = png_get_image_width( ld_->png_ptr_, ld_->info_ptr_ ); bit_depth_ = png_get_bit_depth( ld_->png_ptr_, ld_->info_ptr_ ); color_type_ = png_get_color_type( ld_->png_ptr_, ld_-> info_ptr_ ); if (color_type_ != PNG_COLOR_TYPE_GRAY && color_type_ != PNG_COLOR_TYPE_RGB && color_type_ != PNG_COLOR_TYPE_RGB_ALPHA ) { fclose( fp ); png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) ); throw image_load_error(std::string("png_loader: unsupported color type in file ") + filename); } if (bit_depth_ != 8 && bit_depth_ != 16) { fclose( fp ); png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) ); throw image_load_error("png_loader: unsupported bit depth of " + cast_to_string(bit_depth_) + " in file " + std::string(filename)); } ld_->row_pointers_ = png_get_rows( ld_->png_ptr_, ld_->info_ptr_ ); fclose( fp ); if ( ld_->row_pointers_ == NULL ) { png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) ); throw image_load_error(std::string("png_loader: parse error in file ") + filename); } }
TypedImage LoadPng(const std::string& filename) { #ifdef HAVE_PNG FILE *in = fopen(filename.c_str(), "rb"); if( in ) { //check the header const size_t nBytes = 8; png_byte header[nBytes]; size_t nread = fread(header, 1, nBytes, in); int nIsPNG = png_sig_cmp(header, 0, nread); if ( nIsPNG != 0 ) { throw std::runtime_error( filename + " is not a PNG file" ); } //set up initial png structs png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, &PngWarningsCallback); if (!png_ptr) { throw std::runtime_error( "PNG Init error 1" ); } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); throw std::runtime_error( "PNG Init error 2" ); } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); throw std::runtime_error( "PNG Init error 3" ); } png_init_io(png_ptr, in); png_set_sig_bytes(png_ptr, nBytes); //read the file png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); if( png_get_bit_depth(png_ptr, info_ptr) == 1) { //Unpack bools to bytes to ease loading. png_set_packing(png_ptr); } else if( png_get_bit_depth(png_ptr, info_ptr) < 8) { //Expand nonbool colour depths up to 8bpp png_set_expand_gray_1_2_4_to_8(png_ptr); } //Get rid of palette, by transforming it to RGB if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); } if( png_get_interlace_type(png_ptr,info_ptr) != PNG_INTERLACE_NONE) { throw std::runtime_error( "Interlace not yet supported" ); } const size_t w = png_get_image_width(png_ptr,info_ptr); const size_t h = png_get_image_height(png_ptr,info_ptr); const size_t pitch = png_get_rowbytes(png_ptr, info_ptr); TypedImage img; img.Alloc(w, h, PngFormat(png_ptr, info_ptr), pitch); png_bytepp rows = png_get_rows(png_ptr, info_ptr); for( unsigned int r = 0; r < h; r++) { memcpy( img.ptr + pitch*r, rows[r], pitch ); } png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(in); return img; } throw std::runtime_error("Unable to load PNG file, '" + filename + "'"); #else throw std::runtime_error("PNG Support not enabled. Please rebuild Pangolin."); #endif }
void read( Image& img, const char* file_name ) { // TODO: Use shared_ptr to execute fclose() etc. when exiting scope. // open file FILE *fp = fopen(file_name, "rb"); if (!fp) { throw std::exception("Failed to open file."); } boost::shared_ptr<void> fp_cleanup( static_cast<void*>(0), boost::bind( fclose, fp ) ); const int PNG_BYTES_TO_CHECK = 4; png_byte header[PNG_BYTES_TO_CHECK]; fread(header, 1, PNG_BYTES_TO_CHECK, fp); const bool is_png = !png_sig_cmp(header, 0, PNG_BYTES_TO_CHECK); if (!is_png) { throw std::exception("File is not a valid PNG file."); } // setup PNG structs png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png_ptr) { throw std::exception("png_create_read_struct failed."); } png_infop info_ptr = 0; png_infop end_info = 0; boost::shared_ptr<void> png_cleanup( static_cast<void*>(0), boost::bind( png_destroy_read_struct, &png_ptr, &info_ptr, &end_info ) ); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { throw std::exception("png_create_info_struct failed."); } end_info = png_create_info_struct(png_ptr); if (!end_info) { throw std::exception("png_create_info_struct failed."); } // TODO Remove setjmp if (setjmp(png_jmpbuf(png_ptr))) { throw std::exception("Failed to read PNG-image."); } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); const png_bytep* row_pointers = png_get_rows(png_ptr, info_ptr); // Assert we are making correct assumptions about PNG lib. assert( info_ptr->rowbytes == info_ptr->channels * info_ptr->width ); Image img_tmp( info_ptr->width, info_ptr->height, info_ptr->channels, row_pointers ); img.swap( img_tmp ); }
bool PngRead(uint8 * * pixels, uint32 * width, uint32 * height, bool expand, const utf8 * path, sint32 * bitDepth) { png_structp png_ptr; png_infop info_ptr; // Setup PNG structures png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (png_ptr == nullptr) { return false; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == nullptr) { png_destroy_read_struct(&png_ptr, nullptr, nullptr); return false; } // Open PNG file try { unsigned int sig_read = 0; auto fs = FileStream(path, FILE_MODE_OPEN); // Set error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); return false; } // Setup PNG reading png_set_read_fn(png_ptr, &fs, PngReadData); png_set_sig_bytes(png_ptr, sig_read); uint32 readFlags = PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING; if (expand) { // If we expand the resulting image always be full RGBA readFlags |= PNG_TRANSFORM_GRAY_TO_RGB | PNG_TRANSFORM_EXPAND; } png_read_png(png_ptr, info_ptr, readFlags, nullptr); // Read header png_uint_32 pngWidth, pngHeight; int colourType, interlaceType; png_get_IHDR(png_ptr, info_ptr, &pngWidth, &pngHeight, bitDepth, &colourType, &interlaceType, nullptr, nullptr); // Read pixels as 32bpp RGBA data png_size_t rowBytes = png_get_rowbytes(png_ptr, info_ptr); png_bytepp rowPointers = png_get_rows(png_ptr, info_ptr); uint8 * pngPixels = Memory::Allocate<uint8>(pngWidth * pngHeight * 4); uint8 * dst = pngPixels; if (colourType == PNG_COLOR_TYPE_RGB) { // 24-bit PNG (no alpha) Guard::Assert(rowBytes == pngWidth * 3, GUARD_LINE); for (png_uint_32 i = 0; i < pngHeight; i++) { uint8 * src = rowPointers[i]; for (png_uint_32 x = 0; x < pngWidth; x++) { *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = 255; } } } else if (*bitDepth == 8 && !expand) { // 8-bit paletted or grayscale Guard::Assert(rowBytes == pngWidth, GUARD_LINE); for (png_uint_32 i = 0; i < pngHeight; i++) { std::copy_n(rowPointers[i], rowBytes, dst); dst += rowBytes; } } else { // 32-bit PNG (with alpha) Guard::Assert(rowBytes == pngWidth * 4, GUARD_LINE); for (png_uint_32 i = 0; i < pngHeight; i++) { std::copy_n(rowPointers[i], rowBytes, dst); dst += rowBytes; } } // Close the PNG png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); // Return the output data *pixels = pngPixels; if (width != nullptr) *width = pngWidth; if (height != nullptr) *height = pngHeight; return true; } catch (const std::exception &) { *pixels = nullptr; if (width != nullptr) *width = 0; if (height != nullptr) *height = 0; return false; } }
int datpng_write (FILE * outfile, datpng_info * dat_info, void *data, size_t data_size) { png_colorp palette = NULL; int num_palette; int exit_stat = EXIT_SUCCESS; /* Check the bit depth. */ if (dat_info->bit_depth != 8) return PNGDAT_INVALID_BIT_DEPTH; int pixel_width, color_type; switch (dat_info->color_type) { case PNGDAT_CT_AUTO: pixel_width = 3; color_type = PNG_COLOR_TYPE_RGB; break; case PNGDAT_CT_RGB: pixel_width = 3; color_type = PNG_COLOR_TYPE_RGB; break; case PNGDAT_CT_PALETTE: pixel_width = 1; color_type = PNG_COLOR_TYPE_PALETTE; break; default: return PNGDAT_INVALID_COLOR_TYPE; break; } int csum = dat_info->checksum; int x_pos = dat_info->x_pos; int y_pos = dat_info->y_pos; int data_width = dat_info->data_width; int data_height = dat_info->data_height; int img_width = dat_info->png_width; int img_height = dat_info->png_height; /* No constraints defined. */ if (img_width == 0 && img_height == 0 && data_width == 0 && data_height == 0) return PNGDAT_MISSING_CONSTRAINT; /* Propagate width value. */ if (img_width == 0 && data_width > 0) img_width = data_width + x_pos; if (img_width > 0 && data_width == 0) data_width = img_width - x_pos; /* Propagate height value. */ if (img_height == 0 && data_height > 0) img_height = data_height - y_pos; if (img_height > 0 && data_height == 0) data_height = img_height + y_pos; if (img_width == 0 && data_width == 0) { /* Calculate a width. */ data_width = (int) ceil ((data_size + header_size) / (data_height * pixel_width * 1.0)); if (csum) data_width = (int) ceil ((data_size + header_size + data_height) / (data_height * pixel_width * 1.0)); img_width = data_width + x_pos; } if (img_height == 0 && data_height == 0) { /* Calculate a height. */ data_height = (int) ceil ((data_size + header_size) / (data_width * pixel_width * 1.0)); if (csum) data_height = (int) ceil ((data_size + header_size + data_height) / (data_width * pixel_width * 1.0)); img_height = data_height + y_pos; } png_bytep *row_pointers; /* Set up the image data. */ png_infop infoin_ptr; png_structp pngin_ptr; if (dat_info->insert) { pngin_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); infoin_ptr = png_create_info_struct (pngin_ptr); png_init_io (pngin_ptr, outfile); png_read_png (pngin_ptr, infoin_ptr, PNG_TRANSFORM_STRIP_ALPHA, NULL); row_pointers = png_get_rows (pngin_ptr, infoin_ptr); rewind (outfile); /* Check dimensions. */ img_width = infoin_ptr->width; img_height = infoin_ptr->height; if (data_width + x_pos > img_width) data_width = img_width - x_pos; if (data_height + y_pos > img_height) data_height = img_height - y_pos; /* Check color type. */ switch (infoin_ptr->color_type) { case PNG_COLOR_TYPE_PALETTE: pixel_width = 1; color_type = PNG_COLOR_TYPE_PALETTE; break; case PNG_COLOR_TYPE_RGB: pixel_width = 3; color_type = PNG_COLOR_TYPE_RGB; break; case PNG_COLOR_TYPE_RGB_ALPHA: pixel_width = 3; color_type = PNG_COLOR_TYPE_RGB; break; default: /* XXX free resources */ return PNGDAT_INVALID_COLOR_TYPE; break; } /* Check the bit depth. */ if (infoin_ptr->bit_depth != 8) { /* XXX free resources */ return PNGDAT_INVALID_BIT_DEPTH; } } else { row_pointers = (png_bytep *) malloc (sizeof (png_bytep) * img_height); } int rowbytes = img_width * pixel_width; int datbytes = data_width * pixel_width - csum; if (datbytes * data_height < data_size) { data_size = datbytes * data_height - header_size; exit_stat = PNGDAT_TRUNCATED; } /* Initialize png structs. */ png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_infop info_ptr = png_create_info_struct (png_ptr); png_init_io (png_ptr, outfile); /* Generate the header. */ uint8_t header[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; header[1] = (uint8_t) dat_info->bit_depth; if (csum) header[0] = 128; header[0] += cur_ver; /* Length of data in network order. */ uint32_t size = (int) data_size; size = htonl (size); memcpy (header + 2, &size, 4); /* Width of data in network order. */ uint32_t hdr_width = data_width; hdr_width = htonl (hdr_width); memcpy (header + 6, &hdr_width, 4); /* Load data into row_pointers image data. */ int data_len, offset; void *next_data = data; int i; for (i = 0; i < img_height; i++) { if (!dat_info->insert) row_pointers[i] = (png_bytep) calloc (1, rowbytes); /* Write the header. */ if (i == y_pos) { memcpy (row_pointers[y_pos] + (x_pos * pixel_width), &header, header_size); offset = header_size; } else offset = 0; /* 8-bit depth only: */ data_len = (i - y_pos + 1) * datbytes - header_size; if (data_len > data_size) data_len = data_size - (data_len - datbytes); else data_len = datbytes - offset; if (data_len < 0) data_len = 0; int write_out; write_out = 0; if (i >= y_pos && data_len > 0) { memcpy (row_pointers[i] + offset + (x_pos * pixel_width), next_data, data_len); next_data += data_len; write_out = 1; } /* Calculate the checksum. */ if (csum && write_out) { int j; uint8_t sum = 0; for (j = (x_pos * pixel_width); j < datbytes + (x_pos * pixel_width); j++) sum += row_pointers[i][j]; row_pointers[i][(x_pos * pixel_width) + datbytes] = sum; } } /* Determine a palette. */ if (color_type == PNG_COLOR_TYPE_PALETTE) { palette = gen_palette (); info_ptr->palette = palette; info_ptr->num_palette = num_palette; png_set_PLTE (png_ptr, info_ptr, palette, num_palette); } /* Set image meta data. */ info_ptr->width = img_width; info_ptr->height = img_height; info_ptr->valid = 0; info_ptr->rowbytes = rowbytes; info_ptr->num_trans = 0; info_ptr->bit_depth = dat_info->bit_depth; info_ptr->color_type = color_type; info_ptr->compression_type = PNG_COMPRESSION_TYPE_DEFAULT; info_ptr->filter_type = PNG_FILTER_TYPE_DEFAULT; info_ptr->interlace_type = PNG_INTERLACE_NONE; png_write_info (png_ptr, info_ptr); if (setjmp (png_jmpbuf (png_ptr))) printf ("[write_png_file] Error during write\n"); png_write_image (png_ptr, row_pointers); png_write_end (png_ptr, NULL); return exit_stat; }
/* Ripped from the libpng manual */ png_bytepp readpng(const char *filename, int* width, int* height) { FILE *fp = fopen(filename, "rb"); char header[8]; png_structp png_ptr; png_infop info_ptr, end_info; if (!fp) { fprintf(stderr, "%s ", filename); perror("fopen"); return NULL; } fread(header, 1, 8, fp); if(png_sig_cmp((png_byte*)header, 0, 8)) { fprintf(stderr, "%s: Not a PNG image!\n", filename); return NULL; } png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) return NULL; info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); return NULL; } end_info = png_create_info_struct(png_ptr); if(!end_info) { png_destroy_read_struct(&png_ptr, NULL, NULL); return NULL; } /* Set up jump target for libpng errors */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fprintf(stderr, "libpng error!\n"); fclose(fp); return NULL; } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_read_png(png_ptr, info_ptr, 0, NULL); /* Make sure the image is in the format we want */ *width = png_get_image_width(png_ptr, info_ptr); *height = png_get_image_height(png_ptr, info_ptr); if(png_get_bit_depth(png_ptr, info_ptr) != 8 || png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGB) fprintf(stderr, "Need an 8 bit/color RGB image!!\n"); fclose(fp); // close the file so we don't have too many open /* Warning! We leak these data structures!!! */ return png_get_rows(png_ptr, info_ptr); }
int dec_png(unsigned char *pngbuf,g2int *width,g2int *height,char *cout) { int interlace,color,compres,filter,bit_depth; g2int j,k,n,bytes,clen; png_structp png_ptr; png_infop info_ptr,end_info; png_bytepp row_pointers; png_stream read_io_ptr; png_uint_32 h32, w32; /* check if stream is a valid PNG format */ if ( png_sig_cmp(pngbuf,0,8) != 0) return (-3); /* create and initialize png_structs */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); if (!png_ptr) 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); return (-2); } end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr,(png_infopp)info_ptr,(png_infopp)NULL); return (-2); } /* Set Error callback */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr,&end_info); return (-3); } /* Initialize info for reading PNG stream from memory */ read_io_ptr.stream_ptr=(png_voidp)pngbuf; read_io_ptr.stream_len=0; /* Set new custom read function */ png_set_read_fn(png_ptr,(png_voidp)&read_io_ptr,(png_rw_ptr)user_read_data); /* png_init_io(png_ptr, fptr); */ /* Read and decode PNG stream */ png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); /* Get pointer to each row of image data */ row_pointers = png_get_rows(png_ptr, info_ptr); /* Get image info, such as size, depth, colortype, etc... */ /*printf("SAGT:png %d %d %d\n",info_ptr->width,info_ptr->height,info_ptr->bit_depth);*/ // (void)png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)width, (png_uint_32 *)height, (void)png_get_IHDR(png_ptr, info_ptr, &w32, &h32, &bit_depth, &color, &interlace, &compres, &filter); *height = h32; *width = w32; /* Check if image was grayscale */ /* if (color != PNG_COLOR_TYPE_GRAY ) { fprintf(stderr,"dec_png: Grayscale image was expected. \n"); } */ if ( color == PNG_COLOR_TYPE_RGB ) { bit_depth=24; } else if ( color == PNG_COLOR_TYPE_RGB_ALPHA ) { bit_depth=32; } /* Copy image data to output string */ n=0; bytes=bit_depth/8; clen=(*width)*bytes; for (j=0;j<*height;j++) { for (k=0;k<clen;k++) { cout[n]=*(row_pointers[j]+k); n++; } } /* Clean up */ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return 0; }
int read_png(png_structp *png_ptr2, png_infop *info_ptr2, struct archive* animarc) { png_structp png_ptr; png_infop info_ptr; png_ptr = *png_ptr2; info_ptr = *info_ptr2; /* Get the first 8 bits of the first file. */ void *pngheader; pngheader = malloc((size_t)8); if (pngheader == NULL) { printf("Failed to allocate."); return 1; } size_t hsize = 8; if (archive_read_data(animarc, pngheader, 8) < 1) { printf("Failed to read png header.\n"); return 1; } else { /* printf("Read header from archive."); */ } /* Check for PNG file. */ if (png_sig_cmp(pngheader, 0, 8)) { printf("Not a PNG file.\n"); return 1; } else { /* printf("Is a png file."); */ } /* Get image data and print out the first row. */ *png_ptr2 = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (*png_ptr2 == NULL) { printf("Failed to create PNG read struct."); return 1; } *info_ptr2 = png_create_info_struct(*png_ptr2); if (*info_ptr2 == NULL) { printf("Failed to create PNG info struct."); png_destroy_read_struct(&(*png_ptr2), png_infopp_NULL, png_infopp_NULL); return 1; } if (setjmp(png_jmpbuf(*png_ptr2))) { printf("Error during init_io.\n"); png_destroy_read_struct(&(*png_ptr2), &(*info_ptr2), png_infopp_NULL); return 1; } /* Set functions, get pointers, execute png_init_io */ png_set_read_fn(*png_ptr2, (void *)animarc, tarpng_read_data); png_set_sig_bytes(*png_ptr2, 8); if (setjmp(png_jmpbuf(*png_ptr2))) { printf("Error during init_io.\n"); png_destroy_read_struct(&(*png_ptr2), &(*info_ptr2), png_infopp_NULL); return 1; } /* Read image into info_ptr structure. */ png_read_png(*png_ptr2, *info_ptr2, 0, png_voidp_NULL); return 0; }
int Graph_LoadPNG( const char *filepath, LCUI_Graph *graph ) { #ifdef USE_LIBPNG FILE *fp; uchar_t *pixel_ptr; png_structp png_ptr; png_infop info_ptr; png_bytep* row_pointers; char buf[PNG_BYTES_TO_CHECK]; int w, h, x, y, ret = 0, temp, color_type; fp = fopen( filepath, "rb" ); if( fp == NULL ) { return FILE_ERROR_OPEN_ERROR; } png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ); info_ptr = png_create_info_struct( png_ptr ); setjmp( png_jmpbuf( png_ptr ) ); /* 读取PNG_BYTES_TO_CHECK个字节的数据 */ temp = fread( buf, 1, PNG_BYTES_TO_CHECK, fp ); /* 若读到的数据并没有PNG_BYTES_TO_CHECK个字节 */ if( temp < PNG_BYTES_TO_CHECK ) { fclose( fp ); png_destroy_read_struct( &png_ptr, &info_ptr, 0 ); return FILE_ERROR_UNKNOWN_FORMAT; } /* 检测数据是否为PNG的签名 */ temp = png_sig_cmp( (png_bytep)buf, (png_size_t)0, PNG_BYTES_TO_CHECK ); /* 如果不是PNG的签名,则说明该文件不是PNG文件 */ if( temp != 0 ) { fclose( fp ); png_destroy_read_struct( &png_ptr, &info_ptr, 0 ); return FILE_ERROR_UNKNOWN_FORMAT; } /* 复位文件指针 */ rewind( fp ); /* 开始读文件 */ png_init_io( png_ptr, fp ); /* 读取PNG图片信息 */ png_read_png( png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0 ); /* 获取图像的色彩类型 */ color_type = png_get_color_type( png_ptr, info_ptr ); /* 获取图像的宽高 */ w = png_get_image_width( png_ptr, info_ptr ); h = png_get_image_height( png_ptr, info_ptr ); /* 获取所有行像素数据,row_pointers里边就是rgba数据 */ row_pointers = png_get_rows( png_ptr, info_ptr ); /* 根据不同的色彩类型进行相应处理 */ switch( color_type ) { case PNG_COLOR_TYPE_RGB_ALPHA: graph->color_type = COLOR_TYPE_ARGB; temp = Graph_Create( graph, w, h ); if( temp != 0 ) { ret = FILE_ERROR_MALLOC_ERROR; break; } pixel_ptr = graph->bytes; for( y = 0; y < h; ++y ) { /* * Graph的像素数据存储格式是BGRA,而PNG库 * 提供像素数据的是RGBA格式的,因此需要调整写入顺序 */ for( x = 0; x < w * 4; x += 4 ) { *pixel_ptr++ = row_pointers[y][x + 2]; *pixel_ptr++ = row_pointers[y][x + 1]; *pixel_ptr++ = row_pointers[y][x]; *pixel_ptr++ = row_pointers[y][x + 3]; } } break; case PNG_COLOR_TYPE_RGB: graph->color_type = COLOR_TYPE_RGB; temp = Graph_Create( graph, w, h ); if( temp != 0 ) { ret = FILE_ERROR_MALLOC_ERROR; break; } pixel_ptr = graph->bytes; for( y = 0; y < h; ++y ) { for( x = 0; x < w * 3; x += 3 ) { *pixel_ptr++ = row_pointers[y][x + 2]; *pixel_ptr++ = row_pointers[y][x + 1]; *pixel_ptr++ = row_pointers[y][x]; } } break; /* 其它色彩类型的图像就读了 */ default: ret = FILE_ERROR_UNKNOWN_FORMAT; break; } fclose( fp ); png_destroy_read_struct( &png_ptr, &info_ptr, 0 ); #else _DEBUG_MSG( "warning: not PNG support!" ); #endif return ret; }
/* * Loads a PNG image * * @param [in] real_filename name of the png file to load * @param [out] image_data allocated storage for the bitmap * @param [in] bpp * @param [in] dest_size * @param [in] cf_type * * @retval true if succesful, false otherwise */ int png_read_bitmap(const char *real_filename, ubyte *image_data, int *bpp, int dest_size, int cf_type) { char filename[MAX_FILENAME_LEN]; png_infop info_ptr; png_structp png_ptr; png_bytepp row_pointers; unsigned int i; png_read_status status; status.reading_header = false; status.filename = real_filename; strcpy_s( filename, real_filename ); char *p = strchr( filename, '.' ); if ( p ) *p = 0; strcat_s( filename, ".png" ); status.cfp = cfopen(filename, "rb", CFILE_NORMAL, cf_type); if (status.cfp == NULL) return PNG_ERROR_READING; /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also supply the * the compiler header file version, so that we know if the application * was compiled with a compatible version of the library. REQUIRED */ png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, &status, png_error_fn, png_warning_fn, NULL, NULL, NULL); if (png_ptr == NULL) { mprintf(("png_read_bitmap: png_ptr went wrong\n")); cfclose(status.cfp); return PNG_ERROR_READING; } /* Allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { mprintf(("png_read_bitmap: info_ptr went wrong\n")); cfclose(status.cfp); png_destroy_read_struct(&png_ptr, NULL, NULL); return PNG_ERROR_READING; } if (setjmp(png_jmpbuf(png_ptr))) { mprintf(("png_read_bitmap: something went wrong\n")); /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); cfclose(status.cfp); /* If we get here, we had a problem reading the file */ return PNG_ERROR_READING; } png_set_read_fn(png_ptr, &status, png_scp_read_data); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_16, NULL); auto len = png_get_rowbytes(png_ptr, info_ptr); row_pointers = png_get_rows(png_ptr, info_ptr); if(bpp) *bpp = (ubyte)(len / png_get_image_width(png_ptr, info_ptr)) << 3; //copy row data to image unsigned int height = png_get_image_height(png_ptr, info_ptr); for (i = 0; i < height; i++) { memcpy(&image_data[i * len], row_pointers[i], len); } png_destroy_read_struct(&png_ptr, &info_ptr, NULL); cfclose(status.cfp); return PNG_ERROR_NONE; }
short load_inp_png_file(ImageData& img, const std::string& fname_inp, ProgramOptions& opts) { FILE* pngfile = fopen(fname_inp.c_str(),"rb"); if (pngfile == NULL) { perror(fname_inp.c_str()); return ERR_CANT_OPEN; } png_byte header[8]; if (fread(header,8,1,pngfile) != 1) { perror(fname_inp.c_str()); fclose(pngfile); return ERR_FILE_READ; } if (png_sig_cmp(header,0,8)) { LogErr("%s: Not a PNG file",fname_inp.c_str()); fclose(pngfile); return ERR_BAD_FILE; } img.png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!img.png_ptr) { LogErr("%s: png_create_read_struct error",fname_inp.c_str()); fclose(pngfile); return ERR_BAD_FILE; } img.info_ptr=png_create_info_struct(img.png_ptr); if (!img.info_ptr) { png_destroy_read_struct(&img.png_ptr, (png_infopp)NULL, (png_infopp)NULL); LogErr("%s: png_create_info_struct error",fname_inp.c_str()); fclose(pngfile); return ERR_BAD_FILE; } img.end_info=png_create_info_struct(img.png_ptr); if (!img.end_info) { png_destroy_read_struct(&img.png_ptr, &img.info_ptr, (png_infopp)NULL); LogErr("%s: png_create_info_struct error",fname_inp.c_str()); fclose(pngfile); return ERR_BAD_FILE; } if (setjmp(png_jmpbuf(img.png_ptr))) { png_destroy_read_struct(&img.png_ptr, &img.info_ptr, &img.end_info); LogErr("%s: PNG error",fname_inp.c_str()); fclose(pngfile); exit(1); } png_init_io(img.png_ptr, pngfile); png_set_sig_bytes(img.png_ptr,8); int trafo=PNG_TRANSFORM_PACKING|PNG_TRANSFORM_STRIP_16|PNG_TRANSFORM_EXPAND; png_read_png(img.png_ptr, img.info_ptr, trafo , NULL); int bit_depth, interlace_type, compression_type, filter_method; png_get_IHDR(img.png_ptr, img.info_ptr, &img.width, &img.height, &bit_depth, &img.color_type, &interlace_type, &compression_type, &filter_method); if ((img.color_type & PNG_COLOR_MASK_COLOR)==0) { LogErr("%s: Grayscale image not supported",fname_inp.c_str()); fclose(pngfile); return ERR_BAD_FILE; } fclose(pngfile); if (img.color_type==PNG_COLOR_TYPE_PALETTE) { LogErr("Invalid format. This shouldn't happen. PNG_TRANSFORM_EXPAND transforms image to RGB."); return ERR_BAD_FILE; } if (img.color_type & PNG_COLOR_MASK_ALPHA) { img.col_bits = 32; } else { img.col_bits = 24; } return ERR_OK; }
bool read_png(char *name, int row_align, int *outStride, int *outWidth, int *outHeight, uint32_t **outData) { png_structp png_ptr; png_infop info_ptr; unsigned int sig_read = 0; int color_type, interlace_type; FILE *fp; if ((fp = fopen(name, "rb")) == NULL) return false; /* Create and initialize the png_struct * with the desired error handler * functions. If you want to use the * default stderr and longjump method, * you can supply NULL for the last * three parameters. We also supply the * the compiler header file version, so * that we know if the application * was compiled with a compatible version * of the library. REQUIRED */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fclose(fp); return false; } /* Allocate/initialize the memory * for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_read_struct(&png_ptr, NULL, NULL); return false; } /* Set error handling if you are * using the setjmp/longjmp method * (this is the normal method of * doing things with libpng). * REQUIRED unless you set up * your own error handlers in * the png_create_read_struct() * earlier. */ if (setjmp(png_jmpbuf(png_ptr))) { /* Free all of the memory associated * with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); /* If we get here, we had a * problem reading the file */ return false; } /* Set up the output control if * you are using standard C streams */ png_init_io(png_ptr, fp); /* If we have already * read some of the signature */ png_set_sig_bytes(png_ptr, sig_read); /* * If you have enough memory to read * in the entire image at once, and * you need to specify only * transforms that can be controlled * with one of the PNG_TRANSFORM_* * bits (this presently excludes * dithering, filling, setting * background, and doing gamma * adjustment), then you can read the * entire image (including pixels) * into the info structure with this * call * * PNG_TRANSFORM_STRIP_16 | * PNG_TRANSFORM_PACKING forces 8 bit * PNG_TRANSFORM_EXPAND forces to * expand a palette into RGB */ png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL); png_uint_32 width, height, stride; int bit_depth; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); unsigned int channels = png_get_channels(png_ptr, info_ptr); uint32_t *data = NULL; png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr); stride = (width * 4 + row_align - 1) & ~(row_align-1); data = malloc(stride * height); switch(channels) { case 3: /* Convert bytewise RGB to A8R8G8B8 */ for (int i = 0; i < height; i++) { for(int j = 0; j < width; j++) { data[(stride/4) * i + j] = 0xff000000 | (row_pointers[i][j*3 + 0] << 16) | (row_pointers[i][j*3 + 1] << 8) | (row_pointers[i][j*3 + 2]); } } break; case 4: /* Convert bytewise RGBA to A8R8G8B8 */ for (int i = 0; i < height; i++) { for(int j = 0; j < width; j++) { data[(stride/4) * i + j] = (row_pointers[i][j*3 + 3] << 24) | (row_pointers[i][j*3 + 0] << 16) | (row_pointers[i][j*3 + 1] << 8) | (row_pointers[i][j*3 + 2]); } } break; default: /* Invalid number of channels */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); free(data); return false; } /* Clean up after the read, * and free any memory allocated */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); /* Close the file */ fclose(fp); /* That's it */ *outWidth = width; *outHeight = height; *outStride = stride; *outData = data; return true; }
bool LoadPng(const char *name, int &iWidth, int &iHeight, bool &hasAlpha, GLubyte **outData) { FILE *fp = NULL; fp = fopen(name, "rb"); if (fp == NULL) { return false; } png_structp png_ptr; png_infop info_ptr; unsigned int sig_read = 0; int color_type, interlace_type; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fclose(fp); return false; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); return false; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(fp); return false; } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, sig_read); png_read_png(png_ptr, info_ptr, /*PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING |*/ PNG_TRANSFORM_EXPAND, png_voidp_NULL); iWidth = info_ptr->width; iHeight = info_ptr->height; switch (info_ptr->color_type) { case PNG_COLOR_TYPE_RGBA: hasAlpha = true; break; case PNG_COLOR_TYPE_RGB: hasAlpha = false; break; default: printf("color type %d is not supported \n ", info_ptr->color_type); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return false; } unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr); *outData = (unsigned char*)malloc(row_bytes * iHeight); png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr); for (int i = 0; i < iHeight; ++i) { memcpy(*outData + (row_bytes * (iHeight - 1- i)), row_pointers[i], row_bytes); } png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(fp); return true; }
void PngIO::read(IMAGEDATA& image, GLuint& type, const std::string& path) { FILE* file = std::fopen(path.c_str(), "rb"); if(file == 0) { throw std::runtime_error("Failed to open image file "+path); } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(png_ptr == 0) { fclose(file); throw std::runtime_error("Failed to create PNG data structure"); } png_infop info_ptr = png_create_info_struct(png_ptr); if(info_ptr == 0) { fclose(file); png_destroy_read_struct(&png_ptr, NULL, NULL); throw std::runtime_error("Failed to create PNG info data structure"); } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(file); /* If we get here, we had a * problem reading the file */ throw std::runtime_error("Problem reading image file "+path); } png_init_io(png_ptr, file); unsigned int sig_read = 0; png_set_sig_bytes(png_ptr, sig_read); // Read png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL); png_uint_32 width, height; int color_type, interlace_type; int bit_depth; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); // Set image parameters image.Width = width; image.Height = height; image.bpp = bit_depth; // Process color type switch(color_type) { case PNG_COLOR_TYPE_RGB: type = GL_RGB; break; case PNG_COLOR_TYPE_RGB_ALPHA: type = GL_RGBA; break; default: // Not supported png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(file); throw std::runtime_error("Unsupported PNG image format: Not RGB or RGB+alpha in file "+path); } unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr); image.pData.reserve(row_bytes * image.Height); unsigned char* dataPtr1 = & image.pData[0]; unsigned char** outData = & dataPtr1; png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr); for (int i = 0; i < image.Height; i++) { // note that png is ordered top to // bottom, but OpenGL expect it bottom to top // so the order or swapped memcpy(*outData+(row_bytes * (image.Height-1-i)), row_pointers[i], row_bytes); } /* Clean up after the read, * and free any memory allocated */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); /* Close the file */ fclose(file); }
RawImage* ImageFactory::loadPNG(const char *filename) { int outWidth, outHeight; bool outHasAlpha; png_structp png_ptr; png_infop info_ptr; unsigned int sig_read = 0; int color_type, interlace_type; FILE* fp = fopen(filename, "rb"); if (fp == NULL) return NULL; /* Create and initialize the png_struct * with the desired error handler * functions. If you want to use the * default stderr and longjump method, * you can supply NULL for the last * three parameters. We also supply the * the compiler header file version, so * that we know if the application * was compiled with a compatible version * of the library. REQUIRED */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fclose(fp); return NULL; } /* Allocate/initialize the memory * for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_read_struct(&png_ptr, NULL, NULL); return NULL; } /* Set error handling if you are * using the setjmp/longjmp method * (this is the normal method of * doing things with libpng). * REQUIRED unless you set up * your own error handlers in * the png_create_read_struct() * earlier. */ if (setjmp(png_jmpbuf(png_ptr))) { /* Free all of the memory associated * with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); /* If we get here, we had a * problem reading the file */ return NULL; } /* Set up the output control if * you are using standard C streams */ png_init_io(png_ptr, fp); /* If we have already * read some of the signature */ png_set_sig_bytes(png_ptr, sig_read); /* * If you have enough memory to read * in the entire image at once, and * you need to specify only * transforms that can be controlled * with one of the PNG_TRANSFORM_* * bits (this presently excludes * dithering, filling, setting * background, and doing gamma * adjustment), then you can read the * entire image (including pixels) * into the info structure with this * call * * PNG_TRANSFORM_STRIP_16 | * PNG_TRANSFORM_PACKING forces 8 bit * PNG_TRANSFORM_EXPAND forces to * expand a palette into RGB */ png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL); png_uint_32 width, height; int bit_depth; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); outWidth = width; outHeight = height; switch (color_type) { case PNG_COLOR_TYPE_RGBA: outHasAlpha = true; break; case PNG_COLOR_TYPE_RGB: outHasAlpha = false; break; default: printf("Color type %d not supported.", color_type); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return NULL; } unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr); //*outData = (unsigned char*) malloc(row_bytes * outHeight); GLubyte *outData = (unsigned char*) malloc(row_bytes * outHeight); png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr); for (int i = 0; i < outHeight; i++) { // note that png is ordered top to // bottom, but OpenGL expect it bottom to top // so the order or swapped memcpy(outData+(row_bytes * (outHeight-1-i)), row_pointers[i], row_bytes); } /* Clean up after the read, * and free any memory allocated */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); /* Close the file */ fclose(fp); /* That's it */ return new RawImage(outWidth, outHeight, outHasAlpha, outData); }
bool CCImage::_initWithPngData(void * pData, int nDatalen) { bool bRet = false; png_byte header[8] = {0}; png_structp png_ptr = 0; png_infop info_ptr = 0; unsigned char * pImateData = 0; do { // png header len is 8 bytes CC_BREAK_IF(nDatalen < 8); // check the data is png or not memcpy(header, pData, 8); CC_BREAK_IF(png_sig_cmp(header, 0, 8)); // init png_struct png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); CC_BREAK_IF(! png_ptr); // init png_info info_ptr = png_create_info_struct(png_ptr); CC_BREAK_IF(!info_ptr); #if (CC_TARGET_PLATFORM != CC_PLATFORM_BADA) CC_BREAK_IF(setjmp(png_jmpbuf(png_ptr))); #endif // set the read call back function tImageSource imageSource; imageSource.data = (unsigned char*)pData; imageSource.size = nDatalen; imageSource.offset = 0; png_set_read_fn(png_ptr, &imageSource, pngReadCallback); // read png // PNG_TRANSFORM_EXPAND: perform set_expand() // PNG_TRANSFORM_PACKING: expand 1, 2 and 4-bit samples to bytes // PNG_TRANSFORM_STRIP_16: strip 16-bit samples to 8 bits // PNG_TRANSFORM_GRAY_TO_RGB: expand grayscale samples to RGB (or GA to RGBA) png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_GRAY_TO_RGB, 0); int color_type = 0; png_uint_32 nWidth = 0; png_uint_32 nHeight = 0; int nBitsPerComponent = 0; png_get_IHDR(png_ptr, info_ptr, &nWidth, &nHeight, &nBitsPerComponent, &color_type, 0, 0, 0); // init image info m_bPreMulti = true; m_bHasAlpha = ( info_ptr->color_type & PNG_COLOR_MASK_ALPHA ) ? true : false; // allocate memory and read data int bytesPerComponent = 3; if (m_bHasAlpha) { bytesPerComponent = 4; } pImateData = new unsigned char[nHeight * nWidth * bytesPerComponent]; CC_BREAK_IF(! pImateData); png_bytep * rowPointers = png_get_rows(png_ptr, info_ptr); // copy data to image info int bytesPerRow = nWidth * bytesPerComponent; if(m_bHasAlpha) { unsigned int *tmp = (unsigned int *)pImateData; for(unsigned int i = 0; i < nHeight; i++) { for(int j = 0; j < bytesPerRow; j += 4) { *tmp++ = CC_RGB_PREMULTIPLY_APLHA( rowPointers[i][j], rowPointers[i][j + 1], rowPointers[i][j + 2], rowPointers[i][j + 3] ); } } } else { for (unsigned int j = 0; j < nHeight; ++j) { memcpy(pImateData + j * bytesPerRow, rowPointers[j], bytesPerRow); } } m_nBitsPerComponent = nBitsPerComponent; m_nHeight = (short)nHeight; m_nWidth = (short)nWidth; m_pData = pImateData; pImateData = 0; bRet = true; } while (0); CC_SAFE_DELETE_ARRAY(pImateData); if (png_ptr) { png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0); } return bRet; }