diff options
author | aavit <qt-info@nokia.com> | 2010-11-30 14:31:09 (GMT) |
---|---|---|
committer | aavit <qt-info@nokia.com> | 2010-12-01 08:18:20 (GMT) |
commit | de30288bb108d70cd66774c3beb7497efb5d0e6d (patch) | |
tree | 4e1664ee44f01bab25c0550d29a992fe68a56e9e | |
parent | a01bd14b63a784d1924133aeb965435e48a93461 (diff) | |
download | Qt-de30288bb108d70cd66774c3beb7497efb5d0e6d.zip Qt-de30288bb108d70cd66774c3beb7497efb5d0e6d.tar.gz Qt-de30288bb108d70cd66774c3beb7497efb5d0e6d.tar.bz2 |
Workaround for certain malformed PNGs that lack the final crc bytes
Task-number: QT-4103
Reviewed-by: gunnar
-rw-r--r-- | src/gui/image/qpnghandler.cpp | 80 |
1 files changed, 46 insertions, 34 deletions
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 935aba0..a4d669b 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -82,6 +82,41 @@ QT_BEGIN_NAMESPACE Never to grayscale. */ +class QPngHandlerPrivate +{ +public: + enum State { + Ready, + ReadHeader, + ReadingEnd, + Error + }; + + QPngHandlerPrivate(QPngHandler *qq) + : gamma(0.0), quality(2), png_ptr(0), info_ptr(0), + end_info(0), row_pointers(0), state(Ready), q(qq) + { } + + float gamma; + int quality; + QString description; + + png_struct *png_ptr; + png_info *info_ptr; + png_info *end_info; + png_byte **row_pointers; + + bool readPngHeader(); + bool readPngImage(QImage *image); + + QImage::Format readImageFormat(); + + State state; + + QPngHandler *q; +}; + + #if defined(Q_C_CALLBACKS) extern "C" { #endif @@ -118,7 +153,15 @@ private: static void CALLBACK_CALL_TYPE iod_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) { - QIODevice *in = (QIODevice *)png_get_io_ptr(png_ptr); + QPngHandlerPrivate *d = (QPngHandlerPrivate *)png_get_io_ptr(png_ptr); + QIODevice *in = d->q->device(); + + if (d->state == QPngHandlerPrivate::ReadingEnd && in->atEnd() && length == 4) { + // Workaround for certain malformed PNGs that lack the final crc bytes + uchar endcrc[4] = { 0xae, 0x42, 0x60, 0x82 }; + qMemCopy(data, endcrc, 4); + return; + } while (length) { int nr = in->read((char*)data, length); @@ -314,38 +357,6 @@ static void CALLBACK_CALL_TYPE qt_png_warning(png_structp /*png_ptr*/, png_const } #endif -class QPngHandlerPrivate -{ -public: - enum State { - Ready, - ReadHeader, - Error - }; - - QPngHandlerPrivate(QPngHandler *qq) - : gamma(0.0), quality(2), png_ptr(0), info_ptr(0), - end_info(0), row_pointers(0), state(Ready), q(qq) - { } - - float gamma; - int quality; - QString description; - - png_struct *png_ptr; - png_info *info_ptr; - png_info *end_info; - png_byte **row_pointers; - - bool readPngHeader(); - bool readPngImage(QImage *image); - - QImage::Format readImageFormat(); - - State state; - - QPngHandler *q; -}; /*! \internal @@ -379,7 +390,7 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngHeader() return false; } - png_set_read_fn(png_ptr, q->device(), iod_read_fn); + png_set_read_fn(png_ptr, this, iod_read_fn); png_read_info(png_ptr, info_ptr); #ifndef QT_NO_IMAGE_TEXT @@ -505,6 +516,7 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage) } #endif + state = ReadingEnd; png_read_end(png_ptr, end_info); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete [] row_pointers; |