From: Robert Roebling Date: Wed, 16 Jun 1999 08:18:14 +0000 (+0000) Subject: Forgot this one. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/e65ed37acbf64415b66ce91ddae2ad23e93aab78 Forgot this one. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2804 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/src/common/imagbmp.cpp b/src/common/imagbmp.cpp new file mode 100644 index 0000000000..05796710b4 --- /dev/null +++ b/src/common/imagbmp.cpp @@ -0,0 +1,404 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: imagbmp.cpp +// Purpose: wxImage BMP handler +// Author: Robert Roebling +// RCS-ID: $Id$ +// Copyright: (c) Robert Roebling +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +/* + We don't put pragma implement in this file because it is already present in + src/common/image.cpp +*/ + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#include "wx/image.h" +#include "wx/bitmap.h" +#include "wx/debug.h" +#include "wx/log.h" +#include "wx/app.h" +#include "wx/filefn.h" +#include "wx/wfstream.h" +#include "wx/intl.h" +#include "wx/module.h" + +// For memcpy +#include + +#ifdef __SALFORDC__ +#ifdef FAR +#undef FAR +#endif +#endif + +#ifdef __WXMSW__ +#include +#endif + +//----------------------------------------------------------------------------- +// wxBMPHandler +//----------------------------------------------------------------------------- + +#if !USE_SHARED_LIBRARIES +IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler,wxImageHandler) +#endif + +#if wxUSE_STREAMS + +#ifndef BI_RGB +#define BI_RGB 0 +#define BI_RLE8 1 +#define BI_RLE4 2 +#endif + +#ifndef BI_BITFIELDS +#define BI_BITFIELDS 3 +#endif + +#define poffset (line * width * 3 + column * 3) + +bool wxBMPHandler::LoadFile( wxImage *image, wxInputStream& stream ) +{ + int rshift = 0, gshift = 0, bshift = 0; + wxUint8 aByte; + wxUint16 aWord; + wxInt32 dbuf[4], aDword, + rmask = 0, gmask = 0, bmask = 0; + wxInt8 bbuf[4]; + struct _cmap { + unsigned char r, g, b; + } *cmap = NULL; + + off_t start_offset = stream.TellI(); + + image->Destroy(); + + /* + * Read the BMP header + */ + + stream.Read( &bbuf, 2 ); + stream.Read( dbuf, 4 * 4 ); + + wxInt32 size = wxINT32_SWAP_ON_BE( dbuf[0] ); + wxInt32 offset = wxINT32_SWAP_ON_BE( dbuf[2] ); + + stream.Read(dbuf, 4 * 2); + int width = (int)wxINT32_SWAP_ON_BE( dbuf[0] ); + int height = (int)wxINT32_SWAP_ON_BE( dbuf[1] ); + if (width > 32767) + { + wxLogError( _T("Image width > 32767 pixels for file.") ); + return FALSE; + } + if (height > 32767) + { + wxLogError( _T("Image height > 32767 pixels for file.") ); + return FALSE; + } + + stream.Read( &aWord, 2 ); +/* + TODO + int planes = (int)wxUINT16_SWAP_ON_BE( aWord ); +*/ + stream.Read( &aWord, 2 ); + int bpp = (int)wxUINT16_SWAP_ON_BE( aWord ); + if (bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32) + { + wxLogError( _T("unknown bitdepth in file.") ); + return FALSE; + } + + stream.Read( dbuf, 4 * 4 ); + int comp = (int)wxINT32_SWAP_ON_BE( dbuf[0] ); + if (comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 && comp != BI_BITFIELDS) + { + wxLogError( _T("unknown encoding in Windows BMP file.") ); + return FALSE; + } + + stream.Read( dbuf, 4 * 2 ); + int ncolors = (int)wxINT32_SWAP_ON_BE( dbuf[0] ); + if (ncolors == 0) + ncolors = 1 << bpp; + /* some more sanity checks */ + if (((comp == BI_RLE4) && (bpp != 4)) || + ((comp == BI_RLE8) && (bpp != 8)) || + ((comp == BI_BITFIELDS) && (bpp != 16 && bpp != 32))) + { + wxLogError( _T("encoding of BMP doesn't match bitdepth.") ); + return FALSE; + } + if (bpp < 16) + { + cmap = (struct _cmap *)malloc(sizeof(struct _cmap) * ncolors); + if (!cmap) + { + wxLogError( _T("Cannot allocate RAM for color map in BMP file.") ); + return FALSE; + } + } + else + cmap = NULL; + + image->Create( width, height ); + unsigned char *ptr = image->GetData(); + if (!ptr) + { + wxLogError( _T("Cannot allocate RAM for RGB data in file.") ); + if (cmap) + free(cmap); + return FALSE; + } + + /* + * Reading the palette, if it exists. + */ + if (bpp < 16 && ncolors != 0) + { + for (int j = 0; j < ncolors; j++) + { + stream.Read( bbuf, 4 ); + cmap[j].b = bbuf[0]; + cmap[j].g = bbuf[1]; + cmap[j].r = bbuf[2]; + } + } + else if (bpp == 16 || bpp == 32) + { + if (comp == BI_BITFIELDS) + { + int bit = 0; + stream.Read( dbuf, 4 * 3 ); + bmask = wxINT32_SWAP_ON_BE( dbuf[0] ); + gmask = wxINT32_SWAP_ON_BE( dbuf[1] ); + rmask = wxINT32_SWAP_ON_BE( dbuf[2] ); + /* find shift amount.. ugly, but i can't think of a better way */ + for (bit = 0; bit < bpp; bit++) + { + if (bmask & (1 << bit)) + bshift = bit; + if (gmask & (1 << bit)) + gshift = bit; + if (rmask & (1 << bit)) + rshift = bit; + } + } + else if (bpp == 16) + { + rmask = 0x7C00; + gmask = 0x03E0; + bmask = 0x001F; + rshift = 10; + gshift = 5; + bshift = 0; + } + else if (bpp == 32) + { + rmask = 0x00FF0000; + gmask = 0x0000FF00; + bmask = 0x000000FF; + rshift = 16; + gshift = 8; + bshift = 0; + } + } + + /* + * Reading the image data + */ + stream.SeekI( start_offset + offset ); + unsigned char *data = ptr; + + /* set the whole image to the background color */ + if (bpp < 16 && (comp == BI_RLE4 || comp == BI_RLE8)) + { + for (int i = 0; i < width * height; i++) + { + *ptr++ = cmap[0].r; + *ptr++ = cmap[0].g; + *ptr++ = cmap[0].b; + } + ptr = data; + } + + int line = 0; + int column = 0; + int linesize = ((width * bpp + 31) / 32) * 4; + + /* BMPs are stored upside down */ + for (line = (height - 1); line >= 0; line--) + { + int linepos = 0; + for (column = 0; column < width;) + { + if (bpp < 16) + { + int index = 0; + linepos++; + aByte = stream.GetC(); + if (bpp == 1) + { + int bit = 0; + for (bit = 0; bit < 8; bit++) + { + index = ((aByte & (0x80 >> bit)) ? 1 : 0); + ptr[poffset] = cmap[index].r; + ptr[poffset + 1] = cmap[index].g; + ptr[poffset + 2] = cmap[index].b; + column++; + } + } + else if (bpp == 4) + { + if (comp == BI_RLE4) + { + wxLogError( _T("Can't deal with 4bit encoded yet.") ); + image->Destroy(); + free(cmap); + return FALSE; + } + else + { + int nibble = 0; + for (nibble = 0; nibble < 2; nibble++) + { + index = ((aByte & (0xF0 >> nibble * 4)) >> (!nibble * 4)); + if (index >= 16) + index = 15; + ptr[poffset] = cmap[index].r; + ptr[poffset + 1] = cmap[index].g; + ptr[poffset + 2] = cmap[index].b; + column++; + } + } + } + else if (bpp == 8) + { + if (comp == BI_RLE8) + { + unsigned char first; + first = aByte; + aByte = stream.GetC(); + if (first == 0) + { + if (aByte == 0) + { + /* column = width; */ + } + else if (aByte == 1) + { + column = width; + line = -1; + } + else if (aByte == 2) + { + aByte = stream.GetC(); + column += aByte; + linepos = column * bpp / 8; + aByte = stream.GetC(); + line += aByte; + } + else + { + int absolute = aByte; + for (int k = 0; k < absolute; k++) + { + linepos++; + aByte = stream.GetC(); + ptr[poffset ] = cmap[aByte].r; + ptr[poffset + 1] = cmap[aByte].g; + ptr[poffset + 2] = cmap[aByte].b; + column++; + } + if (absolute & 0x01) + aByte = stream.GetC(); + } + } + else + { + for (int l = 0; l < first; l++) + { + ptr[poffset ] = cmap[aByte].r; + ptr[poffset + 1] = cmap[aByte].g; + ptr[poffset + 2] = cmap[aByte].b; + column++; + linepos++; + } + } + } + else + { + ptr[poffset ] = cmap[aByte].r; + ptr[poffset + 1] = cmap[aByte].g; + ptr[poffset + 2] = cmap[aByte].b; + column++; + linepos += size; + } + } + } + else if (bpp == 24) + { + stream.Read( &bbuf, 3 ); + linepos += 3; + ptr[poffset ] = (unsigned char)bbuf[2]; + ptr[poffset + 1] = (unsigned char)bbuf[1]; + ptr[poffset + 2] = (unsigned char)bbuf[0]; + column++; + } + else if (bpp == 16) + { + unsigned char temp; + stream.Read( &aWord, 2 ); + aWord = wxUINT16_SWAP_ON_BE( aWord ); + linepos += 2; + temp = (aWord & rmask) >> rshift; + ptr[poffset] = temp; + temp = (aWord & gmask) >> gshift; + ptr[poffset + 1] = temp; + temp = (aWord & bmask) >> gshift; + ptr[poffset + 2] = temp; + column++; + } + else + { + unsigned char temp; + stream.Read( &aDword, 4 ); + aDword = wxINT32_SWAP_ON_BE( aDword ); + linepos += 4; + temp = (aDword & rmask) >> rshift; + ptr[poffset] = temp; + temp = (aDword & gmask) >> gshift; + ptr[poffset + 1] = temp; + temp = (aDword & bmask) >> bshift; + ptr[poffset + 2] = temp; + column++; + } + } + while ((linepos < linesize) && (comp != 1) && (comp != 2)) + { + stream.Read( &aByte, 1 ); + linepos += 1; + if (stream.LastError() != wxStream_NOERROR) + break; + } + } + if (cmap) + free(cmap); + + image->SetMask( FALSE ); + + return TRUE; +} + +#endif // wxUSE_STREAMS + +