From 462031467e75e857f403b3d8a4b3d71b3bce0b67 Mon Sep 17 00:00:00 2001 From: Glenn Randers-Pehrson Date: Wed, 24 Sep 2014 17:38:00 -0400 Subject: [PATCH] Bug 1072340 - Clean up PNG codecs in image/encoders,decoders. r=jmuizelaar --HG-- extra : rebase_source : e8789fd34910ae510483034a769e77e70e644198 --- image/decoders/nsPNGDecoder.cpp | 181 +++++++++++----------------- image/decoders/nsPNGDecoder.h | 6 +- image/encoders/png/nsPNGEncoder.cpp | 53 ++++---- image/encoders/png/nsPNGEncoder.h | 25 ++-- 4 files changed, 117 insertions(+), 148 deletions(-) diff --git a/image/decoders/nsPNGDecoder.cpp b/image/decoders/nsPNGDecoder.cpp index d29045b12a5..b71bd7c843c 100644 --- a/image/decoders/nsPNGDecoder.cpp +++ b/image/decoders/nsPNGDecoder.cpp @@ -4,23 +4,18 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "ImageLogging.h" -#include "nsPNGDecoder.h" - -#include "nsMemory.h" -#include "nsRect.h" - -#include "nsIInputStream.h" - -#include "RasterImage.h" - +#include "ImageLogging.h" // Must appear first #include "gfxColor.h" +#include "gfxPlatform.h" #include "nsColor.h" - +#include "nsIInputStream.h" +#include "nsMemory.h" +#include "nsPNGDecoder.h" +#include "nsRect.h" #include "nspr.h" #include "png.h" +#include "RasterImage.h" -#include "gfxPlatform.h" #include namespace mozilla { @@ -46,7 +41,7 @@ GetPNGDecoderAccountingLog() } #endif -/* limit image dimensions (bug #251381, #591822, and #967656) */ +// Limit image dimensions (bug #251381, #591822, and #967656) #ifndef MOZ_PNG_MAX_DIMENSION # define MOZ_PNG_MAX_DIMENSION 32767 #endif @@ -69,7 +64,7 @@ nsPNGDecoder::AnimFrameInfo::AnimFrameInfo(png_structp aPNG, png_infop aInfo) , mTimeout(0) { png_uint_16 delay_num, delay_den; - /* delay, in seconds is delay_num/delay_den */ + // delay, in seconds is delay_num/delay_den png_byte dispose_op; png_byte blend_op; delay_num = png_get_next_frame_delay_num(aPNG, aInfo); @@ -85,7 +80,8 @@ nsPNGDecoder::AnimFrameInfo::AnimFrameInfo(png_structp aPNG, png_infop aInfo) // Need to cast delay_num to float to have a proper division and // the result to int to avoid compiler warning - mTimeout = static_cast(static_cast(delay_num) * 1000 / delay_den); + mTimeout = static_cast(static_cast(delay_num) * + 1000 / delay_den); } if (dispose_op == PNG_DISPOSE_OP_PREVIOUS) { @@ -131,7 +127,7 @@ nsPNGDecoder::~nsPNGDecoder() if (mInProfile) { qcms_profile_release(mInProfile); - /* mTransform belongs to us only if mInProfile is non-null */ + // mTransform belongs to us only if mInProfile is non-null if (mTransform) qcms_transform_release(mTransform); } @@ -195,7 +191,8 @@ void nsPNGDecoder::EndImageFrame() } #endif - PostFrameStop(alpha, mAnimInfo.mDispose, mAnimInfo.mTimeout, mAnimInfo.mBlend); + PostFrameStop(alpha, mAnimInfo.mDispose, mAnimInfo.mTimeout, + mAnimInfo.mBlend); } void @@ -209,31 +206,32 @@ nsPNGDecoder::InitInternal() mCMSMode = gfxPlatform::GetCMSMode(); if ((mDecodeFlags & DECODER_NO_COLORSPACE_CONVERSION) != 0) mCMSMode = eCMSMode_Off; - mDisablePremultipliedAlpha = (mDecodeFlags & DECODER_NO_PREMULTIPLY_ALPHA) != 0; + mDisablePremultipliedAlpha = (mDecodeFlags & DECODER_NO_PREMULTIPLY_ALPHA) + != 0; #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED static png_byte color_chunks[]= - { 99, 72, 82, 77, '\0', /* cHRM */ - 105, 67, 67, 80, '\0'}; /* iCCP */ + { 99, 72, 82, 77, '\0', // cHRM + 105, 67, 67, 80, '\0'}; // iCCP static png_byte unused_chunks[]= - { 98, 75, 71, 68, '\0', /* bKGD */ - 104, 73, 83, 84, '\0', /* hIST */ - 105, 84, 88, 116, '\0', /* iTXt */ - 111, 70, 70, 115, '\0', /* oFFs */ - 112, 67, 65, 76, '\0', /* pCAL */ - 115, 67, 65, 76, '\0', /* sCAL */ - 112, 72, 89, 115, '\0', /* pHYs */ - 115, 66, 73, 84, '\0', /* sBIT */ - 115, 80, 76, 84, '\0', /* sPLT */ - 116, 69, 88, 116, '\0', /* tEXt */ - 116, 73, 77, 69, '\0', /* tIME */ - 122, 84, 88, 116, '\0'}; /* zTXt */ + { 98, 75, 71, 68, '\0', // bKGD + 104, 73, 83, 84, '\0', // hIST + 105, 84, 88, 116, '\0', // iTXt + 111, 70, 70, 115, '\0', // oFFs + 112, 67, 65, 76, '\0', // pCAL + 115, 67, 65, 76, '\0', // sCAL + 112, 72, 89, 115, '\0', // pHYs + 115, 66, 73, 84, '\0', // sBIT + 115, 80, 76, 84, '\0', // sPLT + 116, 69, 88, 116, '\0', // tEXt + 116, 73, 77, 69, '\0', // tIME + 122, 84, 88, 116, '\0'}; // zTXt #endif - /* For full decodes, do png init stuff */ + // For full decodes, do png init stuff - /* Initialize the container's source image header. */ - /* Always decode to 24 bit pixdepth */ + // Initialize the container's source image header + // Always decode to 24 bit pixdepth mPNG = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nsPNGDecoder::error_callback, @@ -251,7 +249,7 @@ nsPNGDecoder::InitInternal() } #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - /* Ignore unused chunks */ + // Ignore unused chunks if (mCMSMode == eCMSMode_Off) png_set_keep_unknown_chunks(mPNG, 1, color_chunks, 2); @@ -266,23 +264,22 @@ nsPNGDecoder::InitInternal() #ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED #ifndef PR_LOGGING - /* Disallow palette-index checking, for speed; we would ignore the warning - * anyhow unless we have defined PR_LOGGING. This feature was added at - * libpng version 1.5.10 and is disabled in the embedded libpng but enabled - * by default in the system libpng. This call also disables it in the - * system libpng, for decoding speed. Bug #745202. - */ + // Disallow palette-index checking, for speed; we would ignore the warning + // anyhow unless we have defined PR_LOGGING. This feature was added at + // libpng version 1.5.10 and is disabled in the embedded libpng but enabled + // by default in the system libpng. This call also disables it in the + // system libpng, for decoding speed. Bug #745202. png_set_check_for_invalid_index(mPNG, 0); #endif #endif #if defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_sRGB_PROFILE_CHECKS) && \ PNG_sRGB_PROFILE_CHECKS >= 0 - /* Skip checking of sRGB ICC profiles */ + // Skip checking of sRGB ICC profiles png_set_option(mPNG, PNG_SKIP_sRGB_CHECK_PROFILE, PNG_OPTION_ON); #endif - /* use this as libpng "progressive pointer" (retrieve in callbacks) */ + // use this as libpng "progressive pointer" (retrieve in callbacks) png_set_progressive_read_fn(mPNG, static_cast(this), nsPNGDecoder::info_callback, nsPNGDecoder::row_callback, @@ -291,7 +288,8 @@ nsPNGDecoder::InitInternal() } void -nsPNGDecoder::WriteInternal(const char *aBuffer, uint32_t aCount, DecodeStrategy) +nsPNGDecoder::WriteInternal(const char *aBuffer, uint32_t aCount, + DecodeStrategy) { NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!"); @@ -393,24 +391,14 @@ PNGGetColorProfile(png_structp png_ptr, png_infop info_ptr, // First try to see if iCCP chunk is present if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) { png_uint_32 profileLen; -#if (PNG_LIBPNG_VER < 10500) - char *profileData, *profileName; -#else png_bytep profileData; png_charp profileName; -#endif int compression; png_get_iCCP(png_ptr, info_ptr, &profileName, &compression, &profileData, &profileLen); - profile = qcms_profile_from_memory( -#if (PNG_LIBPNG_VER < 10500) - profileData, -#else - (char *)profileData, -#endif - profileLen); + profile = qcms_profile_from_memory((char *)profileData, profileLen); if (profile) { uint32_t profileSpace = qcms_profile_get_color_space(profile); @@ -498,7 +486,7 @@ PNGGetColorProfile(png_structp png_ptr, png_infop info_ptr, void nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr) { -/* int number_passes; NOT USED */ +// int number_passes; NOT USED png_uint_32 width, height; int bit_depth, color_type, interlace_type, compression_type, filter_type; unsigned int channels; @@ -509,19 +497,19 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr) nsPNGDecoder *decoder = static_cast(png_get_progressive_ptr(png_ptr)); - /* always decode to 24-bit RGB or 32-bit RGBA */ + // Always decode to 24-bit RGB or 32-bit RGBA png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type); - /* Are we too big? */ + // Are we too big? if (width > MOZ_PNG_MAX_DIMENSION || height > MOZ_PNG_MAX_DIMENSION) - longjmp(png_jmpbuf(decoder->mPNG), 1); + png_longjmp(decoder->mPNG, 1); // Post our size to the superclass decoder->PostSize(width, height); if (decoder->HasError()) { // Setting the size led to an error. - longjmp(png_jmpbuf(decoder->mPNG), 1); + png_longjmp(decoder->mPNG, 1); } if (color_type == PNG_COLOR_TYPE_PALETTE) @@ -534,10 +522,10 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr) int sample_max = (1 << bit_depth); png_color_16p trans_values; png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values); - /* libpng doesn't reject a tRNS chunk with out-of-range samples - so we check it here to avoid setting up a useless opacity - channel or producing unexpected transparent pixels when using - libpng-1.2.19 through 1.2.26 (bug #428045) */ + // libpng doesn't reject a tRNS chunk with out-of-range samples + // so we check it here to avoid setting up a useless opacity + // channel or producing unexpected transparent pixels when using + // libpng-1.2.19 through 1.2.26 (bug #428045) if ((color_type == PNG_COLOR_TYPE_GRAY && (int)trans_values->gray > sample_max) || (color_type == PNG_COLOR_TYPE_RGB && @@ -545,7 +533,7 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr) (int)trans_values->green > sample_max || (int)trans_values->blue > sample_max))) { - /* clear the tRNS valid flag and release tRNS memory */ + // clear the tRNS valid flag and release tRNS memory png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); } else @@ -562,7 +550,7 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr) intent = gfxPlatform::GetRenderingIntent(); decoder->mInProfile = PNGGetColorProfile(png_ptr, info_ptr, color_type, &inType, &pIntent); - /* If we're not mandating an intent, use the one from the image. */ + // If we're not mandating an intent, use the one from the image. if (intent == uint32_t(-1)) intent = pIntent; } @@ -594,42 +582,20 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr) } } - /* let libpng expand interlaced images */ + // let libpng expand interlaced images if (interlace_type == PNG_INTERLACE_ADAM7) { - /* number_passes = */ + // number_passes = png_set_interlace_handling(png_ptr); } - /* now all of those things we set above are used to update various struct - * members and whatnot, after which we can get channels, rowbytes, etc. */ + // now all of those things we set above are used to update various struct + // members and whatnot, after which we can get channels, rowbytes, etc. png_read_update_info(png_ptr, info_ptr); decoder->mChannels = channels = png_get_channels(png_ptr, info_ptr); - /*---------------------------------------------------------------*/ - /* copy PNG info into imagelib structs (formerly png_set_dims()) */ - /*---------------------------------------------------------------*/ - - // This code is currently unused, but it will be needed for bug 517713. -#if 0 - int32_t alpha_bits = 1; - - if (channels == 2 || channels == 4) { - /* check if alpha is coming from a tRNS chunk and is binary */ - if (num_trans) { - /* if it's not an indexed color image, tRNS means binary */ - if (color_type == PNG_COLOR_TYPE_PALETTE) { - for (int i=0; iformat = gfx::SurfaceFormat::B8G8R8X8; @@ -656,7 +622,7 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr) decoder->mCMSLine = (uint8_t *)moz_malloc(bpp[channels] * width); if (!decoder->mCMSLine) { - longjmp(png_jmpbuf(decoder->mPNG), 5); // NS_ERROR_OUT_OF_MEMORY + png_longjmp(decoder->mPNG, 5); // NS_ERROR_OUT_OF_MEMORY } } @@ -664,14 +630,13 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr) if (height < INT32_MAX / (width * channels)) decoder->interlacebuf = (uint8_t *)moz_malloc(channels * width * height); if (!decoder->interlacebuf) { - longjmp(png_jmpbuf(decoder->mPNG), 5); // NS_ERROR_OUT_OF_MEMORY + png_longjmp(decoder->mPNG, 5); // NS_ERROR_OUT_OF_MEMORY } } if (decoder->NeedsNewFrame()) { - /* We know that we need a new frame, so pause input so the decoder - * infrastructure can give it to us. - */ + // We know that we need a new frame, so pause input so the decoder + // infrastructure can give it to us. png_process_data_pause(png_ptr, /* save = */ 1); } } @@ -735,7 +700,7 @@ nsPNGDecoder::row_callback(png_structp png_ptr, png_bytep new_row, if (decoder->mCMSLine) { qcms_transform_data(decoder->mTransform, line, decoder->mCMSLine, iwidth); - /* copy alpha over */ + // copy alpha over uint32_t channels = decoder->mChannels; if (channels == 2 || channels == 4) { for (uint32_t i = 0; i < iwidth; i++) @@ -786,7 +751,8 @@ nsPNGDecoder::row_callback(png_structp png_ptr, png_bytep new_row, } } else { for (uint32_t x=width; x>0; --x) { - *cptr32++ = gfxPackedPixelNoPreMultiply(line[3], line[0], line[1], line[2]); + *cptr32++ = gfxPackedPixelNoPreMultiply(line[3], line[0], line[1], + line[2]); if (line[3] != 0xff) rowHasNoAlpha = false; line += 4; @@ -795,7 +761,7 @@ nsPNGDecoder::row_callback(png_structp png_ptr, png_bytep new_row, } break; default: - longjmp(png_jmpbuf(decoder->mPNG), 1); + png_longjmp(decoder->mPNG, 1); } if (!rowHasNoAlpha) @@ -835,9 +801,8 @@ nsPNGDecoder::frame_info_callback(png_structp png_ptr, png_uint_32 frame_num) decoder->CreateFrame(x_offset, y_offset, width, height, decoder->format); if (decoder->NeedsNewFrame()) { - /* We know that we need a new frame, so pause input so the decoder - * infrastructure can give it to us. - */ + // We know that we need a new frame, so pause input so the decoder + // infrastructure can give it to us. png_process_data_pause(png_ptr, /* save = */ 1); } } @@ -882,7 +847,7 @@ void nsPNGDecoder::error_callback(png_structp png_ptr, png_const_charp error_msg) { PR_LOG(GetPNGLog(), PR_LOG_ERROR, ("libpng error: %s\n", error_msg)); - longjmp(png_jmpbuf(png_ptr), 1); + png_longjmp(png_ptr, 1); } diff --git a/image/decoders/nsPNGDecoder.h b/image/decoders/nsPNGDecoder.h index ca7a227447a..acf2781e2f2 100644 --- a/image/decoders/nsPNGDecoder.h +++ b/image/decoders/nsPNGDecoder.h @@ -4,8 +4,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef nsPNGDecoder_h__ -#define nsPNGDecoder_h__ +#ifndef nsPNGDecoder_h +#define nsPNGDecoder_h #include "Decoder.h" @@ -133,4 +133,4 @@ public: } // namespace image } // namespace mozilla -#endif // nsPNGDecoder_h__ +#endif // nsPNGDecoder_h diff --git a/image/encoders/png/nsPNGEncoder.cpp b/image/encoders/png/nsPNGEncoder.cpp index 156db9b961a..47e11914fb2 100644 --- a/image/encoders/png/nsPNGEncoder.cpp +++ b/image/encoders/png/nsPNGEncoder.cpp @@ -3,15 +3,28 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "ImageLogging.h" #include "nsCRT.h" #include "nsPNGEncoder.h" -#include "prprf.h" -#include "nsString.h" #include "nsStreamUtils.h" +#include "nsString.h" +#include "prprf.h" using namespace mozilla; -NS_IMPL_ISUPPORTS(nsPNGEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream) +#ifdef PR_LOGGING +static PRLogModuleInfo * +GetPNGEncoderLog() +{ + static PRLogModuleInfo *sPNGEncoderLog; + if (!sPNGEncoderLog) + sPNGEncoderLog = PR_NewLogModule("PNGEncoder"); + return sPNGEncoderLog; +} +#endif + +NS_IMPL_ISUPPORTS(nsPNGEncoder, imgIEncoder, nsIInputStream, + nsIAsyncInputStream) nsPNGEncoder::nsPNGEncoder() : mPNG(nullptr), mPNGinfo(nullptr), mIsAnimation(false), @@ -20,7 +33,8 @@ nsPNGEncoder::nsPNGEncoder() : mPNG(nullptr), mPNGinfo(nullptr), mImageBufferUsed(0), mImageBufferReadPoint(0), mCallback(nullptr), mCallbackTarget(nullptr), mNotifyThreshold(0), - mReentrantMonitor("nsPNGEncoder.mReentrantMonitor") + mReentrantMonitor( + "nsPNGEncoder.mReentrantMonitor") { } @@ -72,7 +86,7 @@ NS_IMETHODIMP nsPNGEncoder::InitFromData(const uint8_t* aData, // nsPNGEncoder::StartImageEncode // -// +// // See ::InitFromData for other info. NS_IMETHODIMP nsPNGEncoder::StartImageEncode(uint32_t aWidth, uint32_t aHeight, @@ -241,7 +255,7 @@ NS_IMETHODIMP nsPNGEncoder::AddImageFrame(const uint8_t* aData, } #endif - // Stride is the padded width of each row, so it better be longer + // Stride is the padded width of each row, so it better be longer // (I'm afraid people will not understand what stride means, so // check it well) if ((aInputFormat == INPUT_FORMAT_RGB && @@ -567,7 +581,8 @@ NS_IMETHODIMP nsPNGEncoder::AsyncWait(nsIInputStreamCallback *aCallback, // We set the callback absolutely last, because NotifyListener uses it to // determine if someone needs to be notified. If we don't set it last, // NotifyListener might try to fire off a notification to a null target - // which will generally cause non-threadsafe objects to be used off the main thread + // which will generally cause non-threadsafe objects to be used off the main + // thread mCallback = aCallback; // What we are being asked for may be present already @@ -631,37 +646,25 @@ nsPNGEncoder::StripAlpha(const uint8_t* aSrc, uint8_t* aDest, // nsPNGEncoder::WarningCallback -void // static +void nsPNGEncoder::WarningCallback(png_structp png_ptr, png_const_charp warning_msg) { -#ifdef DEBUG - // XXX: these messages are probably useful callers... - // use nsIConsoleService? - PR_fprintf(PR_STDERR, "PNG Encoder: %s\n", warning_msg);; -#endif + PR_LOG(GetPNGEncoderLog(), PR_LOG_WARNING, + ("libpng warning: %s\n", warning_msg)); } // nsPNGEncoder::ErrorCallback -void // static +void nsPNGEncoder::ErrorCallback(png_structp png_ptr, png_const_charp error_msg) { -#ifdef DEBUG - // XXX: these messages are probably useful callers... - // use nsIConsoleService? - PR_fprintf(PR_STDERR, "PNG Encoder: %s\n", error_msg);; -#endif -#if PNG_LIBPNG_VER < 10500 - longjmp(png_ptr->jmpbuf, 1); -#else - png_longjmp(png_ptr, 1); -#endif + PR_LOG(GetPNGEncoderLog(), PR_LOG_ERROR, ("libpng error: %s\n", error_msg)); + png_longjmp(png_ptr, 1); } - // nsPNGEncoder::WriteCallback void // static diff --git a/image/encoders/png/nsPNGEncoder.h b/image/encoders/png/nsPNGEncoder.h index 17f39cdad37..c70c9b8a2f8 100644 --- a/image/encoders/png/nsPNGEncoder.h +++ b/image/encoders/png/nsPNGEncoder.h @@ -3,15 +3,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "mozilla/Attributes.h" -#include "mozilla/ReentrantMonitor.h" - -#include "imgIEncoder.h" - -#include "nsCOMPtr.h" +#ifndef nsPNGEncoder_h #include +#include "imgIEncoder.h" +#include "nsCOMPtr.h" + +#include "mozilla/Attributes.h" +#include "mozilla/ReentrantMonitor.h" + #define NS_PNGENCODER_CID \ { /* 38d1592e-b81e-432b-86f8-471878bbfe07 */ \ 0x38d1592e, \ @@ -72,11 +73,11 @@ protected: nsCOMPtr mCallbackTarget; uint32_t mNotifyThreshold; - /* - nsPNGEncoder is designed to allow one thread to pump data into it while another - reads from it. We lock to ensure that the buffer remains append-only while - we read from it (that it is not realloced) and to ensure that only one thread - dispatches a callback for each call to AsyncWait. - */ + // nsPNGEncoder is designed to allow one thread to pump data into it while + // another reads from it. We lock to ensure that the buffer remains + // append-only while we read from it (that it is not realloced) and to + // ensure that only one thread dispatches a callback for each call to + // AsyncWait. ReentrantMonitor mReentrantMonitor; }; +#endif // nsPNGEncoder_h