// Callbacks from the GIF reader. bool GIFImageDecoder::sizeNowAvailable(unsigned width, unsigned height) { if (!setSize(width, height)) return false; prepareScaleDataIfNecessary(); return true; }
bool PNGImageDecoder::setSize(unsigned width, unsigned height) { if (!ImageDecoder::setSize(width, height)) return false; prepareScaleDataIfNecessary(); return true; }
bool GIFImageDecoder::setSize(unsigned width, unsigned height) { if (ImageDecoder::isSizeAvailable() && size() == IntSize(width, height)) return true; if (!ImageDecoder::setSize(width, height)) return false; prepareScaleDataIfNecessary(); return true; }
bool GIFImageDecoder::setSize(int width, int height) { if (ImageDecoder::isSizeAvailable() && size().width() == width && size().height() == height) return true; if (!ImageDecoder::setSize(width, height)) return false; prepareScaleDataIfNecessary(); return true; }
void ImageDecoderQt::internalDecodeSize() { ASSERT(m_reader); // If we have a QSize() something failed QSize size = m_reader->size(); if (size.isEmpty()) { setFailed(); return clearPointers(); } setSize(size.width(), size.height()); // We don't need the tables set by prepareScaleDataIfNecessary, // but their dimensions are used by ImageDecoder::scaledSize(). prepareScaleDataIfNecessary(); if (m_scaled) m_reader->setScaledSize(scaledSize()); }
ImageFrame* PNGImageDecoder::frameBufferAtIndex(size_t index, const FloatSize& reqFrameSize) { #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) prepareScaleDataIfNecessary(reqFrameSize); #endif if (index) return 0; if (m_frameBufferCache.isEmpty()) { m_frameBufferCache.resize(1); m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha); } ImageFrame& frame = m_frameBufferCache[0]; if (frame.status() != ImageFrame::FrameComplete) { PlatformInstrumentation::willDecodeImage("PNG"); decode(false); PlatformInstrumentation::didDecodeImage(); } return &frame; }
void PNGImageDecoder::headerAvailable() { png_structp png = m_reader->pngPtr(); png_infop info = m_reader->infoPtr(); png_uint_32 width = png_get_image_width(png, info); png_uint_32 height = png_get_image_height(png, info); // Protect against large images. if (width > cMaxPNGSize || height > cMaxPNGSize) { longjmp(JMPBUF(png), 1); return; } // We can fill in the size now that the header is available. Avoid memory // corruption issues by neutering setFailed() during this call; if we don't // do this, failures will cause |m_reader| to be deleted, and our jmpbuf // will cease to exist. Note that we'll still properly set the failure flag // in this case as soon as we longjmp(). m_doNothingOnFailure = true; bool result = setSize(width, height); #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) prepareScaleDataIfNecessary(FloatSize(requestedFrameSize().width(), requestedFrameSize().height())); #endif m_doNothingOnFailure = false; if (!result) { longjmp(JMPBUF(png), 1); return; } int bitDepth, colorType, interlaceType, compressionType, filterType, channels; png_get_IHDR(png, info, &width, &height, &bitDepth, &colorType, &interlaceType, &compressionType, &filterType); // The options we set here match what Mozilla does. // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA. if (colorType == PNG_COLOR_TYPE_PALETTE || (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8)) png_set_expand(png); png_bytep trns = 0; int trnsCount = 0; if (png_get_valid(png, info, PNG_INFO_tRNS)) { png_get_tRNS(png, info, &trns, &trnsCount, 0); png_set_expand(png); } if (bitDepth == 16) png_set_strip_16(png); if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); if ((colorType & PNG_COLOR_MASK_COLOR) && !m_ignoreGammaAndColorProfile) { // We only support color profiles for color PALETTE and RGB[A] PNG. Supporting // color profiles for gray-scale images is slightly tricky, at least using the // CoreGraphics ICC library, because we expand gray-scale images to RGB but we // do not similarly transform the color profile. We'd either need to transform // the color profile or we'd need to decode into a gray-scale image buffer and // hand that to CoreGraphics. readColorProfile(png, info, m_colorProfile); #if USE(QCMSLIB) bool decodedImageHasAlpha = (colorType & PNG_COLOR_MASK_ALPHA) || trnsCount; m_reader->createColorTransform(m_colorProfile, decodedImageHasAlpha); m_colorProfile.clear(); #endif } // Deal with gamma and keep it under our control. double gamma; if (!m_ignoreGammaAndColorProfile && png_get_gAMA(png, info, &gamma)) { if ((gamma <= 0.0) || (gamma > cMaxGamma)) { gamma = cInverseGamma; png_set_gAMA(png, info, gamma); } png_set_gamma(png, cDefaultGamma, gamma); } else png_set_gamma(png, cDefaultGamma, cInverseGamma); // Tell libpng to send us rows for interlaced pngs. if (interlaceType == PNG_INTERLACE_ADAM7) png_set_interlace_handling(png); // Update our info now. png_read_update_info(png, info); channels = png_get_channels(png, info); ASSERT(channels == 3 || channels == 4); m_reader->setHasAlpha(channels == 4); if (m_reader->decodingSizeOnly()) { // If we only needed the size, halt the reader. #if defined(PNG_LIBPNG_VER_MAJOR) && defined(PNG_LIBPNG_VER_MINOR) && (PNG_LIBPNG_VER_MAJOR > 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 5)) // '0' argument to png_process_data_pause means: Do not cache unprocessed data. m_reader->setReadOffset(m_reader->currentBufferSize() - png_process_data_pause(png, 0)); #else m_reader->setReadOffset(m_reader->currentBufferSize() - png->buffer_size); png->buffer_size = 0; #endif } }