bool FPngImageWrapper::LoadPNGHeader() { check(CompressedData.Num()); // Test whether the data this PNGLoader is pointing at is a PNG or not. if (IsPNG()) { // thread safety FScopeLock PNGLock(&GPNGSection); png_structp png_ptr = png_create_read_struct_2( PNG_LIBPNG_VER_STRING, this, FPngImageWrapper::user_error_fn, FPngImageWrapper::user_warning_fn, NULL, FPngImageWrapper::user_malloc, FPngImageWrapper::user_free ); check(png_ptr); png_infop info_ptr = png_create_info_struct( png_ptr ); check(info_ptr); PNGReadGuard PNGGuard(&png_ptr, &info_ptr); { png_set_read_fn(png_ptr, this, FPngImageWrapper::user_read_compressed); png_read_info(png_ptr, info_ptr); Width = info_ptr->width; Height = info_ptr->height; ColorType = info_ptr->color_type; BitDepth = info_ptr->bit_depth; Channels = info_ptr->channels; Format = (ColorType & PNG_COLOR_MASK_COLOR) ? ERGBFormat::RGBA : ERGBFormat::Gray; } return true; } return false; }
/* Create a PNG structure for reading, and allocate any memory needed. */ png_structp PNGAPI png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn) { #ifdef PNG_USER_MEM_SUPPORTED return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, warn_fn, NULL, NULL, NULL)); }
void TextureReader::initialisePNGReader(FileReader reader) { _png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, handlePNGError, handlePNGWarning, NULL, allocatePNGMemory, deallocatePNGMemory); //CHECK_ERROR(_png == NULL, "Graphics::TextureReader", "Failed to initialise the PNG reader"); png_set_read_fn(_png, &reader, readPNGData); png_set_sig_bytes(_png, 8); _pngInfo = png_create_info_struct(_png); //CHECK_ERROR(_pngInfo == NULL, "Graphics::TextureReader", "Failed to initialise the PNG reader info"); }
PNGImageReader(PNGImageDecoder* decoder) : m_readOffset(0) , m_currentBufferSize(0) , m_decodingSizeOnly(false) , m_hasAlpha(false) , m_interlaceBuffer(0) #if USE(QCMSLIB) , m_transform(0) , m_rowBuffer() #endif { #if PLATFORM(HP) m_png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning, 0, (png_malloc_ptr) pngMalloc, pngFree); #else m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning); #endif m_info = png_create_info_struct(m_png); png_set_progressive_read_fn(m_png, decoder, headerAvailable, rowAvailable, pngComplete); }
void png_start(struct cached_image *cimg) { png_structp png_ptr; png_infop info_ptr; struct png_decoder *decoder; retry1: #ifdef PNG_USER_MEM_SUPPORTED png_ptr=png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, img_my_png_error, img_my_png_warning, NULL, my_png_alloc, my_png_free); #else png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, img_my_png_error, img_my_png_warning); #endif if (!png_ptr) { if (out_of_memory(0, NULL, 0)) goto retry1; fatal_exit("png_create_read_struct failed"); } retry2: info_ptr=png_create_info_struct(png_ptr); if (!info_ptr) { if (out_of_memory(0, NULL, 0)) goto retry2; fatal_exit("png_create_info_struct failed"); } if (setjmp(png_jmpbuf(png_ptr))){ error: png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); img_end(cimg); return; } png_set_progressive_read_fn(png_ptr, NULL, png_info_callback, &png_row_callback, png_end_callback); if (setjmp(png_jmpbuf(png_ptr))) goto error; decoder=mem_alloc(sizeof(*decoder)); decoder->png_ptr=png_ptr; decoder->info_ptr=info_ptr; cimg->decoder=decoder; }
/* Shared library entry point */ static GdkPixbuf * gdk_pixbuf__png_image_load (FILE *f, GError **error) { GdkPixbuf * volatile pixbuf = NULL; png_structp png_ptr; png_infop info_ptr; png_textp text_ptr; gint i, ctype; png_uint_32 w, h; png_bytepp volatile rows = NULL; gint num_texts; gchar *key; gchar *value; gchar *icc_profile_base64; const gchar *icc_profile_title; const gchar *icc_profile; png_uint_32 icc_profile_size; guint32 retval; gint compression_type; #ifdef PNG_USER_MEM_SUPPORTED png_ptr = png_create_read_struct_2 (PNG_LIBPNG_VER_STRING, error, png_simple_error_callback, png_simple_warning_callback, NULL, png_malloc_callback, png_free_callback); #else png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, error, png_simple_error_callback, png_simple_warning_callback); #endif 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; } if (setjmp (png_jmpbuf(png_ptr))) { g_free (rows); if (pixbuf) g_object_unref (pixbuf); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); return NULL; } png_init_io (png_ptr, f); png_read_info (png_ptr, info_ptr); if (!setup_png_transformations(png_ptr, info_ptr, error, &w, &h, &ctype)) { png_destroy_read_struct (&png_ptr, &info_ptr, NULL); return NULL; } pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, ctype & PNG_COLOR_MASK_ALPHA, 8, w, h); if (!pixbuf) { if (error && *error == NULL) { g_set_error_literal (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Insufficient memory to load PNG file")); } png_destroy_read_struct (&png_ptr, &info_ptr, NULL); return NULL; } rows = g_new (png_bytep, h); for (i = 0; i < h; i++) rows[i] = pixbuf->pixels + i * pixbuf->rowstride; png_read_image (png_ptr, rows); png_read_end (png_ptr, info_ptr); if (png_get_text (png_ptr, info_ptr, &text_ptr, &num_texts)) { for (i = 0; i < num_texts; i++) { png_text_to_pixbuf_option (text_ptr[i], &key, &value); gdk_pixbuf_set_option (pixbuf, key, value); g_free (key); g_free (value); } } #if defined(PNG_cHRM_SUPPORTED) /* Extract embedded ICC profile */ retval = png_get_iCCP (png_ptr, info_ptr, (png_charpp) &icc_profile_title, &compression_type, (png_bytepp) &icc_profile, (png_uint_32*) &icc_profile_size); if (retval != 0) { icc_profile_base64 = g_base64_encode ((const guchar *) icc_profile, (gsize)icc_profile_size); gdk_pixbuf_set_option (pixbuf, "icc-profile", icc_profile_base64); g_free (icc_profile_base64); } #endif g_free (rows); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); return pixbuf; }
/* Test one file */ int test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) { static FILE *fpin, *fpout; /* "static" prevents setjmp corruption */ png_structp read_ptr, write_ptr; png_infop read_info_ptr, write_info_ptr, end_info_ptr, write_end_info_ptr; png_bytep row_buf; png_uint_32 y; png_uint_32 width, height; int num_pass, pass; int bit_depth, color_type; #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD jmp_buf jmp_env; #endif #endif char inbuf[256], outbuf[256]; row_buf = (png_bytep)NULL; if ((fpin = fopen(inname, "rb")) == NULL) { fprintf(STDERR, "Could not find input file %s\n", inname); return (1); } if ((fpout = fopen(outname, "wb")) == NULL) { fprintf(STDERR, "Could not open output file %s\n", outname); fclose(fpin); return (1); } png_debug(0, "Allocating read and write structures\n"); #ifdef PNG_USER_MEM_SUPPORTED read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL, (png_voidp)NULL, (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); #else read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL); #endif #if defined(PNG_NO_STDIO) png_set_error_fn(read_ptr, (png_voidp)inname, png_default_error, png_default_warning); #endif #ifdef PNG_USER_MEM_SUPPORTED write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL, (png_voidp)NULL, (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); #else write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL); #endif #if defined(PNG_NO_STDIO) png_set_error_fn(write_ptr, (png_voidp)inname, png_default_error, png_default_warning); #endif png_debug(0, "Allocating read_info, write_info and end_info structures\n"); read_info_ptr = png_create_info_struct(read_ptr); write_info_ptr = png_create_info_struct(write_ptr); end_info_ptr = png_create_info_struct(read_ptr); write_end_info_ptr = png_create_info_struct(write_ptr); #ifdef PNG_USER_MEM_SUPPORTED #endif #ifdef PNG_SETJMP_SUPPORTED png_debug(0, "Setting jmp_env for read struct\n"); #ifdef USE_FAR_KEYWORD if (setjmp(jmp_env)) #else if (setjmp(png_jmp_env(read_ptr))) #endif { fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); png_destroy_info_struct(write_ptr, &write_end_info_ptr); png_destroy_write_struct(&write_ptr, &write_info_ptr); fclose(fpin); fclose(fpout); return (1); } #ifdef USE_FAR_KEYWORD png_memcpy(png_jmp_env(read_ptr),jmp_env,sizeof(jmp_buf)); #endif png_debug(0, "Setting jmp_env for write struct\n"); #ifdef USE_FAR_KEYWORD if (setjmp(jmp_env)) #else if (setjmp(png_jmp_env(write_ptr))) #endif { fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); png_destroy_info_struct(write_ptr, &write_end_info_ptr); png_destroy_write_struct(&write_ptr, &write_info_ptr); fclose(fpin); fclose(fpout); return (1); } #ifdef USE_FAR_KEYWORD png_memcpy(png_jmp_env(write_ptr),jmp_env,sizeof(jmp_buf)); #endif #endif png_debug(0, "Initializing input and output streams\n"); #if !defined(PNG_NO_STDIO) png_init_io(read_ptr, fpin); png_init_io(write_ptr, fpout); #else png_set_read_fn(read_ptr, (png_voidp)fpin, png_default_read_data); png_set_write_fn(write_ptr, (png_voidp)fpout, png_default_write_data, #if defined(PNG_WRITE_FLUSH_SUPPORTED) png_default_flush); #else NULL); #endif #endif if(status_dots_requested == 1) { png_set_write_status_fn(write_ptr, write_row_callback); png_set_read_status_fn(read_ptr, read_row_callback); } else { png_set_write_status_fn(write_ptr, NULL); png_set_read_status_fn(read_ptr, NULL); } #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) { int i; for(i=0; i<256; i++) filters_used[i]=0; png_set_read_user_transform_fn(read_ptr, count_filters); } #endif #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) zero_samples=0; png_set_write_user_transform_fn(write_ptr, count_zero_samples); #endif #define HANDLE_CHUNK_IF_SAFE 2 #define HANDLE_CHUNK_ALWAYS 3 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) png_set_keep_unknown_chunks(read_ptr, HANDLE_CHUNK_ALWAYS, NULL, 0); #endif #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) png_set_keep_unknown_chunks(write_ptr, HANDLE_CHUNK_IF_SAFE, NULL, 0); #endif png_debug(0, "Reading info struct\n"); png_read_info(read_ptr, read_info_ptr); png_debug(0, "Transferring info struct\n"); { int interlace_type, compression_type, filter_type; if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type)) { png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, #if defined(PNG_WRITE_INTERLACING_SUPPORTED) color_type, interlace_type, compression_type, filter_type); #else color_type, PNG_INTERLACE_NONE, compression_type, filter_type); #endif } }
/* This only determines if we have an alpha value */ int xps_png_has_alpha(xps_context_t *ctx, byte *rbuf, int rlen) { png_structp png; png_infop info; struct xps_png_io_s io; int has_alpha; /* * Set up PNG structs and input source */ io.ptr = rbuf; io.lim = rbuf + rlen; png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, ctx->memory, xps_png_malloc, xps_png_free); if (!png) { gs_warn("png_create_read_struct"); return 0; } info = png_create_info_struct(png); if (!info) { gs_warn("png_create_info_struct"); return 0; } png_set_read_fn(png, &io, xps_png_read); png_set_crc_action(png, PNG_CRC_WARN_USE, PNG_CRC_WARN_USE); /* * Jump to here on errors. */ if (setjmp(png_jmpbuf(png))) { png_destroy_read_struct(&png, &info, NULL); gs_warn("png reading failed"); return 0; } /* * Read PNG header */ png_read_info(png, info); switch (png_get_color_type(png, info)) { case PNG_COLOR_TYPE_PALETTE: case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_RGB: has_alpha = 0; break; case PNG_COLOR_TYPE_GRAY_ALPHA: case PNG_COLOR_TYPE_RGB_ALPHA: has_alpha = 1; break; default: gs_warn("cannot handle this png color type"); has_alpha = 0; break; } /* * Clean up memory. */ png_destroy_read_struct(&png, &info, NULL); return has_alpha; }
bool R9_ImgReadPNG( F9FILE file, r9Img* img ) { if(file==NULL || img==NULL) return false; R9_ImgDestroy(img); // check png sig const int headersize = 8; byte header[headersize]; if(file->Read( header, headersize) != headersize) return false; BOOL ispng = png_check_sig(header, headersize) != 0; if(!ispng) { elog::rnd() << "png sig failed" << std::endl; return false; } // create png structures png_structp png_ptr = png_create_read_struct_2( PNG_LIBPNG_VER_STRING, NULL, R9_ImgPNG_FatalError, R9_ImgPNG_Warning, NULL, R9_ImgPNG_Malloc, R9_ImgPNG_Free ); if(png_ptr==NULL) return false; png_infop info_ptr = png_create_info_struct(png_ptr); if(info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return false; } png_infop end_info = png_create_info_struct(png_ptr); if(end_info == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return false; } // set global file r9_imgpng_file = file; png_set_read_fn(png_ptr, NULL, R9_ImgPNG_ReadData); // read off the info on the image png_set_sig_bytes(png_ptr, headersize); png_read_info(png_ptr, info_ptr); png_uint_32 pngwidth; png_uint_32 pngheight; int32 pngbits; int32 pngpf; png_get_IHDR(png_ptr, info_ptr, &pngwidth, &pngheight, &pngbits, &pngpf, NULL, // interlace NULL, // compression_type NULL); // filter_type BOOL alpha = FALSE; img->m_width = pngwidth; img->m_height = pngheight; img->m_pf = R9_PF_RGB; assert(img->m_width!=0 && img->m_height!=0); // Strip off any 16 bit info if(pngbits==16) png_set_strip_16(png_ptr); // Expand a transparency channel into a full alpha channel... if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_expand(png_ptr); alpha = TRUE; } if( pngpf == PNG_COLOR_TYPE_RGB) { png_set_expand(png_ptr); img->m_pf = alpha ? R9_PF_ARGB : R9_PF_RGB; } else if( pngpf == PNG_COLOR_TYPE_RGB_ALPHA) { png_set_expand(png_ptr); img->m_pf = R9_PF_ARGB; } else { elog::rnd() << "png wrong color format" << std::endl; png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return false; } // Update the info pointer with the result of the transformations above... png_read_update_info(png_ptr, info_ptr); png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr); if(img->m_pf==R9_PF_RGB) assert(rowbytes==img->m_width*3); else if(img->m_pf==R9_PF_RGB) assert(rowbytes==img->m_width*4); // create image R9_ImgCreate(img); // set up the row pointers... png_bytep* rowpointers = new png_bytep[img->m_height]; for(int i=0; i<img->m_height; i++) rowpointers[i] = img->m_data + (i*rowbytes); // read image png_read_image(png_ptr, rowpointers); // release png_read_end(png_ptr, NULL); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete [] rowpointers; r9_imgpng_file = NULL; R9_ImgFlipRGB(img); // it was BGR, we want it RGB ! return true; }
// // In order to avoid CRT mismatches, we override all CRT functions libpng uses // with our own. The alternative, using fopen and fread in our code and then // passing a FILE* into libpng, isn't reliable because it crashes if libpng was // compiled with a different CRT than lsapi.dll // HBITMAP LoadFromPNG(LPCSTR pszFilename) { HBITMAP hDibSection = NULL; if (pszFilename != NULL) { FILE * hFile = fopen(pszFilename, "rb"); if (hFile) { const size_t num_sig_bytes = 8; unsigned char sig[num_sig_bytes]; fread(sig, 1, num_sig_bytes, hFile); if (png_check_sig(sig, num_sig_bytes)) { PNGERROR PngError = { 0 }; PngError.Wnd = GetForegroundWindow(); png_structp Read = png_create_read_struct_2( PNG_LIBPNG_VER_STRING, &PngError, PNGErrorHandler, NULL, NULL, ls_png_malloc, ls_png_free); if (Read) { png_infop Info = png_create_info_struct(Read); if (Info) { if (!setjmp(PngError.ErrorJump)) { png_set_read_fn(Read, hFile, ls_png_read_data); png_set_sig_bytes(Read, num_sig_bytes); png_read_info(Read, Info); const unsigned char bit_depth = png_get_bit_depth(Read, Info); const unsigned char color_type = png_get_color_type(Read, Info); if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(Read); } if ((color_type == PNG_COLOR_TYPE_GRAY) || (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) { if (bit_depth < 8) { png_set_gray_1_2_4_to_8(Read); } png_set_gray_to_rgb(Read); } if (png_get_valid(Read, Info, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(Read); } if (color_type & PNG_COLOR_MASK_COLOR) { png_set_bgr(Read); } if (bit_depth == 16) { png_set_strip_16(Read); } double image_gamma = 1 / 2.2; png_get_gAMA(Read, Info, &image_gamma); png_set_gamma(Read, 2.2, image_gamma); const int num_passes = png_set_interlace_handling(Read); png_read_update_info(Read, Info); BITMAPINFO bmi = { {0} }; bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = (LONG)png_get_image_width(Read, Info); bmi.bmiHeader.biHeight = -(LONG)png_get_image_height(Read, Info); bmi.bmiHeader.biBitCount = (WORD)(png_get_channels(Read, Info) * png_get_bit_depth(Read, Info)); bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biCompression = BI_RGB; unsigned char* bits; hDibSection = CreateDIBSection(NULL, &bmi, 0, reinterpret_cast<LPVOID*>(&bits), NULL, 0); if (!bits) { longjmp(PngError.ErrorJump, 1); } unsigned int dib_bytes_per_scanline = \ (((bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount) + 31) & ~31) >> 3; for (int Pass = 0; Pass < num_passes; ++Pass) { for (int y = 0; y < -bmi.bmiHeader.biHeight; ++y) { unsigned char* Scanline = \ reinterpret_cast<unsigned char*>(bits + (y * dib_bytes_per_scanline)); png_read_row(Read, Scanline, NULL); } } png_read_end(Read, Info); png_destroy_read_struct(&Read, &Info, NULL); } else { png_destroy_read_struct(&Read, &Info, NULL); } } else { png_destroy_read_struct(&Read, NULL, NULL); } }
void FPngImageWrapper::UncompressPNGData( const ERGBFormat::Type InFormat, const int32 InBitDepth ) { // thread safety FScopeLock PNGLock(&GPNGSection); check( CompressedData.Num() ); check( Width > 0 ); check( Height > 0 ); // Note that PNGs on PC tend to be BGR check( InFormat == ERGBFormat::BGRA || InFormat == ERGBFormat::RGBA || InFormat == ERGBFormat::Gray ) // Other formats unsupported at present check( InBitDepth == 8 || InBitDepth == 16 ) // Other formats unsupported at present // Reset to the beginning of file so we can use png_read_png(), which expects to start at the beginning. ReadOffset = 0; png_structp png_ptr = png_create_read_struct_2( PNG_LIBPNG_VER_STRING, this, FPngImageWrapper::user_error_fn, FPngImageWrapper::user_warning_fn, NULL, FPngImageWrapper::user_malloc, FPngImageWrapper::user_free); check( png_ptr ); png_infop info_ptr = png_create_info_struct( png_ptr ); check( info_ptr ); PNGReadGuard PNGGuard( &png_ptr, &info_ptr ); { if (ColorType == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); } if ((ColorType & PNG_COLOR_MASK_COLOR) == 0 && BitDepth < 8) { png_set_expand_gray_1_2_4_to_8(png_ptr); } // Insert alpha channel with full opacity for RGB images without alpha if ((ColorType & PNG_COLOR_MASK_ALPHA) == 0 && (InFormat == ERGBFormat::BGRA || InFormat == ERGBFormat::RGBA)) { // png images don't set PNG_COLOR_MASK_ALPHA if they have alpha from a tRNS chunk, but png_set_add_alpha seems to be safe regardless if ((ColorType & PNG_COLOR_MASK_COLOR) == 0) { png_set_tRNS_to_alpha(png_ptr); } else if (ColorType == PNG_COLOR_TYPE_PALETTE) { png_set_tRNS_to_alpha(png_ptr); } if (InBitDepth == 8) { png_set_add_alpha(png_ptr, 0xff , PNG_FILLER_AFTER); } else if (InBitDepth == 16) { png_set_add_alpha(png_ptr, 0xffff , PNG_FILLER_AFTER); } } // Calculate Pixel Depth const uint32 PixelChannels = (InFormat == ERGBFormat::Gray) ? 1 : 4; const uint32 BytesPerPixel = (InBitDepth * PixelChannels) / 8; const uint32 BytesPerRow = BytesPerPixel * Width; RawData.Empty(Height * BytesPerRow); RawData.AddUninitialized(Height * BytesPerRow); png_set_read_fn( png_ptr, this, FPngImageWrapper::user_read_compressed ); png_bytep* row_pointers = (png_bytep*) png_malloc( png_ptr, Height*sizeof(png_bytep) ); PNGGuard.SetRowPointers(&row_pointers); for (int32 i = 0; i < Height; i++) { row_pointers[i]= &RawData[i * BytesPerRow]; } png_set_rows(png_ptr, info_ptr, row_pointers); uint32 Transform = (InFormat == ERGBFormat::BGRA) ? PNG_TRANSFORM_BGR : PNG_TRANSFORM_IDENTITY; // PNG files store 16-bit pixels in network byte order (big-endian, ie. most significant bits first). #if PLATFORM_LITTLE_ENDIAN // We're little endian so we need to swap if (BitDepth == 16) { Transform |= PNG_TRANSFORM_SWAP_ENDIAN; } #endif // Convert grayscale png to RGB if requested if ((ColorType & PNG_COLOR_MASK_COLOR) == 0 && (InFormat == ERGBFormat::RGBA || InFormat == ERGBFormat::BGRA)) { Transform |= PNG_TRANSFORM_GRAY_TO_RGB; } // Convert RGB png to grayscale if requested if ((ColorType & PNG_COLOR_MASK_COLOR) != 0 && InFormat == ERGBFormat::Gray) { png_set_rgb_to_gray_fixed(png_ptr, 2 /* warn if image is in color */, -1, -1); } // Strip alpha channel if requested output is grayscale if (InFormat == ERGBFormat::Gray) { // this is not necessarily the best option, instead perhaps: // png_color background = {0,0,0}; // png_set_background(png_ptr, &background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); Transform |= PNG_TRANSFORM_STRIP_ALPHA; } // Reduce 16-bit to 8-bit if requested if (BitDepth == 16 && InBitDepth == 8) { #if PNG_LIBPNG_VER >= 10504 check(0); // Needs testing Transform |= PNG_TRANSFORM_SCALE_16; #else Transform |= PNG_TRANSFORM_STRIP_16; #endif } // Increase 8-bit to 16-bit if requested if (BitDepth <= 8 && InBitDepth == 16) { #if PNG_LIBPNG_VER >= 10504 check(0); // Needs testing Transform |= PNG_TRANSFORM_EXPAND_16 #else // Expanding 8-bit images to 16-bit via transform needs a libpng update check(0); #endif } png_read_png(png_ptr, info_ptr, Transform, NULL); } RawFormat = InFormat; RawBitDepth = InBitDepth; }
//-------------------------------------- static bool sReadPNG(Stream &stream, GBitmap *bitmap) { static const U32 cs_headerBytesChecked = 8; U8 header[cs_headerBytesChecked]; stream.read(cs_headerBytesChecked, header); bool isPng = png_check_sig(header, cs_headerBytesChecked) != 0; if (isPng == false) { AssertWarn(false, "GBitmap::readPNG: stream doesn't contain a PNG"); return false; } U32 prevWaterMark = FrameAllocator::getWaterMark(); png_structp png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, pngFatalErrorFn, pngWarningFn, NULL, pngRealMallocFn, pngRealFreeFn); if (png_ptr == NULL) { FrameAllocator::setWaterMark(prevWaterMark); return false; } png_infop info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); FrameAllocator::setWaterMark(prevWaterMark); return false; } png_infop end_info = png_create_info_struct(png_ptr); if (end_info == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); FrameAllocator::setWaterMark(prevWaterMark); return false; } png_set_read_fn(png_ptr, &stream, pngReadDataFn); // Read off the info on the image. png_set_sig_bytes(png_ptr, cs_headerBytesChecked); png_read_info(png_ptr, info_ptr); // OK, at this point, if we have reached it ok, then we can reset the // image to accept the new data... // bitmap->deleteImage(); png_uint_32 width; png_uint_32 height; S32 bit_depth; S32 color_type; png_get_IHDR(png_ptr, info_ptr, &width, &height, // obv. &bit_depth, &color_type, // obv. NULL, // interlace NULL, // compression_type NULL); // filter_type // First, handle the color transformations. We need this to read in the // data as RGB or RGBA, _always_, with a maximal channel width of 8 bits. // bool transAlpha = false; GFXFormat format = GFXFormatR8G8B8; // Strip off any 16 bit info // if (bit_depth == 16 && color_type != PNG_COLOR_TYPE_GRAY) { png_set_strip_16(png_ptr); } // Expand a transparency channel into a full alpha channel... // if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_expand(png_ptr); transAlpha = true; } if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_expand(png_ptr); format = transAlpha ? GFXFormatR8G8B8A8 : GFXFormatR8G8B8; } else if (color_type == PNG_COLOR_TYPE_GRAY) { png_set_expand(png_ptr); if (bit_depth == 16) format = GFXFormatR5G6B5; else format = GFXFormatA8; } else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_expand(png_ptr); png_set_gray_to_rgb(png_ptr); format = GFXFormatR8G8B8A8; } else if (color_type == PNG_COLOR_TYPE_RGB) { format = transAlpha ? GFXFormatR8G8B8A8 : GFXFormatR8G8B8; png_set_expand(png_ptr); } else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) { png_set_expand(png_ptr); format = GFXFormatR8G8B8A8; } // Update the info pointer with the result of the transformations // above... png_read_update_info(png_ptr, info_ptr); const png_size_t rowBytes = png_get_rowbytes(png_ptr, info_ptr); if (format == GFXFormatR8G8B8) { AssertFatal(rowBytes == width * 3, "Error, our rowbytes are incorrect for this transform... (3)"); } else if (format == GFXFormatR8G8B8A8) { AssertFatal(rowBytes == width * 4, "Error, our rowbytes are incorrect for this transform... (4)"); } else if (format == GFXFormatR5G6B5) { AssertFatal(rowBytes == width * 2, "Error, our rowbytes are incorrect for this transform... (2)"); } // actually allocate the bitmap space... bitmap->allocateBitmap(width, height, false, // don't extrude miplevels... format); // use determined format... // Set up the row pointers... png_bytep* rowPointers = new png_bytep[ height ]; U8* pBase = (U8*)bitmap->getBits(); for (U32 i = 0; i < height; i++) rowPointers[i] = pBase + (i * rowBytes); // And actually read the image! png_read_image(png_ptr, rowPointers); // We're outta here, destroy the png structs, and release the lock // as quickly as possible... //png_read_end(png_ptr, end_info); delete [] rowPointers; png_read_end(png_ptr, NULL); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); // Ok, the image is read in, now we need to finish up the initialization, // which means: setting up the detailing members, init'ing the palette // key, etc... // // actually, all of that was handled by allocateBitmap, so we're outta here // // Check this bitmap for transparency bitmap->checkForTransparency(); FrameAllocator::setWaterMark(prevWaterMark); return true; }
uint8_t *PNG_unpack(SYS_FILEHANDLE infile, uint32_t *LX, uint32_t *LY, int *dwBitsPerPixel, rgb24_t *pClut, int options) { uint8_t *out_buffer; uint32_t i; unsigned char sig[8]; png_structp png_ptr; png_infop info_ptr; FIO_cur->fread(sig, 1, 8, infile); if (!png_check_sig(sig, 8)) { return NULL; /* bad signature */ } png_ptr = png_create_read_struct_2( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)pngx_error, (png_error_ptr)pngx_warning, (png_voidp)NULL, (png_malloc_ptr)pngx_malloc, (png_free_ptr)pngx_free); png_init_io(png_ptr, (FILE*)infile); png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ png_set_read_fn(png_ptr, (FILE*)infile, pngx_readm_pData); if (!pClut) pClut = (rgb24_t*)MM_heap.malloc(3*256); info_ptr = png_create_info_struct(png_ptr); png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } out_buffer = 0; if (png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)) { png_colorp palette; int num_palette; png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); if (palette) sysMemCpy(pClut, palette, num_palette * 3); } else { for (i=0;i<256;i++) pClut[i].r = pClut[i].g = pClut[i].b = (uint8_t)i; } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) { double gamma; png_get_gAMA(png_ptr, info_ptr, &gamma); } if (options & 1) { png_uint_32 width, height; int bit_depth, rowbytes; int color_type; uint8_t **row_pointers = NULL; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); if (bit_depth<8) png_set_packing(png_ptr); if ((color_type == PNG_COLOR_TYPE_RGB_ALPHA && bit_depth>8)) png_set_bgr(png_ptr); png_read_update_info(png_ptr, info_ptr); rowbytes = png_get_rowbytes(png_ptr, info_ptr); out_buffer = (uint8_t*) MM_heap.malloc(height * rowbytes); row_pointers = (uint8_t**) MM_std.malloc(sizeof(char*)*height); SYS_ASSERT(row_pointers!=0); for (i=0;i<height;i++) row_pointers[i] = out_buffer + i * rowbytes; png_read_image(png_ptr, row_pointers); MM_std.free(row_pointers); png_read_end(png_ptr, NULL); *LX = width; *LY = height; *dwBitsPerPixel = (rowbytes<<3) / width; png_destroy_read_struct(&png_ptr, &info_ptr, NULL); } return out_buffer; }
/* * @brief Reads header information from the PNG file into the bitmap pointer * * @param [in] filename name of the PNG bitmap file * @param [out] w width of the bitmap * @param [out] h height of the bitmap * @param [out] bpp bits per pixel of the bitmap * @param [out] palette * * @retval PNG_ERROR_NONE if successful, otherwise error code */ int png_read_header(const char *real_filename, CFILE *img_cfp, int *w, int *h, int *bpp, ubyte *palette) { char filename[MAX_FILENAME_LEN]; png_infop info_ptr; png_structp png_ptr; png_read_status status; status.reading_header = true; status.filename = real_filename; if (img_cfp == NULL) { strcpy_s( filename, real_filename ); char *p = strchr( filename, '.' ); if ( p ) *p = 0; strcat_s( filename, ".png" ); status.cfp = cfopen( filename , "rb" ); if ( !status.cfp ) { return PNG_ERROR_READING; } } else { status.cfp = img_cfp; } Assert( status.cfp != NULL ); 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, &status, png_malloc_fn, png_free_fn); if (png_ptr == NULL) { mprintf(("png_read_header: error creating read struct\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_header: error creating info struct\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_header: 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_info(png_ptr, info_ptr); if (w) *w = png_get_image_width(png_ptr, info_ptr); if (h) *h = png_get_image_height(png_ptr, info_ptr); // this turns out to be near useless, but meh if (bpp) *bpp = (png_get_channels(png_ptr, info_ptr) * png_get_bit_depth(png_ptr, info_ptr)); if (img_cfp == NULL) { cfclose(status.cfp); status.cfp = NULL; } png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return PNG_ERROR_NONE; }
/* * 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; }
//============================================================== sPNG *PngRead(void *ptr, size_t size) //-------------------------------------------------------------- // データ読み込み //-------------------------------------------------------------- // in: ptr = データポインタ // size = データサイズ //-------------------------------------------------------------- // out: アクセスハンドル(NULL = 失敗) //============================================================== { png_struct *hdl; png_info *info; u_char *filepos; png_uint_32 width, height; int depth, type; u_char **image; int num_palette; png_colorp palette; sPalette *pal; size_t w_size; int trans_ex; png_bytep trans; png_color_16p trans_16; int trans_num; int i; unsigned int h; sPNG *hdr; // ヘッダチェック //---------------- if(!png_check_sig((png_bytep)ptr, size)) return NULL; // 基本構造体の初期化 //-------------------- #ifdef USE_USER_MEMORY hdl = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, NULL, libpng_Malloc, libpng_Free); #else hdl = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); #endif if(!hdl) return NULL; info = png_create_info_struct(hdl); if(!info) { png_destroy_read_struct(&hdl, NULL, NULL); return NULL; } filepos = (u_char *)ptr; png_set_read_fn(hdl, (png_voidp)&filepos, (png_rw_ptr)readFunc); png_read_info(hdl, info); png_get_IHDR(hdl, info, &width, &height, &depth, &type, NULL, NULL, NULL); if(depth == 16) { png_set_strip_16(hdl); // 16bit -> 8bit } else if(depth == 4) { png_set_packing(hdl); // 4bit -> 8bit } else if(depth != 8) { PRINTF("Format error(%d)\n", depth); return NULL; } #if 0 if(type != PNG_COLOR_TYPE_PALETTE) { PRINTF("Format error(not palette type)\n"); return NULL; } #endif #if 0 // OpenGLで使う場合は不要 // アルファ付きPNG //----------------- if(type & PNG_COLOR_MASK_ALPHA) png_set_bgr(hdl); #endif // 透明色情報取得 //---------------- trans_ex = png_get_tRNS(hdl, info, &trans, &trans_num, &trans_16); // 設定を反映 //------------ png_read_update_info(hdl, info); // パレットを取得 //---------------- if(png_get_PLTE(hdl, info, &palette, &num_palette)) { // PRINTF("palette: %d\n", num_palette); pal = (sPalette *)pngMalloc(sizeof(sPalette) * num_palette, "sPalette"); ASSERT(pal); for(i = 0; i < num_palette; ++i) { pal[i].red = palette[i].red; pal[i].green = palette[i].green; pal[i].blue = palette[i].blue; if(trans_ex && trans_num) { // 取得した情報に従って設定 //-------------------------- pal[i].alpha = *trans; ++trans; --trans_num; } else { // 不透明 //-------- pal[i].alpha = 255; } } } else { pal = NULL; } // データ格納領域を確保 //---------------------- image = (u_char **)pngMalloc(sizeof(u_char *) * height, "png"); ASSERT(image); w_size = png_get_rowbytes(hdl, info); for(h = 0; h < height; ++h) { image[h] = (u_char *)pngMalloc(w_size, "png"); ASSERT(image[h]); } // データを読み込む //------------------ png_read_image(hdl, image); // 読み込み終了処理 //------------------ png_read_end(hdl, info); // 後始末 //-------- png_destroy_read_struct(&hdl, &info, NULL); // アクセスハンドルを作成 //------------------------ hdr = (sPNG *)pngMalloc(sizeof(sPNG), "sPNG"); ASSERT(hdr); hdr->type = type; hdr->width = width; hdr->height = height; hdr->image = (u_char *)pngMalloc(w_size * height, "sPNG image"); hdr->palnum = num_palette; hdr->pal = pal; // イメージをコピー //------------------ for(h = 0; h < height; ++h) { memcpy(&hdr->image[w_size * h], image[h], w_size); Free(image[h]); } Free(image); return hdr; }
static gpointer gdk_pixbuf__png_image_begin_load (GdkPixbufModuleSizeFunc size_func, GdkPixbufModulePreparedFunc prepare_func, GdkPixbufModuleUpdatedFunc update_func, gpointer user_data, GError **error) { LoadContext* lc; lc = g_new0(LoadContext, 1); lc->fatal_error_occurred = FALSE; lc->size_func = size_func; lc->prepare_func = prepare_func; lc->update_func = update_func; lc->notify_user_data = user_data; lc->first_row_seen_in_chunk = -1; lc->last_row_seen_in_chunk = -1; lc->first_pass_seen_in_chunk = -1; lc->last_pass_seen_in_chunk = -1; lc->max_row_seen_in_chunk = -1; lc->error = error; /* Create the main PNG context struct */ #ifdef PNG_USER_MEM_SUPPORTED lc->png_read_ptr = png_create_read_struct_2 (PNG_LIBPNG_VER_STRING, lc, /* error/warning callback data */ png_error_callback, png_warning_callback, NULL, png_malloc_callback, png_free_callback); #else lc->png_read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, lc, /* error/warning callback data */ png_error_callback, png_warning_callback); #endif if (lc->png_read_ptr == NULL) { g_free(lc); /* error callback should have set the error */ return NULL; } if (setjmp (png_jmpbuf(lc->png_read_ptr))) { if (lc->png_info_ptr) png_destroy_read_struct(&lc->png_read_ptr, NULL, NULL); g_free(lc); /* error callback should have set the error */ return NULL; } /* Create the auxiliary context struct */ lc->png_info_ptr = png_create_info_struct(lc->png_read_ptr); if (lc->png_info_ptr == NULL) { png_destroy_read_struct(&lc->png_read_ptr, NULL, NULL); g_free(lc); /* error callback should have set the error */ return NULL; } png_set_progressive_read_fn(lc->png_read_ptr, lc, /* callback data */ png_info_callback, png_row_callback, png_end_callback); /* We don't want to keep modifying error after returning here, * it may no longer be valid. */ lc->error = NULL; return lc; }
Error ImageLoaderPNG::_load_image(void *rf_up,png_rw_ptr p_func,Image *p_image) { png_structp png; png_infop info; //png = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,_png_error_function,_png_warn_function,(png_voidp)NULL, _png_malloc_fn,_png_free_fn ); ERR_FAIL_COND_V(!png, ERR_OUT_OF_MEMORY); info = png_create_info_struct(png); if (!info) { png_destroy_read_struct(&png,NULL,NULL); ERR_PRINT("Out of Memory"); return ERR_OUT_OF_MEMORY; } if (setjmp(png_jmpbuf(png))) { png_destroy_read_struct(&png,NULL,NULL); ERR_PRINT("PNG Corrupted"); return ERR_FILE_CORRUPT; } png_set_read_fn(png,(void*)rf_up,p_func); png_uint_32 width, height; int depth, color; png_read_info(png, info); png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); png_textp t; //https://svn.gov.pt/projects/ccidadao/repository/middleware-offline/trunk/_src/eidmw/FreeImagePTEiD/Source/FreeImage/PluginPNG.cpp //png_get_text(png,info,) /* printf("Image width:%i\n", width); printf("Image Height:%i\n", height); printf("Bit depth:%i\n", depth); printf("Color type:%i\n", color); */ if (depth<8) { //only bit dept 8 per channel is handled png_set_packing(png); }; if (depth > 8) { png_set_strip_16(png); png_read_update_info(png, info); } int palette_colors = 0; int palette_components = 0; int components = 0; Image::Format fmt; switch(color) { case PNG_COLOR_TYPE_GRAY: { fmt=Image::FORMAT_GRAYSCALE; components=1; } break; case PNG_COLOR_TYPE_GRAY_ALPHA: { fmt=Image::FORMAT_GRAYSCALE_ALPHA; components=2; } break; case PNG_COLOR_TYPE_RGB: { fmt=Image::FORMAT_RGB; components=3; } break; case PNG_COLOR_TYPE_RGB_ALPHA: { fmt=Image::FORMAT_RGBA; components=4; } break; case PNG_COLOR_TYPE_PALETTE: { int ntrans = 0; png_get_tRNS(png, info, NULL, &ntrans, NULL); //printf("transparent colors %i\n", ntrans); fmt = ntrans > 0 ? Image::FORMAT_INDEXED_ALPHA : Image::FORMAT_INDEXED; palette_components = ntrans > 0 ? 4 : 3; components = 1; png_colorp colors; png_get_PLTE(png, info, &colors, &palette_colors); } break; default: { ERR_PRINT("INVALID PNG TYPE"); png_destroy_read_struct(&png, &info, NULL); return ERR_UNAVAILABLE; } break; } //int rowsize = png_get_rowbytes(png, info); int rowsize = components * width; DVector<uint8_t> dstbuff; dstbuff.resize( rowsize * height + palette_components * 256 ); // alloc the entire palette? - yes always DVector<uint8_t>::Write dstbuff_write = dstbuff.write(); uint8_t* data = dstbuff_write.ptr(); uint8_t **row_p = memnew_arr( uint8_t*, height ); for (unsigned int i = 0; i < height; i++) { row_p[i] = &data[components*width*i]; } png_read_image(png, (png_bytep*)row_p); if (palette_colors) { uint8_t *r_pal = &data[components*width*height]; // end of the array png_colorp colors; int num; png_get_PLTE(png, info, &colors, &num); int ofs = 0; for (int i=0; i < palette_colors; i++) { r_pal[ofs + 0] = colors[i].red; r_pal[ofs + 1] = colors[i].green; r_pal[ofs + 2] = colors[i].blue; if (palette_components == 4) { r_pal[ofs + 3] = 255; }; ofs += palette_components; }; if (fmt == Image::FORMAT_INDEXED_ALPHA) { png_color_16p alphas; png_bytep alpha_idx; int count; png_get_tRNS(png, info, &alpha_idx, &count, &alphas); for (int i=0; i<count; i++) { //printf("%i: loading alpha fron transparent color %i, values %i, %i, %i, %i, %i\n", i, (int)alpha_idx[i], (int)alphas[i].index, (int)alphas[i].red, (int)alphas[i].green, (int)alphas[i].blue, (int)alphas[i].gray); //r_pal[alpha_idx[i]] = alphas[i].gray >> 8; r_pal[i*4+3] = alpha_idx[i]; }; }; }; memdelete_arr( row_p ); p_image->create( width, height, 0,fmt, dstbuff ); png_destroy_read_struct(&png, &info, NULL ); return OK; }
void printImage(size_t center, size_t middle, void const * imgStart, void const * imgEnd) { PSEUDO_FILE *fp; png_bytep *row_pointers; int width, height; if( (fp = pseudo_fopen((char const *)imgStart, (long)imgEnd-(long)imgStart )) == NULL ) { debug("Pseudo open failed"); return; } png_structp png_ptr = png_create_read_struct_2( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL, NULL, my_malloc, my_free); if ( !png_ptr ) { debug("Got no png ptr"); return; } 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); debug("Got no info struct"); return; } /* read file */ if (setjmp(png_jmpbuf(png_ptr))) { debug("[read_png_file] Error"); png_destroy_read_struct(&png_ptr, &info_ptr, 0); return; } /* Pass file 'handle' and function address to png_set_read_fn() */ png_set_read_fn(png_ptr, (void *)fp, my_fread); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_SWAP_ALPHA, NULL); width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); row_pointers = png_get_rows(png_ptr, info_ptr); int left = center-width/2; int top = middle+height/2; for( int x = 0; x < width; ++x ) { for( int y = 0; y < height; ++y ) { if(sizeof(color) != 4) { debug("Color size: %d", sizeof(color)); } color * screenpxp = (color*)&SCREEN[top-y][left+x]; color * imagepxp = (color*)&((uint32_t *)row_pointers[y])[x]; color imagepx = *imagepxp; color screenpx = *screenpxp; screenpx.r = imagepx.a * imagepx.r / 255 + (255 - imagepx.a) * screenpx.r / 255; screenpx.g = imagepx.a * imagepx.g / 255 + (255 - imagepx.a) * screenpx.g / 255; screenpx.b = imagepx.a * imagepx.b / 255 + (255 - imagepx.a) * screenpx.b / 255; setPixel(left+x,top-y,*(uint32_t *)&screenpx); } } png_destroy_read_struct(&png_ptr, &info_ptr, 0); pseudo_fclose(fp); return; }
Error ImageLoaderPNG::_load_image(void *rf_up, png_rw_ptr p_func, Ref<Image> p_image) { png_structp png; png_infop info; //png = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, _png_error_function, _png_warn_function, (png_voidp)NULL, _png_malloc_fn, _png_free_fn); ERR_FAIL_COND_V(!png, ERR_OUT_OF_MEMORY); info = png_create_info_struct(png); if (!info) { png_destroy_read_struct(&png, NULL, NULL); ERR_PRINT("Out of Memory"); return ERR_OUT_OF_MEMORY; } if (setjmp(png_jmpbuf(png))) { png_destroy_read_struct(&png, NULL, NULL); ERR_PRINT("PNG Corrupted"); return ERR_FILE_CORRUPT; } png_set_read_fn(png, (void *)rf_up, p_func); png_uint_32 width, height; int depth, color; png_read_info(png, info); png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); //https://svn.gov.pt/projects/ccidadao/repository/middleware-offline/trunk/_src/eidmw/FreeImagePTEiD/Source/FreeImage/PluginPNG.cpp //png_get_text(png,info,) /* printf("Image width:%i\n", width); printf("Image Height:%i\n", height); printf("Bit depth:%i\n", depth); printf("Color type:%i\n", color); */ bool update_info = false; if (depth < 8) { //only bit dept 8 per channel is handled png_set_packing(png); update_info = true; }; if (png_get_color_type(png, info) == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png); update_info = true; } if (depth > 8) { png_set_strip_16(png); update_info = true; } if (png_get_valid(png, info, PNG_INFO_tRNS)) { //png_set_expand_gray_1_2_4_to_8(png); png_set_tRNS_to_alpha(png); update_info = true; } if (update_info) { png_read_update_info(png, info); png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); } int components = 0; Image::Format fmt; switch (color) { case PNG_COLOR_TYPE_GRAY: { fmt = Image::FORMAT_L8; components = 1; } break; case PNG_COLOR_TYPE_GRAY_ALPHA: { fmt = Image::FORMAT_LA8; components = 2; } break; case PNG_COLOR_TYPE_RGB: { fmt = Image::FORMAT_RGB8; components = 3; } break; case PNG_COLOR_TYPE_RGB_ALPHA: { fmt = Image::FORMAT_RGBA8; components = 4; } break; default: { ERR_PRINT("INVALID PNG TYPE"); png_destroy_read_struct(&png, &info, NULL); return ERR_UNAVAILABLE; } break; } //int rowsize = png_get_rowbytes(png, info); int rowsize = components * width; PoolVector<uint8_t> dstbuff; dstbuff.resize(rowsize * height); PoolVector<uint8_t>::Write dstbuff_write = dstbuff.write(); uint8_t *data = dstbuff_write.ptr(); uint8_t **row_p = memnew_arr(uint8_t *, height); for (unsigned int i = 0; i < height; i++) { row_p[i] = &data[components * width * i]; } png_read_image(png, (png_bytep *)row_p); memdelete_arr(row_p); p_image->create(width, height, 0, fmt, dstbuff); png_destroy_read_struct(&png, &info, NULL); return OK; }
RADRT_API bool RADRT_CALL DecodeHeader(const void *buff, AddrSize buffLength, Image &out) { RAD_ASSERT(buff&&buffLength); RAD_ASSERT(buffLength <= std::numeric_limits<stream::SPos>::max()); out.Free(); stream::MemInputBuffer ib(buff, (stream::SPos)buffLength); stream::InputStream is(ib); { char sig[SigSize]; if (is.Read(sig, SigSize, 0) != SigSize) return false; // NOTE: png_sig_cmp() returns 0 if the sig matches the PNG sig. if (png_sig_cmp((png_bytep)sig, 0, SigSize)) return false; } png_structp png; png_infop info; png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, 0, PNGErrorHandler, PNGWarningHandler, 0, PNGMalloc, PNGFree); if (!png) return false; info = png_create_info_struct(png); if (!info) { png_destroy_read_struct(&png, 0, 0); return false; } png_set_read_fn(png, &is, PNGRead); png_set_sig_bytes(png, SigSize); try { png_uint_32 w, h; int bd, color, interlace; png_read_info(png, info); png_get_IHDR(png, info, &w, &h, &bd, &color, &interlace, 0, 0); if (!out.AllocateFrames(1)||!out.AllocateMipmaps(0, 1)) return false; Mipmap &m = out.frames[0].mipmaps[0]; out.format = Format(png, info, bd, color); if (out.format == InvalidFormat) { out.Free(); png_destroy_read_struct(&png, &info, 0); return false; } out.bpp = FormatBPP(out.format); m.width = w; m.height = h; m.stride = w * out.bpp; } catch (PNGException&) { out.Free(); png_destroy_read_struct(&png, &info, 0); return false; } png_destroy_read_struct(&png, &info, 0); return true; }
bool R9_ImgReadHeaderPNG( F9FILE file, r9Img* img ) { if(file==NULL || img==NULL) return false; R9_ImgDestroy(img); // check png sig const int headersize = 8; byte header[headersize]; if(file->Read( header, headersize)!=headersize) return false; BOOL ispng = png_check_sig(header, headersize) != 0; if(!ispng) { elog::rnd() << "png sig failed" << std::endl; return false; } // create png structures png_structp png_ptr = png_create_read_struct_2( PNG_LIBPNG_VER_STRING, NULL, R9_ImgPNG_FatalError, R9_ImgPNG_Warning, NULL, R9_ImgPNG_Malloc, R9_ImgPNG_Free ); if(png_ptr==NULL) return false; png_infop info_ptr = png_create_info_struct(png_ptr); if(info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return false; } png_infop end_info = png_create_info_struct(png_ptr); if(end_info == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return false; } // set global file r9_imgpng_file = file; png_set_read_fn(png_ptr, NULL, R9_ImgPNG_ReadData); // read off the info on the image png_set_sig_bytes(png_ptr, headersize); png_read_info(png_ptr, info_ptr); png_uint_32 pngwidth; png_uint_32 pngheight; int32 pngbits; int32 pngpf; png_get_IHDR(png_ptr, info_ptr, &pngwidth, &pngheight, &pngbits, &pngpf, NULL, // interlace NULL, // compression_type NULL); // filter_type BOOL alpha = FALSE; img->m_width = pngwidth; img->m_height = pngheight; img->m_pf = R9_PF_RGB; // release png_read_end(png_ptr, NULL); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); r9_imgpng_file = NULL; return true; }
/* Test one file */ int test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) { static png_FILE_p fpin; static png_FILE_p fpout; /* "static" prevents setjmp corruption */ png_structp read_ptr; png_infop read_info_ptr, end_info_ptr; #ifdef PNG_WRITE_SUPPORTED png_structp write_ptr; png_infop write_info_ptr; png_infop write_end_info_ptr; #else png_structp write_ptr = NULL; png_infop write_info_ptr = NULL; png_infop write_end_info_ptr = NULL; #endif png_bytep row_buf; png_uint_32 y; png_uint_32 width, height; int num_pass, pass; int bit_depth, color_type; #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD jmp_buf jmpbuf; #endif #endif #if defined(_WIN32_WCE) TCHAR path[MAX_PATH]; #endif char inbuf[256], outbuf[256]; row_buf = NULL; #if defined(_WIN32_WCE) MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) #else if ((fpin = fopen(inname, "rb")) == NULL) #endif { fprintf(STDERR, "Could not find input file %s\n", inname); return (1); } #if defined(_WIN32_WCE) MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE) #else if ((fpout = fopen(outname, "wb")) == NULL) #endif { fprintf(STDERR, "Could not open output file %s\n", outname); FCLOSE(fpin); return (1); } png_debug(0, "Allocating read and write structures\n"); #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); #else read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL); #endif #if defined(PNG_NO_STDIO) png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, pngtest_warning); #endif #ifdef PNG_WRITE_SUPPORTED #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); #else write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL); #endif #if defined(PNG_NO_STDIO) png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, pngtest_warning); #endif #endif png_debug(0, "Allocating read_info, write_info and end_info structures\n"); read_info_ptr = png_create_info_struct(read_ptr); end_info_ptr = png_create_info_struct(read_ptr); #ifdef PNG_WRITE_SUPPORTED write_info_ptr = png_create_info_struct(write_ptr); write_end_info_ptr = png_create_info_struct(write_ptr); #endif #ifdef PNG_SETJMP_SUPPORTED png_debug(0, "Setting jmpbuf for read struct\n"); #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) #else if (setjmp(png_jmpbuf(read_ptr))) #endif { fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); if (row_buf) png_free(read_ptr, row_buf); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); #ifdef PNG_WRITE_SUPPORTED png_destroy_info_struct(write_ptr, &write_end_info_ptr); png_destroy_write_struct(&write_ptr, &write_info_ptr); #endif FCLOSE(fpin); FCLOSE(fpout); return (1); } #ifdef USE_FAR_KEYWORD png_memcpy(png_jmpbuf(read_ptr),jmpbuf,png_sizeof(jmp_buf)); #endif #ifdef PNG_WRITE_SUPPORTED png_debug(0, "Setting jmpbuf for write struct\n"); #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) #else if (setjmp(png_jmpbuf(write_ptr))) #endif { fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); png_destroy_info_struct(write_ptr, &write_end_info_ptr); #ifdef PNG_WRITE_SUPPORTED png_destroy_write_struct(&write_ptr, &write_info_ptr); #endif FCLOSE(fpin); FCLOSE(fpout); return (1); } #ifdef USE_FAR_KEYWORD png_memcpy(png_jmpbuf(write_ptr),jmpbuf,png_sizeof(jmp_buf)); #endif #endif #endif png_debug(0, "Initializing input and output streams\n"); #if !defined(PNG_NO_STDIO) png_init_io(read_ptr, fpin); # ifdef PNG_WRITE_SUPPORTED png_init_io(write_ptr, fpout); # endif #else png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); # ifdef PNG_WRITE_SUPPORTED png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, # if defined(PNG_WRITE_FLUSH_SUPPORTED) pngtest_flush); # else NULL); # endif # endif #endif if(status_dots_requested == 1) { #ifdef PNG_WRITE_SUPPORTED png_set_write_status_fn(write_ptr, write_row_callback); #endif png_set_read_status_fn(read_ptr, read_row_callback); } else { #ifdef PNG_WRITE_SUPPORTED png_set_write_status_fn(write_ptr, png_write_status_ptr_NULL); #endif png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL); } #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) { int i; for(i=0; i<256; i++) filters_used[i]=0; png_set_read_user_transform_fn(read_ptr, count_filters); } #endif #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) zero_samples=0; png_set_write_user_transform_fn(write_ptr, count_zero_samples); #endif #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) # ifndef PNG_HANDLE_CHUNK_ALWAYS # define PNG_HANDLE_CHUNK_ALWAYS 3 # endif png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, png_bytep_NULL, 0); #endif #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) # ifndef PNG_HANDLE_CHUNK_IF_SAFE # define PNG_HANDLE_CHUNK_IF_SAFE 2 # endif png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE, png_bytep_NULL, 0); #endif png_debug(0, "Reading info struct\n"); png_read_info(read_ptr, read_info_ptr); png_debug(0, "Transferring info struct\n"); { int interlace_type, compression_type, filter_type; if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type)) { png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, #if defined(PNG_WRITE_INTERLACING_SUPPORTED) color_type, interlace_type, compression_type, filter_type); #else color_type, PNG_INTERLACE_NONE, compression_type, filter_type); #endif } }
RADRT_API bool RADRT_CALL Decode(const void *buff, AddrSize buffLength, Image &out) { RAD_ASSERT(buff&&buffLength); RAD_ASSERT(buffLength <= std::numeric_limits<stream::SPos>::max()); out.Free(); stream::MemInputBuffer ib(buff, (stream::SPos)buffLength); stream::InputStream is(ib); { char sig[SigSize]; if (is.Read(sig, SigSize, 0) != SigSize) return false; // NOTE: png_sig_cmp() returns 0 if the sig matches the PNG sig. if (png_sig_cmp((png_bytep)sig, 0, SigSize)) return false; } png_structp png; png_infop info; png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, 0, PNGErrorHandler, PNGWarningHandler, 0, PNGMalloc, PNGFree); if (!png) return false; info = png_create_info_struct(png); if (!info) { png_destroy_read_struct(&png, 0, 0); return false; } png_set_read_fn(png, &is, PNGRead); png_set_sig_bytes(png, SigSize); try { png_uint_32 w, h; int bd, color, interlace; png_read_info(png, info); png_get_IHDR(png, info, &w, &h, &bd, &color, &interlace, 0, 0); if (!out.AllocateFrames(1)||!out.AllocateMipmaps(0, 1)) { png_destroy_read_struct(&png, &info, 0); return false; } Mipmap &m = out.frames[0].mipmaps[0]; out.format = Format(png, info, bd, color); if (out.format == InvalidFormat) { out.Free(); png_destroy_read_struct(&png, &info, 0); return false; } out.bpp = FormatBPP(out.format); if (!out.AllocateMipmap(0, 0, w, h, w * out.bpp, w * h * out.bpp)) { out.Free(); png_destroy_read_struct(&png, &info, 0); return false; } png_set_strip_16(png); if (color == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png); } if (color == PNG_COLOR_TYPE_GRAY && bd < 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); } png_set_swap(png); int passes = png_set_interlace_handling(png); png_bytep dstRow = 0; png_bytep imgRow = 0; png_uint_32 stride = (png_uint_32)png_get_rowbytes(png, info); RAD_ASSERT(stride >= m.stride); if (stride != m.stride) { dstRow = (png_bytep)safe_zone_malloc(ZImageCodec, stride, 0); } for (int pass = 0; pass < passes; ++pass) { if (stride == m.stride) { dstRow = (png_bytep)m.data; // reset. } imgRow = (png_bytep)m.data; for (png_uint_32 y = 0; y < h; ++y) { if (pass > 0 && stride != m.stride) { RAD_ASSERT(imgRow != dstRow); // interlaced image, copy the result of the last pass. memcpy(dstRow, imgRow, m.stride); } png_read_rows(png, &dstRow, 0, 1); if (stride != m.stride) { // imgRow/dstRow are correct, we are copying from dstRow to imgRow. memcpy(imgRow, dstRow, m.stride); } else { dstRow += m.stride; } imgRow += m.stride; } } if (stride != m.stride) { RAD_ASSERT(dstRow); zone_free(dstRow); } png_read_end(png, info); } catch (PNGException&) { out.Free(); png_destroy_read_struct(&png, &info, 0); return false; } png_destroy_read_struct(&png, &info, 0); return true; }
int ReadPNG(const uint8_t* const data, size_t data_size, struct WebPPicture* const pic, int keep_alpha, struct Metadata* const metadata) { volatile png_structp png = NULL; volatile png_infop info = NULL; volatile png_infop end_info = NULL; PNGReadContext context = { NULL, 0, 0 }; int color_type, bit_depth, interlaced; int has_alpha; int num_passes; int p; volatile int ok = 0; png_uint_32 width, height, y; int64_t stride; uint8_t* volatile rgb = NULL; if (data == NULL || data_size == 0 || pic == NULL) return 0; context.data = data; context.data_size = data_size; png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, NULL, MallocFunc, FreeFunc); if (png == NULL) goto End; png_set_error_fn(png, 0, error_function, NULL); if (setjmp(png_jmpbuf(png))) { Error: MetadataFree(metadata); goto End; } info = png_create_info_struct(png); if (info == NULL) goto Error; end_info = png_create_info_struct(png); if (end_info == NULL) goto Error; png_set_read_fn(png, &context, ReadFunc); png_read_info(png, info); if (!png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, &interlaced, NULL, NULL)) goto Error; png_set_strip_16(png); png_set_packing(png); if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png); } if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { if (bit_depth < 8) { png_set_expand_gray_1_2_4_to_8(png); } png_set_gray_to_rgb(png); } if (png_get_valid(png, info, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png); has_alpha = 1; } else { has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA); } // Apply gamma correction if needed. { double image_gamma = 1 / 2.2, screen_gamma = 2.2; int srgb_intent; if (png_get_sRGB(png, info, &srgb_intent) || png_get_gAMA(png, info, &image_gamma)) { png_set_gamma(png, screen_gamma, image_gamma); } } if (!keep_alpha) { png_set_strip_alpha(png); has_alpha = 0; } num_passes = png_set_interlace_handling(png); png_read_update_info(png, info); stride = (int64_t)(has_alpha ? 4 : 3) * width * sizeof(*rgb); if (stride != (int)stride || !ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) { goto Error; } rgb = (uint8_t*)malloc((size_t)stride * height); if (rgb == NULL) goto Error; for (p = 0; p < num_passes; ++p) { png_bytep row = rgb; for (y = 0; y < height; ++y) { png_read_rows(png, &row, NULL, 1); row += stride; } } png_read_end(png, end_info); if (metadata != NULL && !ExtractMetadataFromPNG(png, info, end_info, metadata)) { fprintf(stderr, "Error extracting PNG metadata!\n"); goto Error; } pic->width = (int)width; pic->height = (int)height; ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, (int)stride) : WebPPictureImportRGB(pic, rgb, (int)stride); if (!ok) { goto Error; } End: if (png != NULL) { png_destroy_read_struct((png_structpp)&png, (png_infopp)&info, (png_infopp)&end_info); } free(rgb); return ok; }
static ImgloadErrorCode IMGLOAD_CALLBACK png_init_image(ImgloadPlugin plugin, ImgloadImage img) { png_structp png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, plugin, png_error_fn, png_warning_fn, plugin, png_malloc_fn, png_free_fn); if (png_ptr == NULL) { return IMGLOAD_ERR_PLUGIN_ERROR; } png_infop png_info = png_create_info_struct(png_ptr); if (png_info == NULL) { png_destroy_read_struct(&png_ptr, NULL, NULL); return IMGLOAD_ERR_PLUGIN_ERROR; } if (png_error_occured(png_ptr)) { // libPNG has caused an error, free memory and return png_destroy_read_struct(&png_ptr, &png_info, NULL); return IMGLOAD_ERR_PLUGIN_ERROR; } png_set_read_fn(png_ptr, img, png_user_read_data); png_set_sig_bytes(png_ptr, PNGSIGSIZE); png_read_info(png_ptr, png_info); // Info has been read png_uint_32 img_width = png_get_image_width(png_ptr, png_info); png_uint_32 img_height = png_get_image_height(png_ptr, png_info); png_uint_32 bitdepth = png_get_bit_depth(png_ptr, png_info); png_uint_32 color_type = png_get_color_type(png_ptr, png_info); if (bitdepth == 16) { png_set_strip_16(png_ptr); } switch (color_type) { case PNG_COLOR_TYPE_PALETTE: // Expand palette to rgb png_set_palette_to_rgb(png_ptr); break; case PNG_COLOR_TYPE_GRAY: if (bitdepth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); break; } // if the image has a transperancy set.. convert it to a full Alpha channel.. // Also make sure that is was RGB before if (png_get_valid(png_ptr, png_info, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); } // Update the structure so we can use it later png_read_update_info(png_ptr, png_info); bitdepth = png_get_bit_depth(png_ptr, png_info); uint32_t channels = png_get_channels(png_ptr, png_info); color_type = png_get_color_type(png_ptr, png_info); if (bitdepth != 8) { // Any bitdepth != 8 is not supported png_destroy_read_struct(&png_ptr, &png_info, NULL); imgload_plugin_log(plugin, IMGLOAD_LOG_ERROR, "PNG has a bitdepth of %"PRIu32" but only a bitdepth of 8 is supported by this plugin!", bitdepth); return IMGLOAD_ERR_UNSUPPORTED_FORMAT; } // Convert PNG format to imageloader. Also validates channel number ImgloadFormat format; if (color_type == PNG_COLOR_TYPE_RGB && channels == 3) { format = IMGLOAD_FORMAT_R8G8B8; } else if (color_type == PNG_COLOR_TYPE_RGBA && channels == 4) { format = IMGLOAD_FORMAT_R8G8B8A8; } else if (color_type == PNG_COLOR_TYPE_GRAY && channels == 1) { format = IMGLOAD_FORMAT_GRAY8; } else { // Currently no other format is supported png_destroy_read_struct(&png_ptr, &png_info, NULL); imgload_plugin_log(plugin, IMGLOAD_LOG_ERROR, "PNG has an unsupported data format!"); return IMGLOAD_ERR_UNSUPPORTED_FORMAT; } // Everything seems to be alright, set imageloader properties imgload_plugin_image_set_data_type(img, format, IMGLOAD_COMPRESSION_NONE); imgload_plugin_image_set_num_frames(img, 1); imgload_plugin_image_set_num_mipmaps(img, 0, 1); imgload_plugin_image_set_property(img, 0, IMGLOAD_PROPERTY_WIDTH, IMGLOAD_PROPERTY_TYPE_UINT32, &img_width); imgload_plugin_image_set_property(img, 0, IMGLOAD_PROPERTY_HEIGHT, IMGLOAD_PROPERTY_TYPE_UINT32, &img_height); // PNGs are always 2D so set depth to 1 uint32_t one = 1; imgload_plugin_image_set_property(img, 0, IMGLOAD_PROPERTY_DEPTH, IMGLOAD_PROPERTY_TYPE_UINT32, &one); PNGPointers* pointers = (PNGPointers*)imgload_plugin_realloc(plugin, NULL, sizeof(PNGPointers)); if (pointers == NULL) { // Currently no other format is supported png_destroy_read_struct(&png_ptr, &png_info, NULL); return IMGLOAD_ERR_OUT_OF_MEMORY; } pointers->png_ptr = png_ptr; pointers->info_ptr = png_info; imgload_plugin_image_set_data(img, pointers); return IMGLOAD_ERR_NO_ERROR; }
int xps_decode_png(xps_context_t *ctx, byte *rbuf, int rlen, xps_image_t *image) { png_structp png; png_infop info; struct xps_png_io_s io; int npasses; int pass; int y; /* * Set up PNG structs and input source */ io.ptr = rbuf; io.lim = rbuf + rlen; png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, ctx->memory, xps_png_malloc, xps_png_free); if (!png) return gs_throw(-1, "png_create_read_struct"); info = png_create_info_struct(png); if (!info) return gs_throw(-1, "png_create_info_struct"); png_set_read_fn(png, &io, xps_png_read); png_set_crc_action(png, PNG_CRC_WARN_USE, PNG_CRC_WARN_USE); /* * Jump to here on errors. */ if (setjmp(png_jmpbuf(png))) { png_destroy_read_struct(&png, &info, NULL); return gs_throw(-1, "png reading failed"); } /* * Read PNG header */ png_read_info(png, info); if (png_get_interlace_type(png, info) == PNG_INTERLACE_ADAM7) { npasses = png_set_interlace_handling(png); } else { npasses = 1; } if (png_get_color_type(png, info) == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png); } if (png_get_valid(png, info, PNG_INFO_tRNS)) { /* this will also expand the depth to 8-bits */ png_set_tRNS_to_alpha(png); } png_read_update_info(png, info); image->width = png_get_image_width(png, info); image->height = png_get_image_height(png, info); image->comps = png_get_channels(png, info); image->bits = png_get_bit_depth(png, info); /* See if we have an icc profile */ if (info->iccp_profile != NULL) { image->profilesize = info->iccp_proflen; image->profile = xps_alloc(ctx, info->iccp_proflen); if (image->profile) { /* If we can't create it, just ignore */ memcpy(image->profile, info->iccp_profile, info->iccp_proflen); } } switch (png_get_color_type(png, info)) { case PNG_COLOR_TYPE_GRAY: image->colorspace = ctx->gray; image->hasalpha = 0; break; case PNG_COLOR_TYPE_RGB: image->colorspace = ctx->srgb; image->hasalpha = 0; break; case PNG_COLOR_TYPE_GRAY_ALPHA: image->colorspace = ctx->gray; image->hasalpha = 1; break; case PNG_COLOR_TYPE_RGB_ALPHA: image->colorspace = ctx->srgb; image->hasalpha = 1; break; default: return gs_throw(-1, "cannot handle this png color type"); } /* * Extract DPI, default to 96 dpi */ image->xres = 96; image->yres = 96; if (info->valid & PNG_INFO_pHYs) { png_uint_32 xres, yres; int unit; png_get_pHYs(png, info, &xres, &yres, &unit); if (unit == PNG_RESOLUTION_METER) { image->xres = xres * 0.0254 + 0.5; image->yres = yres * 0.0254 + 0.5; } } /* * Read rows, filling transformed output into image buffer. */ image->stride = (image->width * image->comps * image->bits + 7) / 8; image->samples = xps_alloc(ctx, image->stride * image->height); for (pass = 0; pass < npasses; pass++) { for (y = 0; y < image->height; y++) { png_read_row(png, image->samples + (y * image->stride), NULL); } } /* * Clean up memory. */ png_destroy_read_struct(&png, &info, NULL); return gs_okay; }
//--------------------------------------------------------------------------- void __fastcall TDeePNG::LoadFromStream(Classes::TStream * Stream) { // LoadFromStream png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_infop end_info = NULL; png_bytep *row_pointers = NULL; BYTE *image = NULL; png_uint_32 i; try { // create png_struct png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)this, DeePNG_error, DeePNG_warning, (png_voidp)this, DeePNG_malloc, DeePNG_free); // set read_chunk_callback png_set_read_user_chunk_fn(png_ptr, reinterpret_cast<void*>(this), PNG_read_chunk_callback); png_set_keep_unknown_chunks(png_ptr, 2, NULL, 0); // keep only if safe-to-copy chunks, for all unknown chunks // create png_info info_ptr = png_create_info_struct(png_ptr); // create end_info end_info = png_create_info_struct(png_ptr); // set stream input functions png_set_read_fn(png_ptr, (voidp)Stream, DeePNG_read_data); // set read_row_callback png_set_read_status_fn(png_ptr, DeePNG_read_row_callback); // call png_read_info png_read_info(png_ptr, info_ptr); // retrieve IHDR png_uint_32 width, height; int bit_depth, color_type, interlace_type, compression_type, filter_type; png_get_IHDR(png_ptr,info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type); // expand palletted image which has transparent color, to 32bpp if (png_get_valid(png_ptr, info_ptr,PNG_INFO_tRNS)) { png_set_expand(png_ptr); color_type=PNG_COLOR_TYPE_RGB_ALPHA; } // analyse IHDR ( color_type ) switch(color_type) { case PNG_COLOR_TYPE_GRAY_ALPHA: PixelFormat=pf32bit; break; case PNG_COLOR_TYPE_GRAY: // w/b SetGrayscalePalette(this,bit_depth); break; case PNG_COLOR_TYPE_PALETTE: SetColorDepth(this,bit_depth); break; case PNG_COLOR_TYPE_RGB_ALPHA: PixelFormat=pf32bit; break; case PNG_COLOR_TYPE_RGB: PixelFormat=pf24bit; break; default: throw EDeePNG("EDeePNG : Non-supported color type."); } // retrieve offset information png_int_32 offset_x, offset_y; int offset_unit_type; if(png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &offset_unit_type)) { ofs_x = offset_x; ofs_y = offset_y; ofs_unit = offset_unit_type; ofs_set = true; } else { ofs_set = false; } // check size if(width>=65536 || height>=65536) { throw EDeePNG("EDeePNG : Too large image size."); } // retrieve palette if(color_type == PNG_COLOR_TYPE_PALETTE) { int num_palette; png_color *palette = NULL; png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); int i; #pragma pack(push, 1) struct { WORD palVersion; WORD palNumEntries; PALETTEENTRY entry[256]; } pal; #pragma pack(pop) pal.palVersion = 0x300; pal.palNumEntries = num_palette; for(i = 0; i < num_palette; i++) { pal.entry[i].peRed = palette[i].red; pal.entry[i].peGreen = palette[i].green; pal.entry[i].peBlue = palette[i].blue; pal.entry[i].peFlags = 0; } Palette = CreatePalette((const LOGPALETTE*)&pal); } // collapse 16bit precision data to 8bit if(bit_depth == 16) png_set_strip_16(png_ptr); // change color component order if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) png_set_bgr(png_ptr); // call png_read_update_info ... png_read_update_info(png_ptr, info_ptr); // set size Width=width, Height=height; // allocate memory for row_pointers row_pointers = new png_bytep[height]; png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr); image = new BYTE[rowbytes*height]; for(i = 0;i < height; i++) { row_pointers[i] = image + i*rowbytes; } // load image png_read_image(png_ptr, row_pointers); // finish loading image png_read_end(png_ptr, info_ptr); // set image to ScanLines BYTE *imageptr = image; if(color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { // IA IA IA .... for(i = 0; i < height; i++) { BYTE *scanptr = (BYTE*)ScanLine[i]; png_uint_32 j; for(j = 0; j < width; j++) { BYTE i = *(imageptr++); scanptr[0] = i; scanptr[1] = i; scanptr[2] = i; scanptr[3] = *(imageptr++); scanptr += 4; } } } else { // intact copy for(i = 0; i < height; i++) { BYTE *scanptr = (BYTE*)ScanLine[i]; memcpy(scanptr, imageptr, rowbytes); imageptr += rowbytes; } } } catch(...) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); if(row_pointers) delete [] row_pointers; if(image) delete [] image; throw; } png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); if(row_pointers) delete [] row_pointers; if(image) delete [] image; }