From 184b9b49d315290ed817652b30b277da1bb0784e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 12 Mar 2014 23:04:09 +0000 Subject: [PATCH] Add support for loading icons in PNG format to wxImage. ICO files can contain data in PNG, as well as BMP, format in recent (i.e. from this millennium) versions of Windows, so check for this case in wxICOHandler and load such data using wxPNGHandler. See #15918. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@76131 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/common/imagbmp.cpp | 47 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/src/common/imagbmp.cpp b/src/common/imagbmp.cpp index 0f2d7193db..96f8f7c7ec 100644 --- a/src/common/imagbmp.cpp +++ b/src/common/imagbmp.cpp @@ -1479,7 +1479,52 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream, if (offset != 0 && stream.SeekI(offset, wxFromCurrent) == wxInvalidOffset) return false; - bResult = LoadDib(image, stream, verbose, false /* not BMP */); +#if wxUSE_LIBPNG + // We can't fall back to loading an icon in the usual BMP format after + // trying to load it as PNG if we have an unseekable stream, so to + // avoid breaking the existing code which does successfully load icons + // from such streams, we only try to load them as PNGs if we can unwind + // back later. + // + // Ideal would be to modify LoadDib() to accept the first 8 bytes not + // coming from the stream but from the signature buffer below, as then + // we'd be able to load PNG icons from any kind of streams. + bool isPNG; + if ( stream.IsSeekable() ) + { + // Check for the PNG signature first to avoid wasting time on + // trying to load typical ICO files which are not PNGs at all. + static const unsigned char signaturePNG[] = + { + 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A + }; + static const int signatureLen = WXSIZEOF(signaturePNG); + + unsigned char signature[signatureLen]; + if ( !stream.ReadAll(signature, signatureLen) ) + return false; + + isPNG = memcmp(signature, signaturePNG, signatureLen) == 0; + + // Rewind to the beginning of the image in any case. + if ( stream.SeekI(-signatureLen, wxFromCurrent) == wxInvalidOffset ) + return false; + } + else // Not seekable stream + { + isPNG = false; + } + + if ( isPNG ) + { + wxPNGHandler handlerPNG; + bResult = handlerPNG.LoadFile(image, stream, verbose); + } + else +#endif // wxUSE_LIBPNG + { + bResult = LoadDib(image, stream, verbose, false /* not BMP */); + } bool bIsCursorType = (this->GetType() == wxBITMAP_TYPE_CUR) || (this->GetType() == wxBITMAP_TYPE_ANI); if ( bResult && bIsCursorType && nType == 2 ) {