X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b4c470164c9e273222715eed7edb0d1334efc5f2..bf2c43c76e2819be443ab1d830ab68d9569d66b1:/src/common/imagbmp.cpp diff --git a/src/common/imagbmp.cpp b/src/common/imagbmp.cpp index bc6f47c858..c3fcfb275e 100644 --- a/src/common/imagbmp.cpp +++ b/src/common/imagbmp.cpp @@ -2,7 +2,6 @@ // Name: src/common/imagbmp.cpp // Purpose: wxImage BMP,ICO and CUR handlers // Author: Robert Roebling, Chris Elliott -// RCS-ID: $Id$ // Copyright: (c) Robert Roebling, Chris Elliott // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -91,7 +90,7 @@ bool wxBMPHandler::SaveDib(wxImage *image, { wxCHECK_MSG( image, false, wxT("invalid pointer in wxBMPHandler::SaveFile") ); - if ( !image->Ok() ) + if ( !image->IsOk() ) { if ( verbose ) { @@ -146,8 +145,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 { @@ -229,10 +228,10 @@ bool wxBMPHandler::SaveDib(wxImage *image, if (// VS: looks ugly but compilers tend to do ugly things with structs, // like aligning hdr.filesize's ofset to dword :( // VZ: we should add padding then... - !stream.Write(&hdr.magic, 2) || - !stream.Write(&hdr.filesize, 4) || - !stream.Write(&hdr.reserved, 4) || - !stream.Write(&hdr.data_offset, 4) + !stream.WriteAll(&hdr.magic, 2) || + !stream.WriteAll(&hdr.filesize, 4) || + !stream.WriteAll(&hdr.reserved, 4) || + !stream.WriteAll(&hdr.data_offset, 4) ) { if (verbose) @@ -245,17 +244,17 @@ bool wxBMPHandler::SaveDib(wxImage *image, if ( !IsMask ) { if ( - !stream.Write(&hdr.bih_size, 4) || - !stream.Write(&hdr.width, 4) || - !stream.Write(&hdr.height, 4) || - !stream.Write(&hdr.planes, 2) || - !stream.Write(&hdr.bpp, 2) || - !stream.Write(&hdr.compression, 4) || - !stream.Write(&hdr.size_of_bmp, 4) || - !stream.Write(&hdr.h_res, 4) || - !stream.Write(&hdr.v_res, 4) || - !stream.Write(&hdr.num_clrs, 4) || - !stream.Write(&hdr.num_signif_clrs, 4) + !stream.WriteAll(&hdr.bih_size, 4) || + !stream.WriteAll(&hdr.width, 4) || + !stream.WriteAll(&hdr.height, 4) || + !stream.WriteAll(&hdr.planes, 2) || + !stream.WriteAll(&hdr.bpp, 2) || + !stream.WriteAll(&hdr.compression, 4) || + !stream.WriteAll(&hdr.size_of_bmp, 4) || + !stream.WriteAll(&hdr.h_res, 4) || + !stream.WriteAll(&hdr.v_res, 4) || + !stream.WriteAll(&hdr.num_clrs, 4) || + !stream.WriteAll(&hdr.num_signif_clrs, 4) ) { if (verbose) @@ -332,7 +331,7 @@ bool wxBMPHandler::SaveDib(wxImage *image, { if ( !IsMask ) { - if ( !stream.Write(rgbquad, palette_size*4) ) + if ( !stream.WriteAll(rgbquad, palette_size*4) ) { if (verbose) { @@ -351,7 +350,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); @@ -467,7 +466,7 @@ bool wxBMPHandler::SaveDib(wxImage *image, } } - if ( !stream.Write(buffer, row_width) ) + if ( !stream.WriteAll(buffer, row_width) ) { if (verbose) { @@ -533,6 +532,14 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, wxON_BLOCK_EXIT1(&BMPPalette::Free, cmap); + bool isUpsideDown = true; + + if (height < 0) + { + isUpsideDown = false; + height = -height; + } + // destroy existing here instead of: image->Destroy(); image->Create(width, height); @@ -578,7 +585,9 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, { if (hasPalette) { - stream.Read(bbuf, 4); + if ( !stream.ReadAll(bbuf, 4) ) + return false; + cmap[j].b = bbuf[0]; cmap[j].g = bbuf[1]; cmap[j].r = bbuf[2]; @@ -610,7 +619,9 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, if ( comp == BI_BITFIELDS ) { int bit; - stream.Read(dbuf, 4 * 3); + if ( !stream.ReadAll(dbuf, 4 * 3) ) + return false; + rmask = wxINT32_SWAP_ON_BE(dbuf[0]); gmask = wxINT32_SWAP_ON_BE(dbuf[1]); bmask = wxINT32_SWAP_ON_BE(dbuf[2]); @@ -672,9 +683,10 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, // NOTE: seeking a positive amount in wxFromCurrent mode allows us to // load even non-seekable streams (see wxInputStream::SeekI docs)! const wxFileOffset pos = stream.TellI(); - if (pos != wxInvalidOffset && bmpOffset > pos) - if (stream.SeekI(bmpOffset - pos, wxFromCurrent) == wxInvalidOffset) - return false; + if ( pos == wxInvalidOffset || + (bmpOffset > pos && + stream.SeekI(bmpOffset - pos, wxFromCurrent) == wxInvalidOffset) ) + return false; //else: icon, just carry on } @@ -702,9 +714,10 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, // this case (see #10915) bool hasValidAlpha = false; - /* BMPs are stored upside down */ - for ( int line = (height - 1); line >= 0; line-- ) + for ( int row = 0; row < height; row++ ) { + int line = isUpsideDown ? height - 1 - row : row; + int linepos = 0; for ( int column = 0; column < width ; ) { @@ -712,6 +725,9 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, { linepos++; aByte = stream.GetC(); + if ( !stream.IsOk() ) + return false; + if ( bpp == 1 ) { for (int bit = 0; bit < 8 && column < width; bit++) @@ -730,25 +746,35 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, wxUint8 first; first = aByte; aByte = stream.GetC(); + if ( !stream.IsOk() ) + return false; + if ( first == 0 ) { if ( aByte == 0 ) { - if ( column > 0 ) - column = width; + // end of scanline marker + column = width; + row--; } else if ( aByte == 1 ) { + // end of RLE data marker, stop decoding column = width; - line = -1; + row = height; } else if ( aByte == 2 ) { + // delta marker, move in image aByte = stream.GetC(); + if ( !stream.IsOk() ) + return false; column += aByte; linepos = column * bpp / 4; aByte = stream.GetC(); - line -= aByte; // upside down + if ( !stream.IsOk() ) + return false; + row += aByte; // upside down } else { @@ -761,6 +787,8 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, { ++readBytes ; aByte = stream.GetC(); + if ( !stream.IsOk() ) + return false; nibble[0] = (wxUint8)( (aByte & 0xF0) >> 4 ) ; nibble[1] = (wxUint8)( aByte & 0x0F ) ; } @@ -772,7 +800,11 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, linepos++; } if ( readBytes & 0x01 ) + { aByte = stream.GetC(); + if ( !stream.IsOk() ) + return false; + } } } else @@ -813,24 +845,35 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, unsigned char first; first = aByte; aByte = stream.GetC(); + if ( !stream.IsOk() ) + return false; + if ( first == 0 ) { if ( aByte == 0 ) { - /* column = width; */ + // end of scanline marker + column = width; + row--; } else if ( aByte == 1 ) { + // end of RLE data marker, stop decoding column = width; - line = -1; + row = height; } else if ( aByte == 2 ) { + // delta marker, move in image aByte = stream.GetC(); + if ( !stream.IsOk() ) + return false; column += aByte; linepos = column * bpp / 8; aByte = stream.GetC(); - line += aByte; + if ( !stream.IsOk() ) + return false; + row -= aByte; } else { @@ -839,13 +882,19 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, { linepos++; aByte = stream.GetC(); + if ( !stream.IsOk() ) + return false; ptr[poffset ] = cmap[aByte].r; ptr[poffset + 1] = cmap[aByte].g; ptr[poffset + 2] = cmap[aByte].b; column++; } if ( absolute & 0x01 ) + { aByte = stream.GetC(); + if ( !stream.IsOk() ) + return false; + } } } else @@ -872,7 +921,8 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, } else if ( bpp == 24 ) { - stream.Read(bbuf, 3); + if ( !stream.ReadAll(bbuf, 3) ) + return false; linepos += 3; ptr[poffset ] = (unsigned char)bbuf[2]; ptr[poffset + 1] = (unsigned char)bbuf[1]; @@ -882,7 +932,8 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, else if ( bpp == 16 ) { unsigned char temp; - stream.Read(&aWord, 2); + if ( !stream.ReadAll(&aWord, 2) ) + return false; aWord = wxUINT16_SWAP_ON_BE(aWord); linepos += 2; /* Use the masks and calculated amount of shift @@ -900,7 +951,9 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, else { unsigned char temp; - stream.Read(&aDword, 4); + if ( !stream.ReadAll(&aDword, 4) ) + return false; + aDword = wxINT32_SWAP_ON_BE(aDword); linepos += 4; temp = (unsigned char)((aDword & rmask) >> rshift); @@ -922,9 +975,8 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, } while ( (linepos < linesize) && (comp != 1) && (comp != 2) ) { - stream.Read(&aByte, 1); - linepos += 1; - if ( !stream ) + ++linepos; + if ( !stream.ReadAll(&aByte, 1) ) break; } } @@ -952,19 +1004,23 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream, if ( IsBmp ) { // read the header off the .BMP format file - stream.Read(bbuf, 2); - stream.Read(dbuf, 16); + if ( !stream.ReadAll(bbuf, 2) || + !stream.ReadAll(dbuf, 16) ) + return false; } else { - stream.Read(dbuf, 4); + if ( !stream.ReadAll(dbuf, 4) ) + return false; } #if 0 // unused wxInt32 size = wxINT32_SWAP_ON_BE(dbuf[0]); #endif wxFileOffset offset = wxINT32_SWAP_ON_BE(dbuf[2]); - stream.Read(dbuf, 4 * 2); + if ( !stream.ReadAll(dbuf, 4 * 2) ) + return false; + int width = wxINT32_SWAP_ON_BE((int)dbuf[0]); int height = wxINT32_SWAP_ON_BE((int)dbuf[1]); if ( !IsBmp)height = height / 2; // for icons divide by 2 @@ -986,12 +1042,16 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream, return false; } - stream.Read(&aWord, 2); + if ( !stream.ReadAll(&aWord, 2) ) + return false; + /* TODO int planes = (int)wxUINT16_SWAP_ON_BE( aWord ); */ - stream.Read(&aWord, 2); + if ( !stream.ReadAll(&aWord, 2) ) + return false; + int bpp = wxUINT16_SWAP_ON_BE((int)aWord); if ( bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32 ) { @@ -1002,7 +1062,9 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream, return false; } - stream.Read(dbuf, 4 * 4); + if ( !stream.ReadAll(dbuf, 4 * 4) ) + return false; + int comp = wxINT32_SWAP_ON_BE((int)dbuf[0]); if ( comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 && comp != BI_BITFIELDS ) @@ -1014,7 +1076,8 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream, return false; } - stream.Read(dbuf, 4 * 2); + if ( !stream.ReadAll(dbuf, 4 * 2) ) + return false; int ncolors = wxINT32_SWAP_ON_BE( (int)dbuf[0] ); if (ncolors == 0) @@ -1079,7 +1142,7 @@ bool wxBMPHandler::DoCanRead(wxInputStream& stream) { unsigned char hdr[2]; - if ( !stream.Read(hdr, WXSIZEOF(hdr)) ) // it's ok to modify the stream position here + if ( !stream.ReadAll(hdr, WXSIZEOF(hdr)) ) // it's ok to modify the stream position here return false; // do we have the BMP file signature? @@ -1161,10 +1224,9 @@ bool wxICOHandler::SaveFile(wxImage *image, IconDir.idReserved = 0; IconDir.idType = wxUINT16_SWAP_ON_BE((wxUint16)type); IconDir.idCount = wxUINT16_SWAP_ON_BE((wxUint16)images); - stream.Write(&IconDir.idReserved, sizeof(IconDir.idReserved)); - stream.Write(&IconDir.idType, sizeof(IconDir.idType)); - stream.Write(&IconDir.idCount, sizeof(IconDir.idCount)); - if ( !stream.IsOk() ) + if ( !stream.WriteAll(&IconDir.idReserved, sizeof(IconDir.idReserved)) || + !stream.WriteAll(&IconDir.idType, sizeof(IconDir.idType)) || + !stream.WriteAll(&IconDir.idCount, sizeof(IconDir.idCount)) ) { if ( verbose ) { @@ -1249,7 +1311,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 ) { @@ -1287,15 +1349,14 @@ bool wxICOHandler::SaveFile(wxImage *image, offset += Size; // write to stream: - stream.Write(&icondirentry.bWidth, sizeof(icondirentry.bWidth)); - stream.Write(&icondirentry.bHeight, sizeof(icondirentry.bHeight)); - stream.Write(&icondirentry.bColorCount, sizeof(icondirentry.bColorCount)); - stream.Write(&icondirentry.bReserved, sizeof(icondirentry.bReserved)); - stream.Write(&icondirentry.wPlanes, sizeof(icondirentry.wPlanes)); - stream.Write(&icondirentry.wBitCount, sizeof(icondirentry.wBitCount)); - stream.Write(&icondirentry.dwBytesInRes, sizeof(icondirentry.dwBytesInRes)); - stream.Write(&icondirentry.dwImageOffset, sizeof(icondirentry.dwImageOffset)); - if ( !stream.IsOk() ) + if ( !stream.WriteAll(&icondirentry.bWidth, sizeof(icondirentry.bWidth)) || + !stream.WriteAll(&icondirentry.bHeight, sizeof(icondirentry.bHeight)) || + !stream.WriteAll(&icondirentry.bColorCount, sizeof(icondirentry.bColorCount)) || + !stream.WriteAll(&icondirentry.bReserved, sizeof(icondirentry.bReserved)) || + !stream.WriteAll(&icondirentry.wPlanes, sizeof(icondirentry.wPlanes)) || + !stream.WriteAll(&icondirentry.wBitCount, sizeof(icondirentry.wBitCount)) || + !stream.WriteAll(&icondirentry.dwBytesInRes, sizeof(icondirentry.dwBytesInRes)) || + !stream.WriteAll(&icondirentry.dwImageOffset, sizeof(icondirentry.dwImageOffset)) ) { if ( verbose ) { @@ -1335,6 +1396,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); } @@ -1346,7 +1412,9 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream, ICONDIR IconDir; - stream.Read(&IconDir, sizeof(IconDir)); + if ( !stream.ReadAll(&IconDir, sizeof(IconDir)) ) + return false; + wxUint16 nIcons = wxUINT16_SWAP_ON_BE(IconDir.idCount); // nType is 1 for Icons, 2 for Cursors: @@ -1364,7 +1432,10 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream, for (unsigned int i = 0; i < nIcons; i++ ) { - alreadySeeked += stream.Read(pCurrentEntry, sizeof(ICONDIRENTRY)).LastRead(); + if ( !stream.ReadAll(pCurrentEntry, sizeof(ICONDIRENTRY)) ) + return false; + + alreadySeeked += stream.LastRead(); // bHeight and bColorCount are wxUint8 if ( pCurrentEntry->bWidth >= wMax ) @@ -1423,10 +1494,16 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream, 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 + if ( !stream.ReadAll(&IconDir, sizeof(IconDir)) ) return 0; return (int)wxUINT16_SWAP_ON_BE(IconDir.idCount); @@ -1492,8 +1569,15 @@ int wxANIHandler::DoGetImageCount(wxInputStream& stream) 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)) ) // it's ok to modify the stream position here + if ( !stream->ReadAll(&iconDir, sizeof(iconDir)) ) { return false; }