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 { } } } }
/*! \internal */ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage) { if (state == Error) return false; if (state == Ready && !readPngHeader()) { state = Error; return false; } row_pointers = 0; if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete [] row_pointers; png_ptr = 0; state = Error; return false; } setup_qt(*outImage, png_ptr, info_ptr, gamma); if (outImage->isNull()) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete [] row_pointers; png_ptr = 0; state = Error; return false; } 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 *data = outImage->bits(); int bpl = outImage->bytesPerLine(); row_pointers = new png_bytep[height]; for (uint y = 0; y < height; y++) row_pointers[y] = data + y * bpl; 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 (outImage->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 { } } } }
bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage) { if (state == Error) return false; if (state == Ready && !readPngHeader()) { state = Error; return false; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); png_ptr = 0; amp.deallocate(); state = Error; return false; } bool doScaledRead = false; setup_qt(*outImage, png_ptr, info_ptr, scaledSize, &doScaledRead, gamma, fileGamma); if (outImage->isNull()) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); png_ptr = 0; amp.deallocate(); state = Error; return false; } if (doScaledRead) { read_image_scaled(outImage, png_ptr, info_ptr, amp, scaledSize); } else { png_uint_32 width = 0; png_uint_32 height = 0; png_int_32 offset_x = 0; png_int_32 offset_y = 0; int bit_depth = 0; int color_type = 0; int unit_type = PNG_OFFSET_PIXEL; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &unit_type); uchar *data = outImage->bits(); int bpl = outImage->bytesPerLine(); amp.row_pointers = new png_bytep[height]; for (uint y = 0; y < height; y++) amp.row_pointers[y] = data + y * bpl; png_read_image(png_ptr, amp.row_pointers); amp.deallocate(); outImage->setDotsPerMeterX(png_get_x_pixels_per_meter(png_ptr,info_ptr)); outImage->setDotsPerMeterY(png_get_y_pixels_per_meter(png_ptr,info_ptr)); if (unit_type == PNG_OFFSET_PIXEL) outImage->setOffset(QPoint(offset_x, offset_y)); // sanity check palette entries if (color_type == PNG_COLOR_TYPE_PALETTE && outImage->format() == QImage::Format_Indexed8) { int color_table_size = outImage->colorCount(); for (int y=0; y<(int)height; ++y) { uchar *p = FAST_SCAN_LINE(data, bpl, y); uchar *end = p + width; while (p < end) { if (*p >= color_table_size) *p = 0; ++p; } } } } state = ReadingEnd; png_read_end(png_ptr, end_info); readPngTexts(end_info); for (int i = 0; i < readTexts.size()-1; i+=2) outImage->setText(readTexts.at(i), readTexts.at(i+1)); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); png_ptr = 0; amp.deallocate(); state = Ready; if (scaledSize.isValid() && outImage->size() != scaledSize) *outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); return true; }