X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/38e23f1020dcf6882d8e21b862d4755d8a76cf8a..f239a20092359e3c914adb79bd39f3f5d2b2e06f:/src/common/imagbmp.cpp diff --git a/src/common/imagbmp.cpp b/src/common/imagbmp.cpp index c50ddff713..631130805c 100644 --- a/src/common/imagbmp.cpp +++ b/src/common/imagbmp.cpp @@ -39,6 +39,16 @@ // For memcpy #include +// ---------------------------------------------------------------------------- +// private functions +// ---------------------------------------------------------------------------- + +#if wxUSE_ICO_CUR + +static bool CanReadICOOrCUR(wxInputStream *stream, wxUint16 resourceType); + +#endif // wxUSE_ICO_CUR + //----------------------------------------------------------------------------- // wxBMPHandler //----------------------------------------------------------------------------- @@ -81,7 +91,7 @@ bool wxBMPHandler::SaveDib(wxImage *image, { wxCHECK_MSG( image, false, wxT("invalid pointer in wxBMPHandler::SaveFile") ); - if ( !image->Ok() ) + if ( !image->IsOk() ) { if ( verbose ) { @@ -136,8 +146,8 @@ bool wxBMPHandler::SaveDib(wxImage *image, } unsigned width = image->GetWidth(); - unsigned row_padding = (4 - int(width*bpp/8.0) % 4) % 4; // # bytes to pad to dword - unsigned row_width = int(width * bpp/8.0) + row_padding; // # of bytes per row + unsigned row_padding = (4 - ((width * bpp + 7) / 8) % 4) % 4; // # bytes to pad to dword + unsigned row_width = (width * bpp + 7) / 8 + row_padding; // # of bytes per row struct { @@ -341,7 +351,7 @@ bool wxBMPHandler::SaveDib(wxImage *image, // pointer to the image data, use quantized if available wxUint8 *data = (wxUint8*) image->GetData(); - if (q_image) if (q_image->Ok()) data = (wxUint8*) q_image->GetData(); + if (q_image) if (q_image->IsOk()) data = (wxUint8*) q_image->GetData(); wxUint8 *buffer = new wxUint8[row_width]; memset(buffer, 0, row_width); @@ -684,6 +694,14 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, int linesize = ((width * bpp + 31) / 32) * 4; + // flag indicating if we have any not fully transparent alpha values: this + // is used to account for the bitmaps which use 32bpp format (normally + // meaning that they have alpha channel) but have only zeroes in it so that + // without this hack they appear fully transparent -- and as this is + // unlikely intentional, we consider that they don't have alpha at all in + // this case (see #10915) + bool hasValidAlpha = false; + /* BMPs are stored upside down */ for ( int line = (height - 1); line >= 0; line-- ) { @@ -895,6 +913,9 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, { temp = (unsigned char)((aDword & amask) >> ashift); alpha[line * width + column] = temp; + + if ( temp != wxALPHA_TRANSPARENT ) + hasValidAlpha = true; } column++; } @@ -910,6 +931,13 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, image->SetMask(false); + // check if we had any valid alpha values in this bitmap + if ( alpha && !hasValidAlpha ) + { + // we didn't, so finally discard the alpha channel completely + image->ClearAlpha(); + } + const wxStreamError err = stream.GetLastError(); return err == wxSTREAM_NO_ERROR || err == wxSTREAM_EOF; } @@ -1221,7 +1249,7 @@ bool wxICOHandler::SaveFile(wxImage *image, // wxCountingOutputStream::IsOk() always returns true for now and this // "if" provokes VC++ warnings in optimized build #if 0 - if ( !cStream.Ok() ) + if ( !cStream.IsOk() ) { if ( verbose ) { @@ -1307,6 +1335,11 @@ bool wxICOHandler::SaveFile(wxImage *image, bool wxICOHandler::LoadFile(wxImage *image, wxInputStream& stream, bool verbose, int index) { + if ( stream.IsSeekable() && stream.SeekI(0) == wxInvalidOffset ) + { + return false; + } + return DoLoadFile(image, stream, verbose, index); } @@ -1320,7 +1353,7 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream, stream.Read(&IconDir, sizeof(IconDir)); wxUint16 nIcons = wxUINT16_SWAP_ON_BE(IconDir.idCount); - + // nType is 1 for Icons, 2 for Cursors: wxUint16 nType = wxUINT16_SWAP_ON_BE(IconDir.idType); @@ -1333,11 +1366,11 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream, // remember how many bytes we read from the stream: wxFileOffset alreadySeeked = sizeof(IconDir); - + for (unsigned int i = 0; i < nIcons; i++ ) { alreadySeeked += stream.Read(pCurrentEntry, sizeof(ICONDIRENTRY)).LastRead(); - + // bHeight and bColorCount are wxUint8 if ( pCurrentEntry->bWidth >= wMax ) { @@ -1351,7 +1384,7 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream, colmax = pCurrentEntry->bColorCount; } } - + pCurrentEntry++; } @@ -1371,13 +1404,13 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream, { // seek to selected icon: pCurrentEntry = pIconDirEntry + iSel; - + // NOTE: seeking a positive amount in wxFromCurrent mode allows us to // load even non-seekable streams (see wxInputStream::SeekI docs)! wxFileOffset offset = wxUINT32_SWAP_ON_BE(pCurrentEntry->dwImageOffset) - alreadySeeked; if (offset != 0 && stream.SeekI(offset, wxFromCurrent) == wxInvalidOffset) return false; - + bResult = LoadDib(image, stream, true, IsBmp); bool bIsCursorType = (this->GetType() == wxBITMAP_TYPE_CUR) || (this->GetType() == wxBITMAP_TYPE_ANI); if ( bResult && bIsCursorType && nType == 2 ) @@ -1387,31 +1420,33 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream, image->SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, wxUINT16_SWAP_ON_BE(pCurrentEntry->wBitCount)); } } - + delete [] pIconDirEntry; - + return bResult; } int wxICOHandler::DoGetImageCount(wxInputStream& stream) { + // It's ok to modify the stream position in this function. + + if ( stream.IsSeekable() && stream.SeekI(0) == wxInvalidOffset ) + { + return 0; + } + ICONDIR IconDir; if (stream.Read(&IconDir, sizeof(IconDir)).LastRead() != sizeof(IconDir)) - // it's ok to modify the stream position here return 0; - + return (int)wxUINT16_SWAP_ON_BE(IconDir.idCount); } bool wxICOHandler::DoCanRead(wxInputStream& stream) { - unsigned char hdr[4]; - if ( !stream.Read(hdr, WXSIZEOF(hdr)) ) // it's ok to modify the stream position here - return false; + return CanReadICOOrCUR(&stream, 1 /*for identifying an icon*/); - // hdr[2] is one for an icon and two for a cursor - return hdr[0] == '\0' && hdr[1] == '\0' && hdr[2] == '\1' && hdr[3] == '\0'; } #endif // wxUSE_STREAMS @@ -1427,12 +1462,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxCURHandler, wxICOHandler) bool wxCURHandler::DoCanRead(wxInputStream& stream) { - unsigned char hdr[4]; - if ( !stream.Read(hdr, WXSIZEOF(hdr)) ) // it's ok to modify the stream position here - return false; - - // hdr[2] is one for an icon and two for a cursor - return hdr[0] == '\0' && hdr[1] == '\0' && hdr[2] == '\2' && hdr[3] == '\0'; + return CanReadICOOrCUR(&stream, 2 /*for identifying a cursor*/); } #endif // wxUSE_STREAMS @@ -1471,6 +1501,26 @@ int wxANIHandler::DoGetImageCount(wxInputStream& stream) return decoder.GetFrameCount(); } +static bool CanReadICOOrCUR(wxInputStream *stream, wxUint16 resourceType) +{ + // It's ok to modify the stream position in this function. + + if ( stream->IsSeekable() && stream->SeekI(0) == wxInvalidOffset ) + { + return false; + } + + ICONDIR iconDir; + if ( !stream->Read(&iconDir, sizeof(iconDir)) ) + { + return false; + } + + return !iconDir.idReserved // reserved, must be 0 + && wxUINT16_SWAP_ON_BE(iconDir.idType) == resourceType // either 1 or 2 + && iconDir.idCount; // must contain at least one image +} + #endif // wxUSE_STREAMS #endif // wxUSE_ICO_CUR