X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/72045d5768a126191a907bc640c28e81a11afdd6..12b5f4b4d2d8a07962da7ba3b78c8c1ec2634a67:/src/common/imagbmp.cpp diff --git a/src/common/imagbmp.cpp b/src/common/imagbmp.cpp index 5f45ba9207..6f3a298d18 100644 --- a/src/common/imagbmp.cpp +++ b/src/common/imagbmp.cpp @@ -27,22 +27,18 @@ #include "wx/bitmap.h" #include "wx/palette.h" #include "wx/intl.h" + #include "wx/math.h" #endif #include "wx/filefn.h" #include "wx/wfstream.h" #include "wx/quantize.h" +#include "wx/scopeguard.h" #include "wx/anidecod.h" // For memcpy #include -#ifdef __SALFORDC__ -#ifdef FAR -#undef FAR -#endif -#endif - //----------------------------------------------------------------------------- // wxBMPHandler //----------------------------------------------------------------------------- @@ -154,7 +150,7 @@ bool wxBMPHandler::SaveDib(wxImage *image, wxUint16 bpp; // bits per pixel wxUint32 compression; // compression method wxUint32 size_of_bmp; // size of the bitmap - wxUint32 h_res, v_res; // image resolution in dpi + wxUint32 h_res, v_res; // image resolution in pixels-per-meter wxUint32 num_clrs; // number of colors used wxUint32 num_signif_clrs;// number of significant colors } hdr; @@ -181,7 +177,36 @@ bool wxBMPHandler::SaveDib(wxImage *image, hdr.bpp = wxUINT16_SWAP_ON_BE(bpp); hdr.compression = 0; // RGB uncompressed hdr.size_of_bmp = wxUINT32_SWAP_ON_BE(row_width * image->GetHeight()); - hdr.h_res = hdr.v_res = wxUINT32_SWAP_ON_BE(72); // 72dpi is standard + + // get the resolution from the image options or fall back to 72dpi standard + // for the BMP format if not specified + int hres, vres; + switch ( GetResolutionFromOptions(*image, &hres, &vres) ) + { + default: + wxFAIL_MSG( _T("unexpected image resolution units") ); + // fall through + + case wxIMAGE_RESOLUTION_NONE: + hres = + vres = 72; + // fall through to convert it to correct units + + case wxIMAGE_RESOLUTION_INCHES: + // convert resolution in inches to resolution in centimeters + hres = (int)(10*mm2inches*hres); + vres = (int)(10*mm2inches*vres); + // fall through to convert it to resolution in meters + + case wxIMAGE_RESOLUTION_CM: + // convert resolution in centimeters to resolution in meters + hres *= 100; + vres *= 100; + break; + } + + hdr.h_res = wxUINT32_SWAP_ON_BE(hres); + hdr.v_res = wxUINT32_SWAP_ON_BE(vres); hdr.num_clrs = wxUINT32_SWAP_ON_BE(palette_size); // # colors in colormap hdr.num_signif_clrs = 0; // all colors are significant @@ -444,18 +469,20 @@ bool wxBMPHandler::SaveDib(wxImage *image, } -typedef struct +struct BMPPalette { + static void Free(BMPPalette* pal) { delete [] pal; } + unsigned char r, g, b; -} _cmap; +}; bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, int bpp, int ncolors, int comp, wxFileOffset bmpOffset, wxInputStream& stream, bool verbose, bool IsBmp, bool hasPalette) { - wxInt32 aDword, rmask = 0, gmask = 0, bmask = 0; - int rshift = 0, gshift = 0, bshift = 0; + wxInt32 aDword, rmask = 0, gmask = 0, bmask = 0, amask = 0; + int rshift = 0, gshift = 0, bshift = 0, ashift = 0; int rbits = 0, gbits = 0, bbits = 0; wxInt32 dbuf[4]; wxInt8 bbuf[4]; @@ -463,11 +490,11 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, wxUint16 aWord; // allocate space for palette if needed: - _cmap *cmap; + BMPPalette *cmap; if ( bpp < 16 ) { - cmap = new _cmap[ncolors]; + cmap = new BMPPalette[ncolors]; if ( !cmap ) { if (verbose) @@ -475,8 +502,12 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, return false; } } - else + else // no palette + { cmap = NULL; + } + + wxON_BLOCK_EXIT1(&BMPPalette::Free, cmap); // destroy existing here instead of: image->Destroy(); @@ -488,11 +519,27 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, { if ( verbose ) wxLogError( _("BMP: Couldn't allocate memory.") ); - if ( cmap ) - delete[] cmap; return false; } + unsigned char *alpha; + if ( bpp == 32 ) + { + // tell the image to allocate an alpha buffer + image->SetAlpha(); + alpha = image->GetAlpha(); + if ( !alpha ) + { + if ( verbose ) + wxLogError(_("BMP: Couldn't allocate memory.")); + return false; + } + } + else // no alpha + { + alpha = NULL; + } + // Reading the palette, if it exists: if ( bpp < 16 && ncolors != 0 ) { @@ -577,6 +624,9 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, rmask = 0x00FF0000; gmask = 0x0000FF00; bmask = 0x000000FF; + amask = 0xFF000000; + + ashift = 24; rshift = 16; gshift = 8; bshift = 0; @@ -590,7 +640,11 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, * Reading the image data */ if ( IsBmp ) - stream.SeekI(bmpOffset); // else icon, just carry on + { + if (stream.SeekI(bmpOffset) == wxInvalidOffset) + return false; + //else: icon, just carry on + } unsigned char *data = ptr; @@ -815,6 +869,11 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, ptr[poffset + 1] = temp; temp = (unsigned char)((aDword & bmask) >> bshift); ptr[poffset + 2] = temp; + if ( alpha ) + { + temp = (unsigned char)((aDword & amask) >> ashift); + alpha[line * width + column] = temp; + } column++; } } @@ -827,8 +886,6 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height, } } - delete[] cmap; - image->SetMask(false); const wxStreamError err = stream.GetLastError(); @@ -906,6 +963,7 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream, } stream.Read(dbuf, 4 * 2); + int ncolors = wxINT32_SWAP_ON_BE( (int)dbuf[0] ); if (ncolors == 0) ncolors = 1 << bpp; @@ -944,6 +1002,11 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream, } + // the resolution in the bitmap header is in meters, convert to centimeters + image->SetOption(wxIMAGE_OPTION_RESOLUTIONUNIT, wxIMAGE_RESOLUTION_CM); + image->SetOption(wxIMAGE_OPTION_RESOLUTIONX, dbuf[2]/100); + image->SetOption(wxIMAGE_OPTION_RESOLUTIONY, dbuf[3]/100); + return true; } @@ -1196,7 +1259,8 @@ bool wxICOHandler::SaveFile(wxImage *image, bool wxICOHandler::LoadFile(wxImage *image, wxInputStream& stream, bool verbose, int index) { - stream.SeekI(0); + if (stream.SeekI(0) == wxInvalidOffset) + return false; return DoLoadFile(image, stream, verbose, index); } @@ -1256,7 +1320,8 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream, { // seek to selected icon: pCurrentEntry = pIconDirEntry + iSel; - stream.SeekI(iPos + wxUINT32_SWAP_ON_BE(pCurrentEntry->dwImageOffset), wxFromStart); + if (stream.SeekI(iPos + wxUINT32_SWAP_ON_BE(pCurrentEntry->dwImageOffset), wxFromStart) == 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 ) @@ -1274,16 +1339,20 @@ int wxICOHandler::GetImageCount(wxInputStream& stream) { ICONDIR IconDir; wxFileOffset iPos = stream.TellI(); - stream.SeekI(0); - stream.Read(&IconDir, sizeof(IconDir)); + if (stream.SeekI(0) == wxInvalidOffset) + return 0; + if (stream.Read(&IconDir, sizeof(IconDir)).LastRead() != sizeof(IconDir)) + return 0; wxUint16 nIcons = wxUINT16_SWAP_ON_BE(IconDir.idCount); - stream.SeekI(iPos); + if (stream.SeekI(iPos) == wxInvalidOffset) + return 0; return (int)nIcons; } bool wxICOHandler::DoCanRead(wxInputStream& stream) { - stream.SeekI(0); + if (stream.SeekI(0) == wxInvalidOffset) + return false; unsigned char hdr[4]; if ( !stream.Read(hdr, WXSIZEOF(hdr)) ) return false; @@ -1305,7 +1374,8 @@ IMPLEMENT_DYNAMIC_CLASS(wxCURHandler, wxICOHandler) bool wxCURHandler::DoCanRead(wxInputStream& stream) { - stream.SeekI(0); + if (stream.SeekI(0) == wxInvalidOffset) + return false; unsigned char hdr[4]; if ( !stream.Read(hdr, WXSIZEOF(hdr)) ) return false;