bool PngLoader::basicImageLoad() { DEBUG_ENTER_FUNC(); _pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!_pngPtr) return false; png_set_error_fn(_pngPtr, (png_voidp) NULL, (png_error_ptr) NULL, warningFn); _infoPtr = png_create_info_struct(_pngPtr); if (!_infoPtr) { png_destroy_read_struct(&_pngPtr, png_infopp_NULL, png_infopp_NULL); return false; } // Set the png lib to use our read function png_set_read_fn(_pngPtr, &_file, libReadFunc); unsigned int sig_read = 0; png_set_sig_bytes(_pngPtr, sig_read); png_read_info(_pngPtr, _infoPtr); int interlaceType; png_get_IHDR(_pngPtr, _infoPtr, (png_uint_32 *)&_width, (png_uint_32 *)&_height, &_bitDepth, &_colorType, &interlaceType, int_p_NULL, int_p_NULL); _channels = png_get_channels(_pngPtr, _infoPtr); if (_colorType & PNG_COLOR_MASK_PALETTE) _paletteSize = _infoPtr->num_palette; return true; }
decoder::decoder(std::streambuf *sbuf, info &i) : input_(sbuf), png_(png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0)), info_(png_create_info_struct(png_)), end_(png_create_info_struct(png_)) { png_byte header[magic_]; input_->sgetn((char*)header, magic_); if (png_sig_cmp(header, 0, magic_)) throw std::runtime_error("Not a PNG file"); png_set_sig_bytes(png_, magic_); png_set_read_fn(png_, input_, decoder_read); png_set_error_fn(png_, input_, decoder_error, decoder_warning); png_set_read_status_fn(png_, 0); png_read_info(png_, info_); png_uint_32 w, h; int d, c, in, co, f; png_get_IHDR(png_, info_, &w, &h, &d, &c, &in, &co, &f); i.width = w; i.height = h; i.rowbytes = png_get_rowbytes(png_, info_); i.depth = d; i.colortype = static_cast<color_type>(c); i.compression = co; i.filter = f; i.interlace = static_cast<interlace_type>(in); }
/* Load a PNG file from disk, doing colour coversion if required. */ ALLEGRO_BITMAP *_al_load_png_f(ALLEGRO_FILE *fp, int flags) { jmp_buf jmpbuf; ALLEGRO_BITMAP *bmp; png_structp png_ptr; png_infop info_ptr; ALLEGRO_ASSERT(fp); if (!check_if_png(fp)) { ALLEGRO_ERROR("Not a png.\n"); return NULL; } /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also supply the * the compiler header file version, so that we know if the application * was compiled with a compatible version of the library. */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (void *)NULL, NULL, NULL); if (!png_ptr) { ALLEGRO_ERROR("png_ptr == NULL\n"); return NULL; } /* Allocate/initialize the memory for image information. */ info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); ALLEGRO_ERROR("png_create_info_struct failed\n"); return NULL; } /* Set error handling. */ if (setjmp(jmpbuf)) { /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); /* If we get here, we had a problem reading the file */ ALLEGRO_ERROR("Error reading PNG file\n"); return NULL; } png_set_error_fn(png_ptr, jmpbuf, user_error_fn, NULL); /* Use Allegro packfile routines. */ png_set_read_fn(png_ptr, fp, (png_rw_ptr) read_data); /* We have already read some of the signature. */ png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); /* Really load the image now. */ bmp = really_load_png(png_ptr, info_ptr, flags); /* Clean up after the read, and free any memory allocated. */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); return bmp; }
static bool png_create(Fl_IO &png_io, uint8 *&data, Fl_PixelFormat &fmt, int &w, int &h) { w=0, h=0; png_structp png_ptr = 0; png_infop info_ptr = 0, end_info_ptr = 0; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) { return_error(); } info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { return_error(); } end_info_ptr = png_create_info_struct(png_ptr); if(!end_info_ptr) { return_error(); } png_bytepp rows = 0; if(setjmp(png_ptr->jmpbuf)) { if(rows) free(rows); if(png_ptr) png_destroy_read_struct (&png_ptr, &info_ptr, &end_info_ptr); fputs((const char *)png_last_error, stderr); return false; } int ctype = 0; int pitch=0, bitspp=0; int ckey = -1; int i=0; uint32 Rmask=0, Gmask=0, Bmask=0, Amask=0; png_color_16 *transv=0; Fl_Colormap *palette=0; png_set_error_fn(png_ptr, (png_voidp)0, my_png_error, my_png_warning); png_set_read_fn(png_ptr, (png_voidp)&png_io, read_data_fn); png_read_info(png_ptr, info_ptr); if(!setup_png_transformations(png_ptr, info_ptr, transv, ctype, ckey, bitspp, w, h)) goto error; if(ctype != PNG_COLOR_TYPE_PALETTE) { #if !WORDS_BIGENDIAN Rmask = 0x000000FF; Gmask = 0x0000FF00; Bmask = 0x00FF0000; Amask = (info_ptr->channels == 4) ? 0xFF000000 : 0; #else int s = (info_ptr->channels == 4) ? 0 : 8; Rmask = 0xFF000000 >> s; Gmask = 0x00FF0000 >> s; Bmask = 0x0000FF00 >> s; Amask = 0x000000FF >> s; #endif if(info_ptr->channels == 4) fmt.masktype = FL_MASK_ALPHA; }
encoder::encoder(std::streambuf *sb, info const &i) : output_(sb), png_(png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0)), info_(png_create_info_struct(png_)) { png_set_write_fn(png_, output_, encoder_write, encoder_flush); png_set_error_fn(png_, output_, encoder_error, encoder_warning); png_set_write_status_fn(png_, 0); png_set_IHDR(png_, info_, i.width, i.height, i.depth, i.colortype, i.interlace, i.compression, i.filter); }
/* Initialize png_ptr structure, and allocate any memory needed */ png_structp png_create_write_struct(png_const_charp user_png_ver, voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn) { png_structp png_ptr; #ifdef USE_FAR_KEYWORD jmp_buf jmpbuf; #endif png_debug(1, "in png_create_write_struct\n"); if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL) { return (png_structp)NULL; } #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) #else if (setjmp(png_ptr->jmpbuf)) #endif { png_free(png_ptr, png_ptr->zbuf); png_destroy_struct(png_ptr); return (png_structp)NULL; } #ifdef USE_FAR_KEYWORD png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf)); #endif png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so * we must recompile any applications that use any older library version. * For versions after libpng 1.0, we will be compatible, so we need * only check the first digit. */ if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || (png_libpng_ver[0] == '0' && user_png_ver[2] < '9')) { png_error(png_ptr, "Incompatible libpng version in application and library"); } /* initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf = png_malloc(png_ptr, png_ptr->zbuf_size); png_set_write_fn(png_ptr, NULL, NULL, NULL); return (png_ptr); }
void PNGImageCodec::Save(OutputStreamPtr& file, const ImageParams& params, const ImageData& data) { OutputStream* writr = file.GetPtr(); if (data.format != PixelFormat::BGRA8 && data.format != PixelFormat::RGBA8) // todo support formats like rgba16 etc. NEX_THROW_FatalError(EXCEPT_NOT_IMPLEMENTED); png_structp pngPtr = nullptr; png_infop infoPtr = nullptr; png_byte ** rowPointers = nullptr; // todo Fix for 64 uint32 bitDepth = 32; size_t rowStride = data.width * bitDepth; bool flip = (data.format == PixelFormat::BGRA8); pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (pngPtr == nullptr) goto failed; infoPtr = png_create_info_struct(pngPtr); if (infoPtr == nullptr) goto failed; png_set_error_fn(pngPtr, (void *) (writr), PngWarn, PngWarn); png_set_write_fn(pngPtr, (void *) (writr), PngWriteFile, PngFlushFile); png_set_IHDR(pngPtr, infoPtr, data.width, data.height, bitDepth, // assumed PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); rowPointers = (png_byte**) NEX_ALLOC(sizeof(png_byte*) * data.height, MEMCAT_GENERAL); for (uint32 i = 0; i < data.height; ++i) { rowPointers[i] = (static_cast<uint8*>(data.data)) + i * rowStride; } png_set_rows(pngPtr, infoPtr, rowPointers); png_write_png(pngPtr, infoPtr, flip ? PNG_TRANSFORM_BGR : PNG_TRANSFORM_IDENTITY, NULL); failed: if (rowPointers) NEX_FREE(rowPointers, MEMCAT_GENERAL); if (pngPtr) png_destroy_write_struct(&pngPtr, &infoPtr); }
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); }
bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngHeader() { state = Error; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) return false; png_set_error_fn(png_ptr, 0, 0, qt_png_warning); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, 0, 0); png_ptr = 0; return false; } end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, 0); png_ptr = 0; return false; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); png_ptr = 0; return false; } png_set_read_fn(png_ptr, this, iod_read_fn); png_read_info(png_ptr, info_ptr); readPngTexts(info_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) { double file_gamma = 0.0; png_get_gAMA(png_ptr, info_ptr, &file_gamma); fileGamma = file_gamma; } state = ReadHeader; return true; }
void png_reader<T>::init() { png_byte header[8]; std::memset(header,0,8); stream_.read(reinterpret_cast<char*>(header),8); if ( stream_.gcount() != 8) { throw image_reader_exception("PNG reader: Could not read image"); } int is_png=!png_sig_cmp(header,0,8); if (!is_png) { throw image_reader_exception("File or stream is not a png"); } png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { throw image_reader_exception("failed to allocate png_ptr"); } // catch errors in a custom way to avoid the need for setjmp png_set_error_fn(png_ptr, png_get_error_ptr(png_ptr), user_error_fn, user_warning_fn); png_infop info_ptr; png_struct_guard sguard(&png_ptr,&info_ptr); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) throw image_reader_exception("failed to create info_ptr"); png_set_read_fn(png_ptr, (png_voidp)&stream_, png_read_data); png_set_sig_bytes(png_ptr,8); png_read_info(png_ptr, info_ptr); png_uint_32 width, height; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth_, &color_type_,0,0,0); has_alpha_ = (color_type_ & PNG_COLOR_MASK_ALPHA) || png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); width_=width; height_=height; MAPNIK_LOG_DEBUG(png_reader) << "png_reader: bit_depth=" << bit_depth_ << ",color_type=" << color_type_; }
static nserror nspng_create_png_data(nspng_content *png_c) { union content_msg_data msg_data; png_c->bitmap = NULL; png_c->png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (png_c->png == NULL) { msg_data.error = messages_get("NoMemory"); content_broadcast(&png_c->base, CONTENT_MSG_ERROR, msg_data); warn_user("NoMemory", 0); return NSERROR_NOMEM; } png_set_error_fn(png_c->png, NULL, nspng_error, nspng_warning); png_c->info = png_create_info_struct(png_c->png); if (png_c->info == NULL) { png_destroy_read_struct(&png_c->png, &png_c->info, 0); msg_data.error = messages_get("NoMemory"); content_broadcast(&png_c->base, CONTENT_MSG_ERROR, msg_data); warn_user("NoMemory", 0); return NSERROR_NOMEM; } if (setjmp(png_jmpbuf(png_c->png))) { png_destroy_read_struct(&png_c->png, &png_c->info, 0); LOG(("Failed to set callbacks")); png_c->png = NULL; png_c->info = NULL; msg_data.error = messages_get("PNGError"); content_broadcast(&png_c->base, CONTENT_MSG_ERROR, msg_data); return NSERROR_NOMEM; } png_set_progressive_read_fn(png_c->png, png_c, info_callback, row_callback, end_callback); return NSERROR_OK; }
FXPNG_Context* CCodec_PngModule::Start(void* pModule) { FXPNG_Context* p = (FXPNG_Context*)FX_Alloc(uint8_t, sizeof(FXPNG_Context)); if (!p) return nullptr; p->m_AllocFunc = _png_alloc_func; p->m_FreeFunc = _png_free_func; p->png_ptr = nullptr; p->info_ptr = nullptr; p->parent_ptr = (void*)this; p->child_ptr = pModule; p->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (!p->png_ptr) { FX_Free(p); return nullptr; } p->info_ptr = png_create_info_struct(p->png_ptr); if (!p->info_ptr) { png_destroy_read_struct(&(p->png_ptr), nullptr, nullptr); FX_Free(p); return nullptr; } if (setjmp(png_jmpbuf(p->png_ptr))) { if (p) { png_destroy_read_struct(&(p->png_ptr), &(p->info_ptr), nullptr); FX_Free(p); } return nullptr; } png_set_progressive_read_fn(p->png_ptr, p, _png_get_header_func, _png_get_row_func, _png_get_end_func); png_set_error_fn(p->png_ptr, m_szLastError, (png_error_ptr)_png_error_data, (png_error_ptr)_png_warning_data); return p; }
/* Alternate create PNG structure for reading, and allocate any memory needed. */ png_structp PNGAPI png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn) { #endif /* PNG_USER_MEM_SUPPORTED */ png_structp png_ptr; #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD jmp_buf jmpbuf; #endif #endif int i; png_debug(1, "in png_create_read_struct\n"); #ifdef PNG_USER_MEM_SUPPORTED png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); #else png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); #endif if (png_ptr == NULL) return (NULL); #if !defined(PNG_1_0_X) #ifdef PNG_ASSEMBLER_CODE_SUPPORTED png_init_mmx_flags(png_ptr); /* 1.2.0 addition */ #endif #endif /* PNG_1_0_X */ /* added at libpng-1.2.6 */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED png_ptr->user_width_max=PNG_USER_WIDTH_MAX; png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; #endif #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) #else if (setjmp(png_ptr->jmpbuf)) #endif { png_free(png_ptr, png_ptr->zbuf); png_ptr->zbuf=NULL; #ifdef PNG_USER_MEM_SUPPORTED png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, (png_voidp)mem_ptr); #else png_destroy_struct((png_voidp)png_ptr); #endif return (NULL); } #ifdef USE_FAR_KEYWORD png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); #endif #endif #ifdef PNG_USER_MEM_SUPPORTED png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); #endif png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); i=0; do { if(user_png_ver[i] != png_libpng_ver[i]) png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; } while (png_libpng_ver[i++]); if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) { /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so * we must recompile any applications that use any older library version. * For versions after libpng 1.0, we will be compatible, so we need * only check the first digit. */ if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || (user_png_ver[0] == '0' && user_png_ver[2] < '9')) { #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) char msg[80]; if (user_png_ver) { sprintf(msg, "Application was compiled with png.h from libpng-%.20s", user_png_ver); png_warning(png_ptr, msg); } sprintf(msg, "Application is running with png.c from libpng-%.20s", png_libpng_ver); png_warning(png_ptr, msg); #endif #ifdef PNG_ERROR_NUMBERS_SUPPORTED png_ptr->flags=0; #endif png_error(png_ptr, "Incompatible libpng version in application and library"); } } /* initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size); png_ptr->zstream.zalloc = png_zalloc; png_ptr->zstream.zfree = png_zfree; png_ptr->zstream.opaque = (voidpf)png_ptr; switch (inflateInit(&png_ptr->zstream)) { case Z_OK: /* Do nothing */ break; case Z_MEM_ERROR: case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break; case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break; default: png_error(png_ptr, "Unknown zlib error"); } png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); #ifdef PNG_SETJMP_SUPPORTED /* Applications that neglect to set up their own setjmp() and then encounter a png_error() will longjmp here. Since the jmpbuf is then meaningless we abort instead of returning. */ #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) PNG_ABORT(); png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); #else if (setjmp(png_ptr->jmpbuf)) PNG_ABORT(); #endif #endif return (png_ptr); }
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 }
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; }
/* * EncodeBlock */ static block_t *EncodeBlock(encoder_t *p_enc, picture_t *p_pic) { encoder_sys_t *p_sys = p_enc->p_sys; if( unlikely( !p_pic ) ) { return NULL; } block_t *p_block = block_Alloc( p_sys->i_blocksize ); if( p_block == NULL ) { return NULL; } png_structp p_png = png_create_write_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ); if( p_png == NULL ) { block_Release( p_block ); return NULL; } /* save buffer start */ uint8_t *p_start = p_block->p_buffer; size_t i_start = p_block->i_buffer; p_sys->b_error = false; png_infop p_info = NULL; /* libpng longjmp's there in case of error */ if( setjmp( png_jmpbuf( p_png ) ) ) goto error; png_set_write_fn( p_png, p_block, user_write, user_flush ); png_set_error_fn( p_png, p_enc, user_error, user_warning ); p_info = png_create_info_struct( p_png ); if( p_info == NULL ) goto error; png_infop p_end_info = png_create_info_struct( p_png ); if( p_end_info == NULL ) goto error; const unsigned i_width = p_enc->fmt_in.video.i_visible_width; const unsigned i_height = p_enc->fmt_in.video.i_visible_height; png_set_IHDR( p_png, p_info, i_width, i_height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); if( p_sys->b_error ) goto error; png_write_info( p_png, p_info ); if( p_sys->b_error ) goto error; /* Encode picture */ for( unsigned i = 0; i < i_height; i++ ) { png_write_row( p_png, p_pic->p->p_pixels + (i_width * i * 3)); if( p_sys->b_error ) goto error; } png_write_end( p_png, p_end_info ); if( p_sys->b_error ) goto error; png_destroy_write_struct( &p_png, &p_info ); /* restore original buffer position */ p_block->p_buffer = p_start; p_block->i_buffer = i_start - p_block->i_buffer; p_block->i_dts = p_block->i_pts = p_pic->date; return p_block; error: png_destroy_write_struct( &p_png, p_info ? &p_info : NULL ); block_Release(p_block); return NULL; }
bool writePNG(Common::WriteStream &out, const Graphics::Surface &input, const bool bottomUp) { #ifdef USE_PNG const Graphics::PixelFormat requiredFormat_3byte(3, 8, 8, 8, 0, 16, 8, 0, 0); const Graphics::PixelFormat requiredFormat_4byte(4, 8, 8, 8, 8, 0, 8, 16, 24); if (input.format.bytesPerPixel == 3) { if (input.format != requiredFormat_3byte) { warning("Cannot currently write PNG with 3-byte pixel format other than %s", requiredFormat_3byte.toString().c_str()); return false; } } else if (input.format.bytesPerPixel != 4) { warning("Cannot currently write PNG with pixel format of bpp other than 3, 4"); return false; } int colorType; Graphics::Surface *tmp = NULL; const Graphics::Surface *surface; if (input.format == requiredFormat_3byte) { surface = &input; colorType = PNG_COLOR_TYPE_RGB; } else { if (input.format == requiredFormat_4byte) { surface = &input; } else { surface = tmp = input.convertTo(requiredFormat_4byte); } colorType = PNG_COLOR_TYPE_RGB_ALPHA; } png_structp pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!pngPtr) { return false; } png_infop infoPtr = png_create_info_struct(pngPtr); if (!infoPtr) { png_destroy_write_struct(&pngPtr, NULL); return false; } png_set_error_fn(pngPtr, NULL, pngError, pngWarning); // TODO: The manual says errors should be handled via setjmp png_set_write_fn(pngPtr, &out, pngWriteToStream, pngFlushStream); png_set_IHDR(pngPtr, infoPtr, surface->w, surface->h, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); Common::Array<const uint8 *> rows; rows.reserve(surface->h); if (bottomUp) { for (uint y = surface->h; y-- > 0;) { rows.push_back((const uint8 *)surface->getBasePtr(0, y)); } } else { for (uint y = 0; y < surface->h; ++y) { rows.push_back((const uint8 *)surface->getBasePtr(0, y)); } } png_set_rows(pngPtr, infoPtr, const_cast<uint8 **>(&rows.front())); png_write_png(pngPtr, infoPtr, 0, NULL); png_destroy_write_struct(&pngPtr, &infoPtr); // free tmp surface if (tmp) { tmp->free(); delete tmp; } return true; #else return false; #endif }
bool PNGImageFileType::read( Image *OSG_PNG_ARG(pImage ), std::istream &OSG_PNG_ARG(is ), const std::string &OSG_PNG_ARG(mimetype)) { #ifdef OSG_WITH_PNG bool retCode; Image::PixelFormat pixelFormat = OSG::Image::OSG_INVALID_PF; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, wc, height, h, i, res_x, res_y; png_byte bit_depth, channels, color_type; png_bytep *row_pointers, base; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if(!png_ptr) return false; png_set_error_fn(png_ptr, 0, &errorOutput, &warningOutput); info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_read_struct(&png_ptr, 0, 0); return false; } if(setjmp(png_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, 0); return false; } png_set_read_fn(png_ptr, &is, &isReadFunc); 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); bit_depth = png_get_bit_depth(png_ptr, info_ptr); res_x = png_get_x_pixels_per_meter(png_ptr, info_ptr); res_y = png_get_y_pixels_per_meter(png_ptr, info_ptr); channels = png_get_channels(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); // Convert paletted images to RGB if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); channels = 3; bit_depth = 8; } // Convert < 8 bit to 8 bit if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { png_set_gray_1_2_4_to_8(png_ptr); bit_depth = 8; } #if BYTE_ORDER == LITTLE_ENDIAN if (bit_depth == 16) png_set_swap(png_ptr); #endif // Add a full alpha channel if there is transparency // information in a tRNS chunk if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); ++channels; } Int32 dataType; switch (bit_depth) { case 8: dataType = Image::OSG_UINT8_IMAGEDATA; break; case 16: dataType = Image::OSG_UINT16_IMAGEDATA; break; default: FWARNING (( "Invalid bit_depth: %d, can not read png-data\n", bit_depth )); return false; } switch(channels) { case 1: pixelFormat = Image::OSG_L_PF; break; case 2: pixelFormat = Image::OSG_LA_PF; break; case 3: pixelFormat = Image::OSG_RGB_PF; break; case 4: pixelFormat = Image::OSG_RGBA_PF; break; }; if(pImage->set(pixelFormat, width, height, 1, 1, 1, 0.0, 0, dataType)) { // set resolution png supports only pixel per meter, // so we do a conversion to dpi with some rounding. res_x = png_uint_32((Real32(res_x) / 39.37007874f) < 0.0f ? (Real32(res_x) / 39.37007874f) - 0.5f : (Real32(res_x) / 39.37007874f) + 0.5f); res_y = png_uint_32((Real32(res_y) / 39.37007874f) < 0.0f ? (Real32(res_y) / 39.37007874f) - 0.5f : (Real32(res_y) / 39.37007874f) + 0.5f); pImage->setResX(Real32(res_x)); pImage->setResY(Real32(res_y)); pImage->setResUnit(Image::OSG_RESUNIT_INCH); // Calculate the row pointers row_pointers = new png_bytep[height]; wc = width * channels * (bit_depth / 8); h = height - 1; base = pImage->editData(); for(i = 0; i < height; ++i) row_pointers[i] = base + (h - i) * wc; // Read the image data png_read_image(png_ptr, row_pointers); delete[] row_pointers; retCode = true; } else { retCode = false; } png_destroy_read_struct(&png_ptr, &info_ptr, 0); return retCode; #else SWARNING << getMimeType() << " read is not compiled into the current binary " << std::endl; return false; #endif }
/**************************************************************************** * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with a complete compressed frame. ****************************************************************************/ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; picture_t *p_pic = 0; png_uint_32 i_width, i_height; int i_color_type, i_interlace_type, i_compression_type, i_filter_type; int i_bit_depth, i; png_structp p_png; png_infop p_info, p_end_info; png_bytep *p_row_pointers = NULL; if( !pp_block || !*pp_block ) return NULL; p_block = *pp_block; p_sys->b_error = false; if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) { block_Release( p_block ); *pp_block = NULL; return NULL; } p_png = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ); if( p_png == NULL ) { block_Release( p_block ); *pp_block = NULL; return NULL; } p_info = png_create_info_struct( p_png ); if( p_info == NULL ) { png_destroy_read_struct( &p_png, NULL, NULL ); block_Release( p_block ); *pp_block = NULL; return NULL; } p_end_info = png_create_info_struct( p_png ); if( p_end_info == NULL ) { png_destroy_read_struct( &p_png, &p_info, NULL ); block_Release( p_block ); *pp_block = NULL; return NULL; } /* libpng longjmp's there in case of error */ if( setjmp( png_jmpbuf( p_png ) ) ) goto error; png_set_read_fn( p_png, (void *)p_block, user_read ); png_set_error_fn( p_png, (void *)p_dec, user_error, user_warning ); png_read_info( p_png, p_info ); if( p_sys->b_error ) goto error; png_get_IHDR( p_png, p_info, &i_width, &i_height, &i_bit_depth, &i_color_type, &i_interlace_type, &i_compression_type, &i_filter_type); if( p_sys->b_error ) goto error; /* Set output properties */ p_dec->fmt_out.i_codec = VLC_CODEC_RGBA; p_dec->fmt_out.video.i_visible_width = p_dec->fmt_out.video.i_width = i_width; p_dec->fmt_out.video.i_visible_height = p_dec->fmt_out.video.i_height = i_height; p_dec->fmt_out.video.i_sar_num = 1; p_dec->fmt_out.video.i_sar_den = 1; p_dec->fmt_out.video.i_rmask = 0x000000ff; p_dec->fmt_out.video.i_gmask = 0x0000ff00; p_dec->fmt_out.video.i_bmask = 0x00ff0000; if( i_color_type == PNG_COLOR_TYPE_PALETTE ) png_set_palette_to_rgb( p_png ); if( i_color_type == PNG_COLOR_TYPE_GRAY || i_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) png_set_gray_to_rgb( p_png ); /* Strip to 8 bits per channel */ if( i_bit_depth == 16 ) png_set_strip_16( p_png ); if( png_get_valid( p_png, p_info, PNG_INFO_tRNS ) ) { png_set_tRNS_to_alpha( p_png ); } else if( !(i_color_type & PNG_COLOR_MASK_ALPHA) ) { p_dec->fmt_out.i_codec = VLC_CODEC_RGB24; } /* Get a new picture */ p_pic = decoder_NewPicture( p_dec ); if( !p_pic ) goto error; /* Decode picture */ p_row_pointers = malloc( sizeof(png_bytep) * i_height ); if( !p_row_pointers ) goto error; for( i = 0; i < (int)i_height; i++ ) p_row_pointers[i] = p_pic->p->p_pixels + p_pic->p->i_pitch * i; png_read_image( p_png, p_row_pointers ); if( p_sys->b_error ) goto error; png_read_end( p_png, p_end_info ); if( p_sys->b_error ) goto error; png_destroy_read_struct( &p_png, &p_info, &p_end_info ); free( p_row_pointers ); p_pic->date = p_block->i_pts > VLC_TS_INVALID ? p_block->i_pts : p_block->i_dts; block_Release( p_block ); *pp_block = NULL; return p_pic; error: free( p_row_pointers ); png_destroy_read_struct( &p_png, &p_info, &p_end_info ); block_Release( p_block ); *pp_block = NULL; return NULL; }
static rt_bool_t rtgui_image_png_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load) { png_uint_32 width; png_uint_32 height; int bit_depth; int color_type; double gamma; struct rtgui_image_png *png; png = (struct rtgui_image_png *) rtgui_malloc(sizeof(struct rtgui_image_png)); png->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png->png_ptr == RT_NULL) { rtgui_free(png); return RT_FALSE; } png_set_error_fn(png->png_ptr, RT_NULL, _image_png_error_fn, _image_png_error_fn); png->info_ptr = png_create_info_struct(png->png_ptr); if (png->info_ptr == RT_NULL) { png_destroy_read_struct(&png->png_ptr, NULL, NULL); rtgui_free(png); return RT_FALSE; } png->filerw = file; png->is_loaded = RT_FALSE; png_set_read_fn(png->png_ptr, png->filerw, rtgui_image_png_read_data); png_read_info(png->png_ptr, png->info_ptr); png_get_IHDR(png->png_ptr, png->info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); /* set image information */ image->w = width; image->h = height; image->engine = &rtgui_image_png_engine; image->data = png; if (bit_depth == 16) png_set_strip_16(png->png_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand(png->png_ptr); if (bit_depth < 8) png_set_expand(png->png_ptr); if (png_get_valid(png->png_ptr, png->info_ptr, PNG_INFO_tRNS)) png_set_expand(png->png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png->png_ptr); /* Ignore background color */ /* set gamma conversion */ if (png_get_gAMA(png->png_ptr, png->info_ptr, &gamma)) png_set_gamma(png->png_ptr, (double)2.2, gamma); png_read_update_info(png->png_ptr, png->info_ptr); if (load == RT_TRUE) { /* load all pixels */ png->pixels = rtgui_malloc(image->w * image->h * sizeof(rtgui_color_t)); if (png->pixels == RT_NULL) { png_read_end(png->png_ptr, RT_NULL); /* destroy png struct */ png_destroy_info_struct(png->png_ptr, &png->info_ptr); png_destroy_read_struct(&png->png_ptr, RT_NULL, RT_NULL); /* release data */ rtgui_free(png); return RT_FALSE; } rtgui_image_png_process(png->png_ptr, png->info_ptr, png); png_read_end(png->png_ptr, RT_NULL); png->is_loaded = RT_TRUE; /* close file handler */ rtgui_filerw_close(png->filerw); png->filerw = RT_NULL; } else { png->pixels = RT_NULL; } return RT_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 } }
static void read_png_image(QImageIO* iio) { png_structp png_ptr; png_infop info_ptr; png_infop end_info; png_bytep* row_pointers; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { iio->setStatus(-1); return; } png_set_error_fn(png_ptr, 0, 0, qt_png_warning); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, 0, 0); iio->setStatus(-2); return; } end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, 0); iio->setStatus(-3); return; } if (setjmp(png_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); iio->setStatus(-4); return; } png_set_read_fn(png_ptr, (void*)iio, iod_read_fn); png_read_info(png_ptr, info_ptr); QImage image; setup_qt(image, png_ptr, info_ptr, iio->gamma()); if (image.isNull()) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); iio->setStatus(-5); return; } png_uint_32 width; png_uint_32 height; int bit_depth; int color_type; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); uchar** jt = image.jumpTable(); row_pointers=new png_bytep[height]; for (uint y=0; y<height; y++) { row_pointers[y]=jt[y]; } png_read_image(png_ptr, row_pointers); #if 0 // libpng takes care of this. png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) if (image.depth()==32 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { QRgb trans = 0xFF000000 | qRgb( (info_ptr->trans_values.red << 8 >> bit_depth)&0xff, (info_ptr->trans_values.green << 8 >> bit_depth)&0xff, (info_ptr->trans_values.blue << 8 >> bit_depth)&0xff); for (uint y=0; y<height; y++) { for (uint x=0; x<info_ptr->width; x++) { if (((uint**)jt)[y][x] == trans) { ((uint**)jt)[y][x] &= 0x00FFFFFF; } else { } } } }
int ReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha, Metadata* const metadata) { png_structp png; png_infop info = NULL; png_infop end_info = NULL; int color_type, bit_depth, interlaced; int has_alpha; int num_passes; int p; int ok = 0; png_uint_32 width, height, y; int stride; uint8_t* rgb = NULL; png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (png == NULL) { goto End; } png_set_error_fn(png, 0, error_function, NULL); if (setjmp(png_jmpbuf(png))) { Error: MetadataFree(metadata); png_destroy_read_struct(&png, &info, &end_info); 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_init_io(png, in_file); 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); } 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 = (has_alpha ? 4 : 3) * width * sizeof(*rgb); rgb = (uint8_t*)malloc(stride * height); if (rgb == NULL) goto Error; for (p = 0; p < num_passes; ++p) { for (y = 0; y < height; ++y) { png_bytep row = rgb + y * stride; png_read_rows(png, &row, NULL, 1); } } png_read_end(png, end_info); if (metadata != NULL && !ExtractMetadataFromPNG(png, info, end_info, metadata)) { fprintf(stderr, "Error extracting PNG metadata!\n"); goto Error; } png_destroy_read_struct(&png, &info, &end_info); pic->width = width; pic->height = height; ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, stride) : WebPPictureImportRGB(pic, rgb, stride); if (!ok) { goto Error; } End: free(rgb); return ok; }
gboolean read_png(curlMemoryStructGCS *chunk, unsigned char **raw_image, picSrcImageInfoGCS *info, char *errBuf) { png_structp png_ptr; png_infop info_ptr; /* initialize stuff */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { GST_DEBUG("png_create_read_struct failed"); strcpy(errBuf, "read_png - Error : png_create_read_struct failed"); return FALSE; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { GST_DEBUG("png_create_info_struct failed"); strcpy(errBuf, "read_png - Error : png_create_info_struct failed"); return FALSE; } FILE* memstream = fmemopen((void *)chunk->memory, chunk->size, "rb"); if (!memstream) { GST_DEBUG("fmemopen failed"); strcpy(errBuf, "read_imgheader - Error : fmemopen failed"); return FALSE; } png_init_io(png_ptr, memstream); png_set_error_fn(png_ptr, (png_voidp)NULL, png_error_fn, png_warning_fn); /* read file */ if (setjmp(png_jmpbuf(png_ptr))) { sprintf(errBuf, "read_png - Error : %s", "undetermined"); fclose(memstream); return FALSE; } png_uint_32 imgWidth, imgHeight; int bitdepth, color_type; png_read_info(png_ptr, info_ptr); png_get_IHDR( png_ptr, info_ptr, &imgWidth, &imgHeight, &bitdepth, &color_type, 0, 0, 0 ); //Number of channels int channels = png_get_channels(png_ptr, info_ptr); switch (color_type) { case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(png_ptr); channels = 3; info->colorspace = COLOR_TYPE_GCS_RGB; break; case PNG_COLOR_TYPE_GRAY: if (bitdepth < 8) png_set_gray_1_2_4_to_8(png_ptr); //And the bitdepth info bitdepth = 8; png_set_gray_to_rgb(png_ptr); info->colorspace = COLOR_TYPE_GCS_RGB; break; } /*if the image has a transperancy set.. convert it to a full Alpha channel..*/ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); channels+=1; info->colorspace = COLOR_TYPE_GCS_RGB_ALPHA; } //We don't support 16 bit precision.. so if the image Has 16 bits per channel //precision... round it down to 8. if (bitdepth == 16) png_set_strip_16(png_ptr); info->width = imgWidth; info->height = imgHeight; info->channels = channels; /* read file */ if (setjmp(png_jmpbuf(png_ptr))) { sprintf(errBuf, "read_png - Error : %s", "undetermined"); fclose(memstream); return FALSE; } png_bytep* rowPtrs[imgHeight]; *raw_image = (unsigned char*)malloc(imgWidth * imgHeight * bitdepth * channels / 8); const unsigned int stride = imgWidth * bitdepth * channels / 8; GST_DEBUG("imgWidth:%d, imgHeight:%d, bitdepth:%d, channels:%d, stride:%d", imgWidth,imgHeight,bitdepth,channels, stride ); size_t i; for (i = 0; i < imgHeight; i++) { rowPtrs[i] = (png_bytep*)((png_bytep)(*raw_image) + ( i * stride)); } png_read_image(png_ptr, (png_bytepp)rowPtrs); fclose(memstream); return TRUE; }
ImageContext* PNGImageLoader::loadHeader(PixelFormat& formatSource, DataSource* data) { PNGImageContext* png = new PNGImageContext(data); if (!png) { return 0; } // Prepare png loading png->d_png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (png->d_png_ptr == 0) { delete png; return 0; } png->d_info_ptr = png_create_info_struct(png->d_png_ptr); if (png->d_info_ptr == 0) { delete png; return 0; } if (setjmp(png_jmpbuf(png->d_png_ptr))) { delete png; return 0; } png_set_error_fn(png->d_png_ptr, 0, PNG_error_function, PNG_warning_function); png_set_read_fn(png->d_png_ptr, png, PNG_read_function); //png_set_sig_bytes(png->d_png_ptr, 8); // Read header Check whether PNG can depaletize transparently or not int png_transform = PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_EXPAND; //printf("Start reading png\n"); png_read_png(png->d_png_ptr, png->d_info_ptr, png_transform, 0); png->setImageSize(); png->d_bit_depth = png_get_bit_depth(png->d_png_ptr, png->d_info_ptr); png->d_num_channels = png_get_channels(png->d_png_ptr, png->d_info_ptr); //printf("PNG Info: width: %d height: %d bpp: %d channels: %d\n", png->getWidth(), png->getHeight(), png->d_bit_depth, png->d_num_channels); if (png->d_bit_depth == 8) { if (png->d_num_channels == 4) { formatSource = PF_RGBA; } else if (png->d_num_channels == 3) { formatSource = PF_RGB; } else { delete png; return 0; } } // Paletized or grayscale not yet handled else { delete png; return 0; } return png; }
UInt64 PNGImageFileType::restoreData( Image *OSG_PNG_ARG (pImage ), const UChar8 *OSG_PNG_ARG (buffer ), Int32 OSG_CHECK_ARG(memSize)) { #ifdef OSG_WITH_PNG UInt64 retCode; Image::PixelFormat pixelFormat = Image::OSG_INVALID_PF; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, wc, height, h, i; png_byte bit_depth, channels, color_type; png_bytep *row_pointers, base; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if(!png_ptr) { return 0; } png_set_error_fn(png_ptr, 0, &errorOutput, &warningOutput); info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_read_struct(&png_ptr, 0, 0); return 0; } if(setjmp(png_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, 0); return 0; } BufferInfo bufferInfo; bufferInfo.buffer = const_cast<UChar8 *>(buffer); bufferInfo.length = 0; png_set_read_fn(png_ptr, static_cast<void *>(&bufferInfo), user_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); bit_depth = png_get_bit_depth(png_ptr, info_ptr); channels = png_get_channels(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); // Convert paletted images to RGB if(color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); channels = 3; bit_depth = 8; } // Convert < 8 bit to 8 bit if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { png_set_gray_1_2_4_to_8(png_ptr); bit_depth = 8; } #if BYTE_ORDER == LITTLE_ENDIAN if (bit_depth == 16) png_set_swap(png_ptr); #endif // Add a full alpha channel if there is transparency // information in a tRNS chunk if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); ++channels; } Int32 dataType; switch (bit_depth) { case 8: dataType = Image::OSG_UINT8_IMAGEDATA; break; case 16: dataType = Image::OSG_UINT16_IMAGEDATA; break; default: FWARNING (( "Invalid bit_depth: %d, can not read png-data\n", bit_depth )); return false; } switch(channels) { case 1: pixelFormat = Image::OSG_L_PF; break; case 2: pixelFormat = Image::OSG_LA_PF; break; case 3: pixelFormat = Image::OSG_RGB_PF; break; case 4: pixelFormat = Image::OSG_RGBA_PF; break; }; if(pImage->set(pixelFormat, width, height, 1, 1, 1, 0.0, 0, dataType)) { // Calculate the row pointers row_pointers = new png_bytep[height]; wc = width * channels * (bit_depth / 8); h = height - 1; base = pImage->editData(); for(i = 0; i < height; ++i) row_pointers[i] = base + (h - i) * wc; // Read the image data png_read_image(png_ptr, row_pointers); delete[] row_pointers; retCode = bufferInfo.length; } else { retCode = 0; } png_destroy_read_struct(&png_ptr, &info_ptr, 0); return retCode; #else SWARNING << getMimeType() << " restoreData is not compiled into the current binary " << std::endl; return 0; #endif }
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; }
int read_png(const std::string & file_name, image_t & image) { png_structp png; png_infop info; int color_type, bit_depth, interlaced; int has_alpha; int num_passes; int p; int ok = 0; png_uint_32 width, height, y; int stride; uint8_t* rgb = NULL; FILE * fp; #ifdef LINUX fp = fopen(file_name.c_str(), "rb"); #endif #ifdef WINDOWS fopen_s(&fp, file_name.c_str(), "rb"); #endif if (fp == NULL) throw webp::exception::FileOperationException(); png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (png == NULL) { goto End; } png_set_error_fn(png, 0, error_function, NULL); if (setjmp(png_jmpbuf(png))) { Error: png_destroy_read_struct(&png, NULL, NULL); free(rgb); goto End; } info = png_create_info_struct(png); if (info == NULL) goto Error; png_init_io(png, fp); 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); } num_passes = png_set_interlace_handling(png); png_read_update_info(png, info); stride = (has_alpha ? 4 : 3) * width * sizeof(*rgb); rgb = (uint8_t*)malloc(stride * height); if (rgb == NULL) goto Error; for (p = 0; p < num_passes; ++p) { for (y = 0; y < height; ++y) { png_bytep row = rgb + y * stride; png_read_rows(png, &row, NULL, 1); } } png_read_end(png, info); png_destroy_read_struct(&png, &info, NULL); image.width = width; image.height = height; image.image.realloc(height * width); for(size_t y = 0; y < height; y++) for(size_t x = 0; x < width; x++){ size_t i = y * width + x; if (has_alpha) { *webp::utils::ALPHA(image.image[i]) = rgb[stride * y + x * 4]; *webp::utils::RED(image.image[i]) = rgb[stride * y + x * 4 + 1]; *webp::utils::GREEN(image.image[i]) = rgb[stride * y + x * 4 + 2]; *webp::utils::BLUE(image.image[i]) = rgb[stride * y + x * 4 + 3]; } else{ *webp::utils::ALPHA(image.image[i]) = 0xFF; *webp::utils::RED(image.image[i]) = rgb[stride * y + x * 3]; *webp::utils::GREEN(image.image[i]) = rgb[stride * y + x * 3 + 1]; *webp::utils::BLUE(image.image[i]) = rgb[stride * y + x * 3 + 2]; } } free(rgb); End: fclose(fp); return ok; }
/* Alternate create PNG structure for reading, and allocate any memory * needed. */ png_structp PNGAPI png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn) { #endif /* PNG_USER_MEM_SUPPORTED */ #ifdef PNG_SETJMP_SUPPORTED volatile #endif png_structp png_ptr; volatile int png_cleanup_needed = 0; #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD jmp_buf jmpbuf; #endif #endif int i; png_debug(1, "in png_create_read_struct"); #ifdef PNG_USER_MEM_SUPPORTED png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, malloc_fn, mem_ptr); #else png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); #endif if (png_ptr == NULL) return (NULL); /* Added at libpng-1.2.6 */ #ifdef PNG_USER_LIMITS_SUPPORTED png_ptr->user_width_max = PNG_USER_WIDTH_MAX; png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; # ifdef PNG_USER_CHUNK_CACHE_MAX /* Added at libpng-1.2.43 and 1.4.0 */ png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; # endif # ifdef PNG_SET_USER_CHUNK_MALLOC_MAX /* Added at libpng-1.2.43 and 1.4.1 */ png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; # endif #endif #ifdef PNG_SETJMP_SUPPORTED /* Applications that neglect to set up their own setjmp() and then encounter a png_error() will longjmp here. Since the jmpbuf is then meaningless we abort instead of returning. */ #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) #else if (setjmp(png_jmpbuf(png_ptr))) /* Sets longjmp to match setjmp */ #endif PNG_ABORT(); #ifdef USE_FAR_KEYWORD png_memcpy(png_jmpbuf(png_ptr), jmpbuf, png_sizeof(jmp_buf)); #endif #endif /* PNG_SETJMP_SUPPORTED */ #ifdef PNG_USER_MEM_SUPPORTED png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); #endif png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); if (user_png_ver) { i = 0; do { if (user_png_ver[i] != png_libpng_ver[i]) png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; } while (png_libpng_ver[i++]); } else png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) { /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so * we must recompile any applications that use any older library version. * For versions after libpng 1.0, we will be compatible, so we need * only check the first digit. */ if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || (user_png_ver[0] == '0' && user_png_ver[2] < '9')) { #ifdef PNG_STDIO_SUPPORTED char msg[80]; if (user_png_ver) { png_snprintf(msg, 80, "Application was compiled with png.h from libpng-%.20s", user_png_ver); png_warning(png_ptr, msg); } png_snprintf(msg, 80, "Application is running with png.c from libpng-%.20s", png_libpng_ver); png_warning(png_ptr, msg); #endif #ifdef PNG_ERROR_NUMBERS_SUPPORTED png_ptr->flags = 0; #endif png_warning(png_ptr, "Incompatible libpng version in application and library"); png_cleanup_needed = 1; } } if (!png_cleanup_needed) { /* Initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, png_ptr->zbuf_size); if (png_ptr->zbuf == NULL) png_cleanup_needed = 1; } png_ptr->zstream.zalloc = png_zalloc; png_ptr->zstream.zfree = png_zfree; png_ptr->zstream.opaque = (voidpf)png_ptr; if (!png_cleanup_needed) { switch (inflateInit(&png_ptr->zstream)) { case Z_OK: /* Do nothing */ break; case Z_MEM_ERROR: case Z_STREAM_ERROR: png_warning(png_ptr, "zlib memory error"); png_cleanup_needed = 1; break; case Z_VERSION_ERROR: png_warning(png_ptr, "zlib version error"); png_cleanup_needed = 1; break; default: png_warning(png_ptr, "Unknown zlib error"); png_cleanup_needed = 1; } } if (png_cleanup_needed) { /* Clean up PNG structure and deallocate any memory. */ png_free(png_ptr, png_ptr->zbuf); png_ptr->zbuf = NULL; #ifdef PNG_USER_MEM_SUPPORTED png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, (png_voidp)mem_ptr); #else png_destroy_struct((png_voidp)png_ptr); #endif return (NULL); } png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; png_set_read_fn(png_ptr, NULL, NULL); return (png_ptr); }
void png_reader<T>::read(unsigned x0, unsigned y0,image_data_32& image) { stream_.clear(); stream_.seekg(0, std::ios_base::beg); png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { throw image_reader_exception("failed to allocate png_ptr"); } // catch errors in a custom way to avoid the need for setjmp png_set_error_fn(png_ptr, png_get_error_ptr(png_ptr), user_error_fn, user_warning_fn); png_infop info_ptr; png_struct_guard sguard(&png_ptr,&info_ptr); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) throw image_reader_exception("failed to create info_ptr"); png_set_read_fn(png_ptr, (png_voidp)&stream_, png_read_data); png_read_info(png_ptr, info_ptr); if (color_type_ == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); if (color_type_ == PNG_COLOR_TYPE_GRAY && bit_depth_ < 8) png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); if (bit_depth_ == 16) png_set_strip_16(png_ptr); if (color_type_ == PNG_COLOR_TYPE_GRAY || color_type_ == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); // quick hack -- only work in >=libpng 1.2.7 png_set_add_alpha(png_ptr,0xff,PNG_FILLER_AFTER); //rgba double gamma; if (png_get_gAMA(png_ptr, info_ptr, &gamma)) png_set_gamma(png_ptr, 2.2, gamma); if (x0 == 0 && y0 == 0 && image.width() >= width_ && image.height() >= height_) { if (png_get_interlace_type(png_ptr,info_ptr) == PNG_INTERLACE_ADAM7) { png_set_interlace_handling(png_ptr); // FIXME: libpng bug? // according to docs png_read_image // "..automatically handles interlacing, // so you don't need to call png_set_interlace_handling()" } png_read_update_info(png_ptr, info_ptr); // we can read whole image at once // alloc row pointers const std::unique_ptr<png_bytep[]> rows(new png_bytep[height_]); for (unsigned i=0; i<height_; ++i) rows[i] = (png_bytep)image.getRow(i); png_read_image(png_ptr, rows.get()); } else { png_read_update_info(png_ptr, info_ptr); unsigned w=std::min(unsigned(image.width()),width_ - x0); unsigned h=std::min(unsigned(image.height()),height_ - y0); unsigned rowbytes=png_get_rowbytes(png_ptr, info_ptr); const std::unique_ptr<png_byte[]> row(new png_byte[rowbytes]); //START read image rows for (unsigned i = 0;i < height_; ++i) { png_read_row(png_ptr,row.get(),0); if (i >= y0 && i < (y0 + h)) { image.setRow(i-y0,reinterpret_cast<unsigned*>(&row[x0 * 4]),w); } } //END } png_read_end(png_ptr,0); }