void set_filler(uint_32 filler, filler_type type) const { TRACE_IO_TRANSFORM("png_set_filler: filler=%08x, type=%d\n", filler, type); png_set_filler(m_png, filler, type); }
/* Since libpng forces us to use longjmp, this function shouldn't create any C++ * objects, and needs to watch out for memleaks. */ static bool RageSurface_Save_PNG( RageFile &f, char szErrorbuf[1024], RageSurface *pImgIn ) { bool bAlpha = pImgIn->format->Amask != 0; RageSurface *pImg; bool bDeleteImg = RageSurfaceUtils::ConvertSurface( pImgIn, pImg, pImgIn->w, pImgIn->h, 32, Swap32BE( 0xFF000000 ), Swap32BE( 0x00FF0000 ), Swap32BE( 0x0000FF00 ), Swap32BE( 0x000000FF ) ); if( !bDeleteImg ) pImg = pImgIn; error_info error; error.szErr = szErrorbuf; png_struct *pPng = png_create_write_struct( PNG_LIBPNG_VER_STRING, &error, PNG_Error, PNG_Warning ); if( pPng == NULL ) { sprintf( szErrorbuf, "creating png_create_write_struct failed"); return false; } png_info *pInfo = png_create_info_struct(pPng); if( pInfo == NULL ) { png_destroy_read_struct( &pPng, NULL, NULL ); if( bDeleteImg ) delete pImg; sprintf( szErrorbuf, "creating png_create_info_struct failed"); return false; } if( setjmp(png_jmpbuf(pPng)) ) { png_destroy_read_struct( &pPng, &pInfo, NULL ); return false; } png_set_write_fn( pPng, &f, RageFile_png_write, RageFile_png_flush ); png_set_compression_level( pPng, 1 ); png_set_IHDR( pPng, pInfo, pImg->w, pImg->h, 8, bAlpha? PNG_COLOR_TYPE_RGBA:PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE ); png_write_info( pPng, pInfo ); png_set_filler( pPng, 0, PNG_FILLER_AFTER ); png_byte *pixels = (png_byte *) pImg->pixels; for( int y = 0; y < pImg->h; y++ ) png_write_row( pPng, pixels + pImg->pitch*y ); png_write_end( pPng, pInfo ); png_destroy_write_struct( &pPng, &pInfo ); /* Free the converted image. */ if( bDeleteImg ) delete pImg; return true; }
/* Added to libpng-1.2.7 */ void PNGAPI png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc) { png_debug(1, "in png_set_add_alpha\n"); png_set_filler(png_ptr, filler, filler_loc); png_ptr->transformations |= PNG_ADD_ALPHA; }
void writePNG(const QImage& image) { #ifndef QT_LSB // LSB disallows accessing the info_ptr directly. LSB's png_set_IHDR sets // the channels anyways, so just comment it out for LSB usage info_ptr->channels = 4; #endif png_set_sig_bytes(png_ptr, 8); // Pretend we already wrote the sig png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(), 8, image.hasAlphaChannel() ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, 0, 0, 0); png_write_info(png_ptr, info_ptr); if (!image.hasAlphaChannel()) png_set_filler(png_ptr, 0, QSysInfo::ByteOrder == QSysInfo::BigEndian ? PNG_FILLER_BEFORE : PNG_FILLER_AFTER); //if ( QImage::systemByteOrder() == QImage::BigEndian ) { //png_set_swap_alpha(png_ptr); //} if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) { png_set_bgr(png_ptr); } int height = image.height(); png_bytep *row_pointers = new png_bytep[height]; for (int i = 0; i < height; ++i) row_pointers[i] = (png_bytep)image.scanLine(i); png_write_image(png_ptr, row_pointers); delete [] row_pointers; png_write_end(png_ptr, info_ptr); end_png(); begin_png(); }
/** * \brief encode an image to RGB(A) PNG format * \private \memberof mapcache_image_format_png * \sa mapcache_image_format::write() */ mapcache_buffer* _mapcache_imageio_png_encode(mapcache_context *ctx, mapcache_image *img, mapcache_image_format *format) { png_infop info_ptr; int color_type; size_t row; mapcache_buffer *buffer = NULL; int compression = ((mapcache_image_format_png*)format)->compression_level; png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); if (!png_ptr) { ctx->set_error(ctx, 500, "failed to allocate png_struct structure"); return NULL; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); ctx->set_error(ctx, 500, "failed to allocate png_info structure"); return NULL; } if (setjmp(png_jmpbuf(png_ptr))) { ctx->set_error(ctx, 500, "failed to setjmp(png_jmpbuf(png_ptr))"); png_destroy_write_struct(&png_ptr, &info_ptr); return NULL; } buffer = mapcache_buffer_create(5000,ctx->pool); png_set_write_fn(png_ptr, buffer, _mapcache_imageio_png_write_func, _mapcache_imageio_png_flush_func); if(mapcache_image_has_alpha(img)) color_type = PNG_COLOR_TYPE_RGB_ALPHA; else color_type = PNG_COLOR_TYPE_RGB; png_set_IHDR(png_ptr, info_ptr, img->w, img->h, 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if(compression == MAPCACHE_COMPRESSION_BEST) png_set_compression_level (png_ptr, Z_BEST_COMPRESSION); else if(compression == MAPCACHE_COMPRESSION_FAST) png_set_compression_level (png_ptr, Z_BEST_SPEED); png_write_info(png_ptr, info_ptr); if(color_type == PNG_COLOR_TYPE_RGB) png_set_filler(png_ptr, 255, PNG_FILLER_AFTER); png_bytep rowptr = img->data; for(row=0;row<img->h;row++) { png_write_row(png_ptr,rowptr); rowptr += img->stride; } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); return buffer; }
void read_png_file(char *filename) { FILE *fp = fopen(filename, "rb"); png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png) abort(); png_infop info = png_create_info_struct(png); if(!info) abort(); if(setjmp(png_jmpbuf(png))) abort(); png_init_io(png, fp); png_read_info(png, info); width = png_get_image_width(png, info); height = png_get_image_height(png, info); color_type = png_get_color_type(png, info); bit_depth = png_get_bit_depth(png, info); // Read any color_type into 8bit depth, RGBA format. // See http://www.libpng.org/pub/png/libpng-manual.txt if(bit_depth == 16) png_set_strip_16(png); if(color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); // PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth. if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png); if(png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png); // These color_type don't have an alpha channel then fill it with 0xff. if(color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE) png_set_filler(png, 0xFF, PNG_FILLER_AFTER); if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); png_read_update_info(png, info); row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height); int y ; for( y = 0; y < height; y++) { row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png,info)); } png_read_image(png, row_pointers); fclose(fp); }
static void nspng_setup_transforms(png_structp png_ptr, png_infop info_ptr) { int bit_depth, color_type; #if 0 int intent; double gamma; #endif bit_depth = png_get_bit_depth(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); /* Set up our transformations */ 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 (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); } if (!(color_type & PNG_COLOR_MASK_ALPHA)) { png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); } #if 0 /* gamma correction - we use 2.2 as our screen gamma * this appears to be correct (at least in respect to !Browse) * see http://www.w3.org/Graphics/PNG/all_seven.html for a test case */ if (png_get_sRGB(png_ptr, info_ptr, &intent)) { png_set_gamma(png_ptr, 2.2, 0.45455); } else { if (png_get_gAMA(png_ptr, info_ptr, &gamma)) { png_set_gamma(png_ptr, 2.2, gamma); } else { png_set_gamma(png_ptr, 2.2, 0.45455); } } #endif png_read_update_info(png_ptr, info_ptr); }
static CogFrame * cog_frame_new_from_png (void *data, int size) { struct png_data_struct s = { 0 }; png_structp png_ptr; png_infop info_ptr; png_bytep *rows; CogFrame *frame; guchar *frame_data; int j; int width, height; int color_type; png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info_ptr = png_create_info_struct (png_ptr); s.data = data; s.size = size; png_set_read_fn (png_ptr, (void *) &s, read_data); 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); GST_DEBUG ("PNG size %dx%d color_type %d", width, height, color_type); png_set_strip_16 (png_ptr); png_set_packing (png_ptr); if (color_type == PNG_COLOR_TYPE_RGB) { png_set_filler (png_ptr, 0xff, PNG_FILLER_BEFORE); } if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) { png_set_swap_alpha (png_ptr); } frame_data = g_malloc (width * height * 4); frame = cog_frame_new_from_data_ARGB (frame_data, width, height); frame->regions[0] = frame_data; rows = (png_bytep *) g_malloc (sizeof (png_bytep) * height); for (j = 0; j < height; j++) { rows[j] = COG_FRAME_DATA_GET_LINE (frame->components + 0, j); } png_read_image (png_ptr, rows); g_free (rows); png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL); return frame; }
/** * @brief Initializes the npng. */ static int npng_info( npng_t *npng ) { png_uint_32 width, height; int bit_depth, color_type, interlace_type; /*double display_exponent, gamma;*/ /* Read information. */ png_read_info( npng->png_ptr, npng->info_ptr ); /* Read header stuff. */ png_get_IHDR( npng->png_ptr, npng->info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL ); /* Set Interlace handling if necessary. */ if (interlace_type != PNG_INTERLACE_NONE) png_set_interlace_handling( npng->png_ptr ); /* Strip down from 16 bit to 8 bit. */ png_set_strip_16( npng->png_ptr ); /* Extract small bits into separate bytes. */ png_set_packing( npng->png_ptr ); /* Expand palette to RGB. */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand( npng->png_ptr ); /* Expand low bit grayscale to 8 bit. */ if ((color_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8)) png_set_expand( npng->png_ptr ); /* Expand tRNS data to alpha channel. */ if (png_get_valid( npng->png_ptr, npng->info_ptr, PNG_INFO_tRNS) ) png_set_expand( npng->png_ptr ); /* Set grayscale to 8 bits. */ if ((color_type == PNG_COLOR_TYPE_GRAY) || (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) png_set_gray_to_rgb( npng->png_ptr ); /* Set gamma. */ /*if (png_get_gAMA( npng->png_ptr, info_ptr, &gamma) ) png_set_gamma( npng->png_ptr, display_exponent, gamma );*/ /* Fill alpha. */ png_set_filler( npng->png_ptr, 0xff, PNG_FILLER_AFTER ); /* Update information. */ png_read_update_info( npng->png_ptr, npng->info_ptr ); /* Success. */ return 0; }
/* Since libpng forces us to use longjmp, this function shouldn't create any C++ * objects, and needs to watch out for memleaks. */ bool SavePNG( FILE *f, char szErrorbuf[1024], const Surface *pSurf ) { /* RageSurfaceUtils::ConvertSurface( pImgIn, pImg, pImgIn->w, pImgIn->h, 32, Swap32BE( 0xFF000000 ), Swap32BE( 0x00FF0000 ), Swap32BE( 0x0000FF00 ), Swap32BE( 0x000000FF ) ); */ error_info error; error.szErr = szErrorbuf; png_struct *pPng = png_create_write_struct( PNG_LIBPNG_VER_STRING, &error, PNG_Error, PNG_Warning ); if( pPng == NULL ) { sprintf( szErrorbuf, "creating png_create_write_struct failed"); return false; } png_info *pInfo = png_create_info_struct(pPng); if( pInfo == NULL ) { png_destroy_read_struct( &pPng, NULL, NULL ); sprintf( szErrorbuf, "creating png_create_info_struct failed"); return false; } if( setjmp(pPng->jmpbuf) ) { png_destroy_read_struct( &pPng, &pInfo, png_infopp_NULL ); return false; } png_set_write_fn( pPng, f, File_png_write, File_png_flush ); png_set_compression_level( pPng, 1 ); png_set_IHDR( pPng, pInfo, pSurf->iWidth, pSurf->iHeight, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE ); png_write_info( pPng, pInfo ); png_set_filler( pPng, 0, PNG_FILLER_AFTER ); png_byte *pixels = (png_byte *) pSurf->pRGBA; for( int y = 0; y < pSurf->iHeight; y++ ) png_write_row( pPng, pixels + pSurf->iPitch*y ); png_write_end( pPng, pInfo ); png_destroy_write_struct( &pPng, &pInfo ); return true; }
static void info_callback(png_structp png, png_infop info) { int bit_depth, color_type, interlace, intent; double gamma; png_uint_32 width, height; /* Read the PNG details */ png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, &interlace, 0, 0); /* Set up our transformations */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png); if (png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png); if (bit_depth == 16) png_set_strip_16(png); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); if (!(color_type & PNG_COLOR_MASK_ALPHA)) png_set_filler(png, 0xff, PNG_FILLER_AFTER); /* gamma correction - we use 2.2 as our screen gamma * this appears to be correct (at least in respect to !Browse) * see http://www.w3.org/Graphics/PNG/all_seven.html for a test case */ if (png_get_sRGB(png, info, &intent)) png_set_gamma(png, 2.2, 0.45455); else { if (png_get_gAMA(png, info, &gamma)) png_set_gamma(png, 2.2, gamma); else png_set_gamma(png, 2.2, 0.45455); } png_read_update_info(png, info); rowbytes = png_get_rowbytes(png, info); interlace = (interlace == PNG_INTERLACE_ADAM7); raw_width = width; raw_height = height; rowstride = raw_width * 4; bitmap_data = malloc(rowstride * raw_height); }
bool SkPngEncoderMgr::writeInfo(const SkImageInfo& srcInfo) { if (setjmp(png_jmpbuf(fPngPtr))) { return false; } png_write_info(fPngPtr, fInfoPtr); if (kRGBA_F16_SkColorType == srcInfo.colorType() && kOpaque_SkAlphaType == srcInfo.alphaType()) { // For kOpaque, kRGBA_F16, we will keep the row as RGBA and tell libpng // to skip the alpha channel. png_set_filler(fPngPtr, 0, PNG_FILLER_AFTER); } return true; }
void _gTexLoadPNG(FILE* fp, gImage* tex) { 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, x, y; u32* line; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); png_set_error_fn(png_ptr,NULL,NULL,NULL); info_ptr = png_create_info_struct(png_ptr); png_init_io(png_ptr,fp); png_set_sig_bytes(png_ptr,sig_read); png_read_info(png_ptr,info_ptr); png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth,&color_type, &interlace_type,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_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); png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); tex->w = width; tex->h = height; tex->tw = _getNextPower2(width); tex->th = _getNextPower2(height); tex->ratio = (float)width / height; tex->data = memalign(16, tex->tw * tex->th * sizeof(gColor)); line = malloc(width * 4); for (y = 0; y < height; y++) { png_read_row(png_ptr, (u8*) line, png_bytep_NULL); for (x = 0; x < width; x++) { u32 color = line[x]; tex->data[x + y * tex->tw] = color; } } free(line); png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); }
static void readRgb( PngInfo& info, unsigned width, unsigned height, bool update ){ //Apply transparency information bool alpha = info.isGrayAlpha() || info.isRgbAlpha(); if( png_get_valid( info.png, info.info, PNG_INFO_tRNS ) ){ png_set_tRNS_to_alpha( info.png ); alpha = true; } //Convert Grayscale if( info.isGray() || info.isGrayAlpha() ) png_set_gray_to_rgb( info.png ); //Use the format BGRA info.force8bit(); png_set_filler( info.png, 255, PNG_FILLER_AFTER ); png_set_bgr( info.png ); //Initialize image auto format = alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32; info.read( width, height, format, update ); }
/* This function is called (as set by png_set_progressive_read_fn() above) when enough data has been supplied so all of the header has been read. */ void info_callback(png_structp png_ptr, png_infop info) { file_end=0; width = png_get_image_width(png_ptr,info); height = png_get_image_height(png_ptr,info); pixel_depth = png_get_bit_depth(png_ptr,info); channels = png_get_channels(png_ptr,info); color_type = png_get_color_type(png_ptr,info); if(color_type == PNG_COLOR_TYPE_GRAY) {} if(color_type == PNG_COLOR_TYPE_GRAY_ALPHA){} if(color_type == PNG_COLOR_TYPE_RGB) {} if(color_type == PNG_COLOR_TYPE_RGB_ALPHA) {} if(color_type == PNG_COLOR_TYPE_PALETTE ) { int r = png_get_PLTE(png_ptr,info,&palette,&num_palette); if(r == 0) { } png_uint_16p histogram = NULL; png_get_hIST(png_ptr, info, &histogram); png_set_expand(png_ptr); png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); png_read_update_info(png_ptr, info); pixel_depth = 8; } int row_bytes = png_get_rowbytes(png_ptr,info); row_pointers = malloc(sizeof(png_bytep *) * height); for(size_t n=0;n<height;n++) { row_pointers[n] = malloc(row_bytes); } png_start_read_image(png_ptr); }
void LoadPNGBuffer(byte * data, byte ** pic, int *width, int *height) { int bit_depth; int color_type; png_uint_32 w; png_uint_32 h; unsigned int row; size_t rowbytes; png_infop info; png_structp png; png_bytep *row_pointers; byte *out; int size; byte alphaByte = 255; // load png // size = ri.FS_ReadFile(name, (void **)&data); if(!data) return; //png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, png_user_error_fn, png_user_warning_fn); if(!png) { Sys_FPrintf(SYS_WRN, "LoadPNGBuffer: png_create_write_struct() failed\n"); //free(data); return; } // allocate/initialize the memory for image information. REQUIRED info = png_create_info_struct(png); if(!info) { Sys_FPrintf(SYS_WRN, "LoadPNGBuffer: png_create_info_struct() failed\n"); //free(data); png_destroy_read_struct(&png, (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. // if(setjmp(png_jmpbuf(png))) { // if we get here, we had a problem reading the file Sys_FPrintf(SYS_WRN, "LoadPNGBuffer: first exception handler called\n"); //free(data); png_destroy_read_struct(&png, (png_infopp) & info, (png_infopp) NULL); return; } //png_set_write_fn(png, buffer, png_write_data, png_flush_data); png_set_read_fn(png, data, png_read_data); png_set_sig_bytes(png, 0); // 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, info); // get picture info png_get_IHDR(png, info, (png_uint_32 *) & w, (png_uint_32 *) & h, &bit_depth, &color_type, NULL, NULL, NULL); // tell libpng to strip 16 bit/color files down to 8 bits/color png_set_strip_16(png); // expand paletted images to RGB triplets if(color_type & PNG_COLOR_MASK_PALETTE) png_set_expand(png); // expand gray-scaled images to RGB triplets if(!(color_type & PNG_COLOR_MASK_COLOR)) png_set_gray_to_rgb(png); // 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_gray_1_2_4_to_8(png); // 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, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png); // if there is no alpha information, fill with alphaByte if(!(color_type & PNG_COLOR_MASK_ALPHA)) png_set_filler(png, alphaByte, PNG_FILLER_AFTER); // expand pictures with less than 8bpp to 8bpp if(bit_depth < 8) png_set_packing(png); // update structure with the above settings png_read_update_info(png, info); // allocate the memory to hold the image *width = w; *height = h; *pic = out = (byte *) safe_malloc(w * h * 4); row_pointers = (png_bytep *) safe_malloc(sizeof(png_bytep) * h); // set a new exception handler if(setjmp(png_jmpbuf(png))) { Sys_FPrintf(SYS_WRN, "LoadPNGBuffer: second exception handler called\n"); free(row_pointers); //free(data); png_destroy_read_struct(&png, (png_infopp) & info, (png_infopp) NULL); return; } rowbytes = png_get_rowbytes(png, info); for(row = 0; row < h; row++) row_pointers[row] = (png_bytep) (out + (row * 4 * w)); // read image data png_read_image(png, row_pointers); // read rest of file, and get additional chunks in info png_read_end(png, info); // clean up after the read, and free any memory allocated png_destroy_read_struct(&png, &info, (png_infopp) NULL); free(row_pointers); //free(data); }
bool MCImageEncodePNG(MCImageBitmap *p_bitmap, IO_handle p_stream, uindex_t &r_bytes_written) { bool t_success = true; MCPNGWriteContext t_context; t_context.stream = p_stream; t_context.byte_count = 0; png_structp t_png_ptr = nil; png_infop t_info_ptr = nil; png_color *t_png_palette = nil; png_byte *t_png_transparency = nil; png_bytep t_data_ptr = nil; uindex_t t_stride = 0; MCImageIndexedBitmap *t_indexed = nil; if (MCImageConvertBitmapToIndexed(p_bitmap, false, t_indexed)) { t_success = MCImageEncodePNG(t_indexed, p_stream, r_bytes_written); MCImageFreeIndexedBitmap(t_indexed); return t_success; } /*init png stuff*/ if (t_success) { t_success = nil != (t_png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL)); } if (t_success) t_success = nil != (t_info_ptr = png_create_info_struct(t_png_ptr)); /*in case of png error*/ if (setjmp(png_jmpbuf(t_png_ptr))) t_success = false; if (t_success) png_set_write_fn(t_png_ptr,(png_voidp)&t_context,fakewrite,fakeflush); bool t_fully_opaque = true; if (t_success) { t_fully_opaque = !MCImageBitmapHasTransparency(p_bitmap); png_set_IHDR(t_png_ptr, t_info_ptr, p_bitmap->width, p_bitmap->height, 8, t_fully_opaque ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_gAMA(t_png_ptr, t_info_ptr, 1/MCgamma); } if (t_success) { png_write_info(t_png_ptr, t_info_ptr); //32 bit compensate for byte swapped systems if (t_fully_opaque) png_set_filler(t_png_ptr, 0, MCswapbytes ? PNG_FILLER_AFTER : PNG_FILLER_BEFORE); if (MCswapbytes) png_set_bgr(t_png_ptr); else png_set_swap_alpha(t_png_ptr); } if (t_success) { t_data_ptr = (png_bytep)p_bitmap->data; t_stride = p_bitmap->stride; } if (t_success) { for (uindex_t i = 0; i < p_bitmap->height; i++) { png_write_row(t_png_ptr, t_data_ptr); t_data_ptr += t_stride; } } if (t_success) png_write_end(t_png_ptr, t_info_ptr); if (t_png_ptr != nil) png_destroy_write_struct(&t_png_ptr, &t_info_ptr); if (t_png_palette != nil) MCMemoryDeleteArray(t_png_palette); if (t_png_transparency != nil) MCMemoryDeallocate(t_png_transparency); if (t_success) r_bytes_written = t_context.byte_count; return t_success; }
FloatPixMapRef FPMCreateWithPNGCustom(png_voidp ioPtr, png_rw_ptr readDataFn, FPMGammaFactor desiredGamma, FPMPNGErrorHandler errorHandler) { png_structp png = NULL; png_infop pngInfo = NULL; png_infop pngEndInfo = NULL; FloatPixMapRef result = NULL; png_uint_32 i, width, height, rowBytes; int depth, colorType; png_bytepp rows = NULL; void *data = NULL; png = png_create_read_struct(PNG_LIBPNG_VER_STRING, errorHandler, PNGError, PNGWarning); if (png == NULL) goto FAIL; pngInfo = png_create_info_struct(png); if (pngInfo == NULL) goto FAIL; pngEndInfo = png_create_info_struct(png); if (pngEndInfo == NULL) goto FAIL; if (setjmp(png_jmpbuf(png))) { // libpng will jump here on error. goto FAIL; } png_set_read_fn(png, ioPtr, readDataFn); png_read_info(png, pngInfo); if (!png_get_IHDR(png, pngInfo, &width, &height, &depth, &colorType, NULL, NULL, NULL)) goto FAIL; #if __LITTLE_ENDIAN__ if (depth == 16) png_set_swap(png); #endif if (depth <= 8 && !(colorType & PNG_COLOR_MASK_ALPHA)) { png_set_filler(png, 0xFF, PNG_FILLER_AFTER); } png_set_gray_to_rgb(png); if (depth < 8) { png_set_packing(png); png_set_expand(png); } png_read_update_info(png, pngInfo); rowBytes = png_get_rowbytes(png, pngInfo); rows = malloc(sizeof *rows * height); data = malloc(rowBytes * height); if (rows == NULL || data == NULL) goto FAIL; // Set up row pointers. for (i = 0; i < height; i++) { rows[i] = (png_bytep)data + i * rowBytes; } png_read_image(png, rows); png_read_end(png, pngEndInfo); free(rows); result = ConvertPNGData(data, width, height, rowBytes, png_get_bit_depth(png, pngInfo), png_get_color_type(png, pngInfo)); if (result != NULL) { double invGamma = 1.0/kFPMGammaSRGB; png_get_gAMA(png, pngInfo, &invGamma); FPMApplyGamma(result, 1.0/invGamma, desiredGamma, png_get_bit_depth(png, pngInfo) == 16 ? 65536 : 256); } png_destroy_read_struct(&png, &pngInfo, &pngEndInfo); free(data); return result; FAIL: FPMRelease(&result); if (png != NULL) png_destroy_read_struct(&png, &pngInfo, &pngEndInfo); free(rows); free(data); return NULL; }
pngquant_error rwpng_read_image24(FILE *infile, png24_image *mainprog_ptr) { png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 i; png_size_t rowbytes; int color_type, bit_depth; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr, rwpng_error_handler, NULL); if (!png_ptr) { return PNG_OUT_OF_MEMORY_ERROR; /* out of memory */ } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); return PNG_OUT_OF_MEMORY_ERROR; /* out of memory */ } /* setjmp() must be called in every function that calls a non-trivial * libpng function */ if (setjmp(mainprog_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return LIBPNG_FATAL_ERROR; /* fatal libpng error (via longjmp()) */ } struct rwpng_read_data read_data = {infile, 0}; png_set_read_fn(png_ptr, &read_data, user_read_data); png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ /* alternatively, could make separate calls to png_get_image_width(), * etc., but want bit_depth and color_type for later [don't care about * compression_type and filter_type => NULLs] */ png_get_IHDR(png_ptr, info_ptr, &mainprog_ptr->width, &mainprog_ptr->height, &bit_depth, &color_type, NULL, NULL, NULL); /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits, * transparency chunks to full alpha channel; strip 16-bit-per-sample * images to 8 bits per sample; and convert grayscale to RGB[A] */ /* GRR TO DO: preserve all safe-to-copy ancillary PNG chunks */ if (!(color_type & PNG_COLOR_MASK_ALPHA)) { #ifdef PNG_READ_FILLER_SUPPORTED /* GRP: expand palette to RGB, and grayscale or RGB to GA or RGBA */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); png_set_filler(png_ptr, 65535L, PNG_FILLER_AFTER); #else fprintf(stderr, "pngquant readpng: image is neither RGBA nor GA\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); mainprog_ptr->retval = 26; return mainprog_ptr->retval; #endif } /* 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); /* get and save the gamma info (if any) for writing */ double gamma; mainprog_ptr->gamma = png_get_gAMA(png_ptr, info_ptr, &gamma) ? gamma : 0.45455f; png_set_interlace_handling(png_ptr); /* all transformations have been registered; now update info_ptr data, * get rowbytes and channels, and allocate image memory */ png_read_update_info(png_ptr, info_ptr); rowbytes = png_get_rowbytes(png_ptr, info_ptr); if ((mainprog_ptr->rgba_data = malloc(rowbytes*mainprog_ptr->height)) == NULL) { fprintf(stderr, "pngquant readpng: unable to allocate image data\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return PNG_OUT_OF_MEMORY_ERROR; } if ((mainprog_ptr->row_pointers = (png_bytepp)malloc(mainprog_ptr->height*sizeof(png_bytep))) == NULL) { fprintf(stderr, "pngquant readpng: unable to allocate row pointers\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); free(mainprog_ptr->rgba_data); mainprog_ptr->rgba_data = NULL; return PNG_OUT_OF_MEMORY_ERROR; } /* set the individual row_pointers to point at the correct offsets */ for (i = 0; i < mainprog_ptr->height; ++i) mainprog_ptr->row_pointers[i] = mainprog_ptr->rgba_data + i*rowbytes; /* now we can go ahead and just read the whole image */ png_read_image(png_ptr, (png_bytepp)mainprog_ptr->row_pointers); /* and we're done! (png_read_end() can be omitted if no processing of * post-IDAT text/time/etc. is desired) */ png_read_end(png_ptr, NULL); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); mainprog_ptr->file_size = read_data.bytes_read; return SUCCESS; }
Load_SBit_Png( FT_GlyphSlot slot, FT_Int x_offset, FT_Int y_offset, FT_Int pix_bits, TT_SBit_Metrics metrics, FT_Memory memory, FT_Byte* data, FT_UInt png_len, FT_Bool populate_map_and_metrics ) { FT_Bitmap *map = &slot->bitmap; FT_Error error = FT_Err_Ok; FT_StreamRec stream; png_structp png; png_infop info; png_uint_32 imgWidth, imgHeight; int bitdepth, color_type, interlace; FT_Int i; png_byte* *rows = NULL; /* pacify compiler */ if ( x_offset < 0 || y_offset < 0 ) { error = FT_THROW( Invalid_Argument ); goto Exit; } if ( !populate_map_and_metrics && ( x_offset + metrics->width > map->width || y_offset + metrics->height > map->rows || pix_bits != 32 || map->pixel_mode != FT_PIXEL_MODE_BGRA ) ) { error = FT_THROW( Invalid_Argument ); goto Exit; } FT_Stream_OpenMemory( &stream, data, png_len ); png = png_create_read_struct( PNG_LIBPNG_VER_STRING, &error, error_callback, warning_callback ); if ( !png ) { error = FT_THROW( Out_Of_Memory ); goto Exit; } info = png_create_info_struct( png ); if ( !info ) { error = FT_THROW( Out_Of_Memory ); png_destroy_read_struct( &png, NULL, NULL ); goto Exit; } if ( ft_setjmp( png_jmpbuf( png ) ) ) { error = FT_THROW( Invalid_File_Format ); goto DestroyExit; } png_set_read_fn( png, &stream, read_data_from_FT_Stream ); png_read_info( png, info ); png_get_IHDR( png, info, &imgWidth, &imgHeight, &bitdepth, &color_type, &interlace, NULL, NULL ); if ( error || ( !populate_map_and_metrics && ( (FT_Int)imgWidth != metrics->width || (FT_Int)imgHeight != metrics->height ) ) ) goto DestroyExit; if ( populate_map_and_metrics ) { FT_Long size; metrics->width = (FT_Int)imgWidth; metrics->height = (FT_Int)imgHeight; map->width = metrics->width; map->rows = metrics->height; map->pixel_mode = FT_PIXEL_MODE_BGRA; map->pitch = map->width * 4; map->num_grays = 256; size = map->rows * map->pitch; error = ft_glyphslot_alloc_bitmap( slot, size ); if ( error ) goto DestroyExit; } /* convert palette/gray image to rgb */ if ( color_type == PNG_COLOR_TYPE_PALETTE ) png_set_palette_to_rgb( png ); /* expand gray bit depth if needed */ if ( color_type == PNG_COLOR_TYPE_GRAY ) { #if PNG_LIBPNG_VER >= 10209 png_set_expand_gray_1_2_4_to_8( png ); #else png_set_gray_1_2_4_to_8( png ); #endif } /* transform transparency to alpha */ if ( png_get_valid(png, info, PNG_INFO_tRNS ) ) png_set_tRNS_to_alpha( png ); if ( bitdepth == 16 ) png_set_strip_16( png ); if ( bitdepth < 8 ) png_set_packing( png ); /* convert grayscale to RGB */ if ( color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) png_set_gray_to_rgb( png ); if ( interlace != PNG_INTERLACE_NONE ) png_set_interlace_handling( png ); png_set_filler( png, 0xFF, PNG_FILLER_AFTER ); /* recheck header after setting EXPAND options */ png_read_update_info(png, info ); png_get_IHDR( png, info, &imgWidth, &imgHeight, &bitdepth, &color_type, &interlace, NULL, NULL ); if ( bitdepth != 8 || !( color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA ) ) { error = FT_THROW( Invalid_File_Format ); goto DestroyExit; } switch ( color_type ) { default: /* Shouldn't happen, but fall through. */ case PNG_COLOR_TYPE_RGB_ALPHA: png_set_read_user_transform_fn( png, premultiply_data ); break; case PNG_COLOR_TYPE_RGB: /* Humm, this smells. Carry on though. */ png_set_read_user_transform_fn( png, convert_bytes_to_data ); break; } if ( FT_NEW_ARRAY( rows, imgHeight ) ) { error = FT_THROW( Out_Of_Memory ); goto DestroyExit; } for ( i = 0; i < (FT_Int)imgHeight; i++ ) rows[i] = map->buffer + ( y_offset + i ) * map->pitch + x_offset * 4; png_read_image( png, rows ); FT_FREE( rows ); png_read_end( png, info ); DestroyExit: png_destroy_read_struct( &png, &info, NULL ); FT_Stream_Close( &stream ); Exit: return error; }
bool PNGLoader::doDecodeImage(const byte *fileDataPtr, uint fileSize, byte *&uncompressedDataPtr, int &width, int &height, int &pitch) { #ifndef USE_INTERNAL_PNG_DECODER png_structp png_ptr = NULL; png_infop info_ptr = NULL; int bitDepth; int colorType; int interlaceType; int i; // Check for valid PNG signature if (!doIsCorrectImageFormat(fileDataPtr, fileSize)) { error("png_check_sig failed"); } // Create both PNG structures png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { error("Could not create libpng read struct."); } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { error("Could not create libpng info struct."); } // Use alternative reading function const byte **ref = &fileDataPtr; png_set_read_fn(png_ptr, (void *)ref, png_user_read_data); // Read PNG header png_read_info(png_ptr, info_ptr); // Read out PNG informations png_uint_32 w, h; png_get_IHDR(png_ptr, info_ptr, &w, &h, &bitDepth, &colorType, &interlaceType, NULL, NULL); width = w; height = h; // Calculate pitch of output image pitch = GraphicEngine::calcPitch(GraphicEngine::CF_ARGB32, width); // Allocate memory for the final image data. // To keep memory framentation low this happens before allocating memory for temporary image data. uncompressedDataPtr = new byte[pitch * height]; if (!uncompressedDataPtr) { error("Could not allocate memory for output image."); } // Images of all color formates will be transformed into ARGB images if (bitDepth == 16) png_set_strip_16(png_ptr); if (colorType == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); if (bitDepth < 8) png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); png_set_bgr(png_ptr); if (colorType != PNG_COLOR_TYPE_RGB_ALPHA) png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); // After the transformations have been registered, the image data is read again. png_read_update_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &w, &h, &bitDepth, &colorType, NULL, NULL, NULL); width = w; height = h; if (interlaceType == PNG_INTERLACE_NONE) { // PNGs without interlacing can simply be read row by row. for (i = 0; i < height; i++) { png_read_row(png_ptr, uncompressedDataPtr + i * pitch, NULL); } } else { // PNGs with interlacing require us to allocate an auxillary // buffer with pointers to all row starts. // Allocate row pointer buffer png_bytep *pRowPtr = new png_bytep[height]; if (!pRowPtr) { error("Could not allocate memory for row pointers."); } // Initialize row pointers for (i = 0; i < height; i++) pRowPtr[i] = uncompressedDataPtr + i * pitch; // Read image data png_read_image(png_ptr, pRowPtr); // Free row pointer buffer delete[] pRowPtr; } // Read additional data at the end. png_read_end(png_ptr, NULL); // Destroy libpng structures png_destroy_read_struct(&png_ptr, &info_ptr, NULL); #else Common::MemoryReadStream *fileStr = new Common::MemoryReadStream(fileDataPtr, fileSize, DisposeAfterUse::NO); Graphics::PNG *png = new Graphics::PNG(); if (!png->read(fileStr)) // the fileStr pointer, and thus pFileData will be deleted after this is done error("Error while reading PNG image"); Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); Graphics::Surface *pngSurface = png->getSurface(format); width = pngSurface->w; height = pngSurface->h; uncompressedDataPtr = new byte[pngSurface->pitch * pngSurface->h]; memcpy(uncompressedDataPtr, (byte *)pngSurface->pixels, pngSurface->pitch * pngSurface->h); pngSurface->free(); delete pngSurface; delete png; #endif // Signal success return true; }
static void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float screen_gamma=0.0) { if (screen_gamma != 0.0 && png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) { double file_gamma; png_get_gAMA(png_ptr, info_ptr, &file_gamma); png_set_gamma(png_ptr, screen_gamma, file_gamma); } png_uint_32 width; png_uint_32 height; int bit_depth; int color_type; png_bytep trans_alpha = 0; png_color_16p trans_color_p = 0; int num_trans; png_colorp palette = 0; int num_palette; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); png_set_interlace_handling(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY) { // Black & White or 8-bit grayscale if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) { png_set_invert_mono(png_ptr); png_read_update_info(png_ptr, info_ptr); if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) { image = QImage(width, height, QImage::Format_Mono); if (image.isNull()) return; } image.setColorCount(2); image.setColor(1, qRgb(0,0,0)); image.setColor(0, qRgb(255,255,255)); } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_expand(png_ptr); png_set_strip_16(png_ptr); png_set_gray_to_rgb(png_ptr); if (image.size() != QSize(width, height) || image.format() != QImage::Format_ARGB32) { image = QImage(width, height, QImage::Format_ARGB32); if (image.isNull()) return; } if (QSysInfo::ByteOrder == QSysInfo::BigEndian) png_set_swap_alpha(png_ptr); png_read_update_info(png_ptr, info_ptr); } else { if (bit_depth == 16) png_set_strip_16(png_ptr); else if (bit_depth < 8) png_set_packing(png_ptr); int ncols = bit_depth < 8 ? 1 << bit_depth : 256; png_read_update_info(png_ptr, info_ptr); if (image.size() != QSize(width, height) || image.format() != QImage::Format_Indexed8) { image = QImage(width, height, QImage::Format_Indexed8); if (image.isNull()) return; } image.setColorCount(ncols); for (int i=0; i<ncols; i++) { int c = i*255/(ncols-1); image.setColor(i, qRgba(c,c,c,0xff)); } if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) { const int g = trans_color_p->gray; if (g < ncols) { image.setColor(g, 0); } } } } else if (color_type == PNG_COLOR_TYPE_PALETTE && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) && num_palette <= 256) { // 1-bit and 8-bit color if (bit_depth != 1) png_set_packing(png_ptr); png_read_update_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); QImage::Format format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8; if (image.size() != QSize(width, height) || image.format() != format) { image = QImage(width, height, format); if (image.isNull()) return; } png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); image.setColorCount(num_palette); int i = 0; if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) { while (i < num_trans) { image.setColor(i, qRgba( palette[i].red, palette[i].green, palette[i].blue, trans_alpha[i] ) ); i++; } } while (i < num_palette) { image.setColor(i, qRgba( palette[i].red, palette[i].green, palette[i].blue, 0xff ) ); i++; } } else { // 32-bit if (bit_depth == 16) png_set_strip_16(png_ptr); png_set_expand(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); QImage::Format format = QImage::Format_ARGB32; // Only add filler if no alpha, or we can get 5 channel data. if (!(color_type & PNG_COLOR_MASK_ALPHA) && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_filler(png_ptr, 0xff, QSysInfo::ByteOrder == QSysInfo::BigEndian ? PNG_FILLER_BEFORE : PNG_FILLER_AFTER); // We want 4 bytes, but it isn't an alpha channel format = QImage::Format_RGB32; } if (image.size() != QSize(width, height) || image.format() != format) { image = QImage(width, height, format); if (image.isNull()) return; } if (QSysInfo::ByteOrder == QSysInfo::BigEndian) png_set_swap_alpha(png_ptr); png_read_update_info(png_ptr, info_ptr); } // Qt==ARGB==Big(ARGB)==Little(BGRA) if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) { png_set_bgr(png_ptr); } }
s_screen *pngToScreen(const void *data) { 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, y; u32 *line; s_screen *image; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(png_ptr == NULL) { goto error; } png_set_error_fn(png_ptr, (png_voidp) NULL, (png_error_ptr) NULL, png_warning_fn); info_ptr = png_create_info_struct(png_ptr); if(info_ptr == NULL) { goto error2; } if(setjmp(png_jmpbuf(png_ptr))) { goto error2; } png_set_read_fn(png_ptr, &data, png_read_fn); png_set_sig_bytes(png_ptr, sig_read); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, 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 WII png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE); #else png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); #endif image = allocscreen(width, height, PIXEL_32); if(image == NULL) { goto error2; } line = (u32 *)image->data; for(y = 0; y < height; y++) { png_read_row(png_ptr, (u8 *) line, NULL); line += width; } png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return image; error2: png_destroy_read_struct(&png_ptr, NULL, NULL); error: return NULL; }
void LinuxAppPlatform::loadPNG(ImageData& imgData, const std::string& path, bool b) { std::cout << "loadPNG: " << path << "(from assets: " << b << ")" << "\n"; FILE* file = fopen(getImagePath(path, b).c_str(), "rb"); if (file == NULL) { std::cout << "failed to open file\n"; return; } png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) { std::cout << "png_create_read_struct failed\n"; abort(); return; } png_infop info = png_create_info_struct(png); if (!info) { std::cout << "png_create_info_struct failed\n"; abort(); return; } unsigned char header[8]; if(fread(header, 8, 1, file) != 1) { std::cout << "failed to read png header\n"; return; } if(png_sig_cmp(header, 0, 8)) { std::cout << "header is invalid\n"; return; } if (setjmp(png_jmpbuf(png))) { std::cout << "failed to load png\n"; abort(); return; } png_init_io(png, file); png_set_sig_bytes(png, 8); png_read_info(png, info); imgData.w = (int) png_get_image_width(png, info); imgData.h = (int) png_get_image_height(png, info); imgData.format = TextureFormat::U8888; imgData.mipLevel = 0; png_byte bitDepth = png_get_bit_depth(png, info); png_byte colorType = png_get_color_type(png, info); switch(colorType){ case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(png); break; case PNG_COLOR_TYPE_RGB: if(png_get_valid(png, info, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png); } else { png_set_filler(png, 0xff, PNG_FILLER_AFTER); } break; case PNG_COLOR_TYPE_RGB_ALPHA: break; case PNG_COLOR_TYPE_GRAY: if(bitDepth < 8) { png_set_expand_gray_1_2_4_to_8(png); } default: std::cout << "png: unsupported color type\n"; } if(bitDepth == 16) { png_set_strip_16(png); } png_read_update_info(png, info); png_size_t rowBytes = png_get_rowbytes(png, info); std::vector<char> data(rowBytes * imgData.h); png_byte* rows[imgData.h]; for (int i = 0; i < imgData.h; i++) { rows[i] = (png_byte*) &data[i * rowBytes]; } png_read_image(png, rows); fclose(file); { std::string empty; ((void **) &imgData.data)[0] = ((void **) &empty)[0]; imgData.data = " "; } imgData.data = std::string(&data[0], rowBytes * imgData.h); }
bool PNGDecoder::loadStream(Common::SeekableReadStream &stream) { #ifdef USE_PNG destroy(); // First, check the PNG signature (if not set to skip it) if (!_skipSignature) { if (stream.readUint32BE() != MKTAG(0x89, 'P', 'N', 'G')) { return false; } if (stream.readUint32BE() != MKTAG(0x0d, 0x0a, 0x1a, 0x0a)) { return false; } } // The following is based on the guide provided in: //http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-3 //http://www.libpng.org/pub/png/libpng-1.4.0-manual.pdf // along with the png-loading code used in the sword25-engine. png_structp pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!pngPtr) { return false; } png_infop infoPtr = png_create_info_struct(pngPtr); if (!infoPtr) { png_destroy_read_struct(&pngPtr, NULL, NULL); return false; } png_set_error_fn(pngPtr, NULL, pngError, pngWarning); // TODO: The manual says errors should be handled via setjmp png_set_read_fn(pngPtr, &stream, pngReadFromStream); png_set_crc_action(pngPtr, PNG_CRC_DEFAULT, PNG_CRC_WARN_USE); // We already verified the PNG-header png_set_sig_bytes(pngPtr, 8); // Read PNG header png_read_info(pngPtr, infoPtr); // No handling for unknown chunks yet. int bitDepth, colorType, width, height, interlaceType; png_uint_32 w, h; png_get_IHDR(pngPtr, infoPtr, &w, &h, &bitDepth, &colorType, &interlaceType, NULL, NULL); width = w; height = h; // Allocate memory for the final image data. // To keep memory framentation low this happens before allocating memory for temporary image data. _outputSurface = new Graphics::Surface(); // Images of all color formats except PNG_COLOR_TYPE_PALETTE // will be transformed into ARGB images if (colorType == PNG_COLOR_TYPE_PALETTE && !png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS)) { int numPalette = 0; png_colorp palette = NULL; uint32 success = png_get_PLTE(pngPtr, infoPtr, &palette, &numPalette); if (success != PNG_INFO_PLTE) { png_destroy_read_struct(&pngPtr, &infoPtr, NULL); return false; } _paletteColorCount = numPalette; _palette = new byte[_paletteColorCount * 3]; for (int i = 0; i < _paletteColorCount; i++) { _palette[(i * 3)] = palette[i].red; _palette[(i * 3) + 1] = palette[i].green; _palette[(i * 3) + 2] = palette[i].blue; } _outputSurface->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); png_set_packing(pngPtr); } else { bool isAlpha = (colorType & PNG_COLOR_MASK_ALPHA); if (png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS)) { isAlpha = true; png_set_expand(pngPtr); } _outputSurface->create(width, height, Graphics::PixelFormat(4, 8, 8, 8, isAlpha ? 8 : 0, 24, 16, 8, 0)); if (!_outputSurface->getPixels()) { error("Could not allocate memory for output image."); } if (bitDepth == 16) png_set_strip_16(pngPtr); if (bitDepth < 8) png_set_expand(pngPtr); if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(pngPtr); // PNGs are Big-Endian: #ifdef SCUMM_LITTLE_ENDIAN png_set_bgr(pngPtr); png_set_swap_alpha(pngPtr); if (colorType != PNG_COLOR_TYPE_RGB_ALPHA) png_set_filler(pngPtr, 0xff, PNG_FILLER_BEFORE); #else if (colorType != PNG_COLOR_TYPE_RGB_ALPHA) png_set_filler(pngPtr, 0xff, PNG_FILLER_AFTER); #endif } // After the transformations have been registered, the image data is read again. png_set_interlace_handling(pngPtr); png_read_update_info(pngPtr, infoPtr); png_get_IHDR(pngPtr, infoPtr, &w, &h, &bitDepth, &colorType, NULL, NULL, NULL); width = w; height = h; if (interlaceType == PNG_INTERLACE_NONE) { // PNGs without interlacing can simply be read row by row. for (int i = 0; i < height; i++) { png_read_row(pngPtr, (png_bytep)_outputSurface->getBasePtr(0, i), NULL); } } else { // PNGs with interlacing require us to allocate an auxillary // buffer with pointers to all row starts. // Allocate row pointer buffer png_bytep *rowPtr = new png_bytep[height]; if (!rowPtr) { error("Could not allocate memory for row pointers."); } // Initialize row pointers for (int i = 0; i < height; i++) rowPtr[i] = (png_bytep)_outputSurface->getBasePtr(0, i); // Read image data png_read_image(pngPtr, rowPtr); // Free row pointer buffer delete[] rowPtr; } // Read additional data at the end. png_read_end(pngPtr, NULL); // Destroy libpng structures png_destroy_read_struct(&pngPtr, &infoPtr, NULL); return true; #else return false; #endif }
static void init_output(void) { int bit_depth ; int color_type ; int invert_mono = 0 ; png_colorp pngpalette = NULL ; png_bytep ptrans = NULL ; outfile = openout(flatspec.output_filename); libpng = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, my_error_callback, png_error_ptr_NULL); if( !libpng ) FatalUnexpected(_("Couldn't initialize libpng library")); libpng2 = png_create_info_struct(libpng); if( !libpng2 ) FatalUnexpected("Couldn't create PNG info structure"); png_init_io(libpng,outfile); bit_depth = 8; switch( flatspec.out_color_mode ) { case COLOR_GRAY: if( flatspec.default_pixel == PERHAPS_ALPHA_CHANNEL || flatspec.default_pixel == FORCE_ALPHA_CHANNEL ) color_type = PNG_COLOR_TYPE_GRAY_ALPHA ; else color_type = PNG_COLOR_TYPE_GRAY ; break ; case COLOR_RGB: if( flatspec.default_pixel == PERHAPS_ALPHA_CHANNEL || flatspec.default_pixel == FORCE_ALPHA_CHANNEL ) color_type = PNG_COLOR_TYPE_RGB_ALPHA ; else color_type = PNG_COLOR_TYPE_RGB ; break ; case COLOR_INDEXED: if( paletteSize == 2 && palette[0] == NEWALPHA(0,255) && palette[1] == NEWALPHA(-1,255) ) { color_type = PNG_COLOR_TYPE_GRAY ; bit_depth = 1 ; } else if( paletteSize == 2 && palette[0] == NEWALPHA(-1,255) && palette[1] == NEWALPHA(0,255) ) { color_type = PNG_COLOR_TYPE_GRAY ; bit_depth = 1 ; invert_mono = 1 ; } else { unsigned i ; int need_trans = flatspec.default_pixel == FORCE_ALPHA_CHANNEL ; color_type = PNG_COLOR_TYPE_PALETTE ; pngpalette = xcfmalloc(paletteSize*sizeof(png_color)) ; ptrans = xcfmalloc(paletteSize); for(i = 0; i<paletteSize; i++ ) { pngpalette[i].red = 255 & (palette[i] >> RED_SHIFT); pngpalette[i].green = 255 & (palette[i] >> GREEN_SHIFT); pngpalette[i].blue = 255 & (palette[i] >> BLUE_SHIFT); if( (ptrans[i] = ALPHA(palette[i])) != 255 ) need_trans = 1 ; } if( !need_trans ) { xcffree(ptrans); ptrans = NULL ; } if( paletteSize <= 2 ) bit_depth = 1 ; else if( paletteSize <= 4 ) bit_depth = 2 ; else if( paletteSize <= 16 ) bit_depth = 4 ; else bit_depth = 8; } break ; default: FatalUnexpected("This can't happen (unknown out_color_mode)"); } if( verboseFlag ) { fprintf(stderr,"Writing PNG: %s%s%s%s, %d bits", color_type & PNG_COLOR_MASK_COLOR ? _("color") : _("grayscale"), color_type & PNG_COLOR_MASK_PALETTE ? _("+palette") : "", color_type & PNG_COLOR_MASK_ALPHA ? _("+alpha") : "", ptrans || NULLALPHA(flatspec.default_pixel) ? _("+transparency") : "", bit_depth); if( pngpalette ) fprintf(stderr,_(" (%d colors)"),paletteSize); fprintf(stderr,"\n"); } png_set_IHDR(libpng,libpng2,flatspec.dim.width,flatspec.dim.height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if( invert_mono ) png_set_invert_mono(libpng); if( pngpalette ) png_set_PLTE(libpng,libpng2,pngpalette,paletteSize); if( ptrans ) png_set_tRNS(libpng,libpng2,ptrans,paletteSize,NULL); else if ( !pngpalette && NULLALPHA(flatspec.default_pixel) ) { static png_color_16 trans ; trans.gray = trans.red = 255 & (flatspec.default_pixel >> RED_SHIFT) ; trans.green = 255 & (flatspec.default_pixel >> GREEN_SHIFT) ; trans.blue = 255 & (flatspec.default_pixel >> BLUE_SHIFT) ; png_set_tRNS(libpng,libpng2,NULL,0,&trans); } /* png_set_text here */ png_write_info(libpng,libpng2); if( bit_depth < 8 ) png_set_packing(libpng); switch( color_type ) { case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGBA: #if (BLUE_SHIFT < RED_SHIFT) == !defined(WORDS_BIGENDIAN) png_set_bgr(libpng); #endif if( color_type == PNG_COLOR_TYPE_RGB ) #if (ALPHA_SHIFT < RED_SHIFT) == !defined(WORDS_BIGENDIAN) png_set_filler(libpng,0,PNG_FILLER_BEFORE); else png_set_swap_alpha(libpng); #else png_set_filler(libpng,0,PNG_FILLER_AFTER); #endif break ; case PNG_COLOR_TYPE_GRAY: png_set_filler(libpng,0,PNG_FILLER_AFTER); break ; case PNG_COLOR_TYPE_GRAY_ALPHA: case PNG_COLOR_TYPE_PALETTE: break ; default: FatalUnexpected("This can't happen (unexpected png color_type)"); } }
PNGImage LoadImagePNG(const char *path) { PNGImage loadedImage; loadedImage.loadedSuccessfully = GL_FALSE; FILE *PNG_file = fopen(path, "rb"); if (PNG_file == NULL) { printf("Can't open PNG file %s\n", path); return loadedImage; } GLubyte PNG_header[PNG_HEADER_SIZE]; fread(PNG_header, 1, PNG_HEADER_SIZE, PNG_file); if (png_sig_cmp(PNG_header, 0, PNG_HEADER_SIZE) != 0) { printf("%s is not a PNG file\n", path); return loadedImage; } png_structp PNG_reader = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (PNG_reader == NULL) { printf("Can't start reading PNG file %s\n", path); fclose(PNG_file); return loadedImage; } png_infop PNG_info = png_create_info_struct(PNG_reader); if (PNG_info == NULL) { printf("Can't get info for PNG file %s\n", path); png_destroy_read_struct(&PNG_reader, NULL, NULL); fclose(PNG_file); return loadedImage; } png_infop PNG_end_info = png_create_info_struct(PNG_reader); if (PNG_end_info == NULL) { printf("Can't get end info for PNG file %s\n", path); png_destroy_read_struct(&PNG_reader, &PNG_info, NULL); fclose(PNG_file); return loadedImage; } if (setjmp(png_jmpbuf(PNG_reader))) { printf("Can't load PNG file %s\n", path); png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info); fclose(PNG_file); return loadedImage; } png_init_io(PNG_reader, PNG_file); png_set_sig_bytes(PNG_reader, PNG_HEADER_SIZE); png_read_info(PNG_reader, PNG_info); // we have to do a custom transformation to premultiply the alpha of the image png_set_read_user_transform_fn(PNG_reader, png_read_premultiply_alpha); png_uint_32 width, height; int bit_depth, color_type; png_get_IHDR(PNG_reader, PNG_info, &width, &height, &bit_depth, &color_type,NULL, NULL, NULL); if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(PNG_reader); } if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { png_set_expand_gray_1_2_4_to_8(PNG_reader); } if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(PNG_reader); } if (png_get_valid(PNG_reader, PNG_info, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(PNG_reader); } else { png_set_filler(PNG_reader, 0xff, PNG_FILLER_AFTER); } if (bit_depth == 16) { png_set_strip_16(PNG_reader); } png_read_update_info(PNG_reader, PNG_info); png_uint_32 widthPow2, heightPow2; widthPow2 = pow2(width); heightPow2 = pow2(height); png_byte* PNG_image_buffer = (png_byte*)malloc(4 * widthPow2 * heightPow2); memset(PNG_image_buffer,0,4*widthPow2*heightPow2); // clear image buffer png_byte** PNG_rows = (png_byte**)malloc(height * sizeof(png_byte*)); png_uint_32 rowBytes = widthPow2*4; // load the image from the bottom up /* image texture in mem looks like: -------- | | |xxxx | |xxxx | -------- where 'x's represent actual image data and the lines are the image buffer. so the image is aligned at the (0,0) texel coordinate of the image buffer. */ unsigned int row; for (row = 0; row < height; ++row) { PNG_rows[height-1-row] = PNG_image_buffer + (row * rowBytes); } png_read_image(PNG_reader, PNG_rows); free(PNG_rows); png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info); fclose(PNG_file); GLuint textureID = 0; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, widthPow2, heightPow2, 0, GL_RGBA, GL_UNSIGNED_BYTE, PNG_image_buffer); free(PNG_image_buffer); loadedImage.width = width; loadedImage.height = height; loadedImage.widthPow2 = widthPow2; loadedImage.heightPow2 = heightPow2; loadedImage.textureId = textureID; loadedImage.loadedSuccessfully = GL_TRUE; return loadedImage; }
bool CGLImageData::LoadPNG(const char * filename) { FILE *png_file = fopen(filename, "rb"); if (png_file == NULL) { sLog(DEFAULT_LOG_NAME, LOG_WARNING_EV, "Can't Load PNG file: \"%s\" can't open or doesn't exist", filename); return false; } BYTE header[PNG_SIG_BYTES]; fread(header, 1, PNG_SIG_BYTES, png_file); if (png_sig_cmp(header, 0, PNG_SIG_BYTES)) { sLog(DEFAULT_LOG_NAME, LOG_WARNING_EV, "Can't load PNG file: \"%s\" is not a PNG file.", filename); return false; } 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); png_infop end_info = png_create_info_struct(png_ptr); if(setjmp(png_jmpbuf(png_ptr))) { sLog(DEFAULT_LOG_NAME, LOG_WARNING_EV, "Can't load PNG file: \"%s\". Some error occured.", filename); return false; } 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*)); for (UINT 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); data = pixels; sLog(DEFAULT_LOG_NAME, LOG_INFO_EV, "PNG image \"%s\" loaded", filename); return true; }
bool ply_image_load (ply_image_t *image) { png_struct *png; png_info *info; png_uint_32 width, height, row; int bits_per_pixel, color_type, interlace_method; png_byte **rows; uint32_t *bytes; FILE *fp; assert (image != NULL); fp = fopen (image->filename, "r"); if (fp == NULL) return false; png = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); assert (png != NULL); info = png_create_info_struct (png); assert (info != NULL); png_init_io (png, fp); if (setjmp (png_jmpbuf (png)) != 0) { fclose (fp); return false; } png_read_info (png, info); png_get_IHDR (png, info, &width, &height, &bits_per_pixel, &color_type, &interlace_method, NULL, NULL); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb (png); if ((color_type == PNG_COLOR_TYPE_GRAY) && (bits_per_pixel < 8)) png_set_expand_gray_1_2_4_to_8 (png); if (png_get_valid (png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha (png); if (bits_per_pixel == 16) png_set_strip_16 (png); if (bits_per_pixel < 8) png_set_packing (png); if ((color_type == PNG_COLOR_TYPE_GRAY) || (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) png_set_gray_to_rgb (png); if (interlace_method != PNG_INTERLACE_NONE) png_set_interlace_handling (png); png_set_filler (png, 0xff, PNG_FILLER_AFTER); png_set_read_user_transform_fn (png, transform_to_argb32); png_read_update_info (png, info); rows = malloc (height * sizeof (png_byte *)); image->buffer = ply_pixel_buffer_new (width, height); bytes = ply_pixel_buffer_get_argb32_data (image->buffer); for (row = 0; row < height; row++) rows[row] = (png_byte*) &bytes[row * width]; png_read_image (png, rows); free (rows); png_read_end (png, info); fclose (fp); png_destroy_read_struct (&png, &info, NULL); return true; }
unsigned char* load_png_data(char *filename, int *w, int *h) { FILE *fp = fopen(filename, "rb"); if(!fp) { return NULL; } png_byte header[8]; fread(header, 1, 8, fp); if(png_sig_cmp(header, 0, 8)) { return NULL; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) { return NULL; } png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); fclose(fp); return NULL; } png_infop end_ptr = png_create_info_struct(png_ptr); if(!end_ptr) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return NULL; } if(setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_ptr); fclose(fp); return NULL; } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); int bit_depth = png_get_bit_depth(png_ptr, info_ptr); switch(png_get_color_type(png_ptr, info_ptr)) { case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(png_ptr); png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); break; case PNG_COLOR_TYPE_GRAY: png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); case PNG_COLOR_TYPE_GRAY_ALPHA: if(bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); if(bit_depth==16) png_set_strip_16(png_ptr); png_set_gray_to_rgb(png_ptr); break; case PNG_COLOR_TYPE_RGB: if(bit_depth < 8 ) png_set_packing(png_ptr); if(bit_depth == 16) png_set_strip_16(png_ptr); png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); break; default: break; } png_read_update_info(png_ptr, info_ptr); *w = png_get_image_width(png_ptr, info_ptr); *h = png_get_image_height(png_ptr, info_ptr); int rowbytes = (int)png_get_rowbytes(png_ptr, info_ptr); png_bytep data = malloc((*h)*rowbytes*sizeof(*data)); png_bytep row_pointers[*h]; int i; for(i=0; i<(*h); ++i) { row_pointers[i] = &data[i*rowbytes]; } png_read_image(png_ptr, row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, &end_ptr); fclose(fp); return data; }