bitmapBmp.cpp

Engine/source/gfx/bitmap/loaders/bitmapBmp.cpp

More...

Classes:

Public Defines

define
define
BI_RGB() 0L
define
BI_RLE4() 2L
define
BI_RLE8() 1L

Public Variables

struct _privateRegisterBMP

Public Functions

bool
sReadBMP(Stream & stream, GBitmap * bitmap)
bool
sWriteBMP(GBitmap * bitmap, Stream & stream, U32 compressionLevel)

Detailed Description

Public Defines

BI_BITFIELDS() 3L
BI_RGB() 0L
BI_RLE4() 2L
BI_RLE8() 1L

Public Variables

struct _privateRegisterBMP sStaticRegisterBMP 

Public Functions

sReadBMP(Stream & stream, GBitmap * bitmap)

sWriteBMP(GBitmap * bitmap, Stream & stream, U32 compressionLevel)

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "core/stream/stream.h"
 25
 26#include "gfx/bitmap/gBitmap.h"
 27
 28
 29static bool sReadBMP(Stream &stream, GBitmap *bitmap);
 30static bool sWriteBMP(GBitmap *bitmap, Stream &stream, U32 compressionLevel);
 31
 32static struct _privateRegisterBMP
 33{
 34   _privateRegisterBMP()
 35   {
 36      GBitmap::Registration reg;
 37
 38      reg.extensions.push_back( "bmp" );
 39
 40      reg.readFunc = sReadBMP;
 41      reg.writeFunc = sWriteBMP;
 42
 43      GBitmap::sRegisterFormat( reg );
 44   }
 45} sStaticRegisterBMP;
 46
 47
 48// structures mirror those defined by the win32 API
 49
 50struct RGBQUAD
 51{
 52   U8 rgbBlue;
 53   U8 rgbGreen;
 54   U8 rgbRed;
 55   U8 rgbReserved;
 56};
 57
 58struct BITMAPFILEHEADER
 59{
 60   U16 bfType;
 61   U32 bfSize;
 62   U16 bfReserved1;
 63   U16 bfReserved2;
 64   U32 bfOffBits;
 65};
 66
 67struct BITMAPINFOHEADER
 68{
 69   U32 biSize;
 70   S32 biWidth;
 71   S32 biHeight;
 72   U16 biPlanes;
 73   U16 biBitCount;
 74   U32 biCompression;
 75   U32 biSizeImage;
 76   S32 biXPelsPerMeter;
 77   S32 biYPelsPerMeter;
 78   U32 biClrUsed;
 79   U32 biClrImportant;
 80};
 81
 82// constants for the biCompression field
 83#define BI_RGB        0L
 84#define BI_RLE8       1L
 85#define BI_RLE4       2L
 86#define BI_BITFIELDS  3L
 87
 88
 89//------------------------------------------------------------------------------
 90//-------------------------------------- Supplementary I/O (Partially located in
 91//                                                          bitmapPng.cc)
 92//
 93
 94static bool sReadBMP(Stream &stream, GBitmap *bitmap)
 95{
 96   BITMAPINFOHEADER  bi;
 97   BITMAPFILEHEADER  bf;
 98   RGBQUAD           rgb[256];
 99
100   stream.read(&bf.bfType);
101   stream.read(&bf.bfSize);
102   stream.read(&bf.bfReserved1);
103   stream.read(&bf.bfReserved2);
104   stream.read(&bf.bfOffBits);
105
106   stream.read(&bi.biSize);
107   stream.read(&bi.biWidth);
108   stream.read(&bi.biHeight);
109   stream.read(&bi.biPlanes);
110   stream.read(&bi.biBitCount);
111   stream.read(&bi.biCompression);
112   stream.read(&bi.biSizeImage);
113   stream.read(&bi.biXPelsPerMeter);
114   stream.read(&bi.biYPelsPerMeter);
115   stream.read(&bi.biClrUsed);
116   stream.read(&bi.biClrImportant);
117
118   GFXFormat fmt = GFXFormatR8G8B8;
119   if(bi.biBitCount == 8)
120   {
121      // read in texture palette
122      if(!bi.biClrUsed)
123         bi.biClrUsed = 256;
124      stream.read(sizeof(RGBQUAD) * bi.biClrUsed, rgb);
125   }
126   bitmap->allocateBitmap(bi.biWidth, bi.biHeight, false, fmt);
127   U32   width  = bitmap->getWidth();
128   U32   height = bitmap->getHeight();
129   U32   bytesPerPixel = bitmap->getBytesPerPixel();
130
131   for(U32 i = 0; i < bi.biHeight; i++)
132   {
133      U8 *rowDest = bitmap->getAddress(0, height - i - 1);
134      if (bi.biBitCount == 8)
135      {
136         // use palette...don't worry about being slow
137         for (S32 j=0; j<width; j++)
138         {
139            U8 palIdx;
140            stream.read(&palIdx);
141            U8 * pixelLocation = &rowDest[j*bytesPerPixel];
142            pixelLocation[0] = rgb[palIdx].rgbRed;
143            pixelLocation[1] = rgb[palIdx].rgbGreen;
144            pixelLocation[2] = rgb[palIdx].rgbBlue;
145            if (bytesPerPixel==3)
146               pixelLocation[3] = 255;
147         }
148      }
149      else
150         stream.read(bytesPerPixel * width, rowDest);
151   }
152
153   if(bytesPerPixel == 3 && bi.biBitCount != 8) // do BGR swap
154   {
155      U8 *ptr = bitmap->getAddress(0,0);
156      for(S32 i = 0; i < width * height; i++)
157      {
158         U8 tmp = ptr[0];
159         ptr[0] = ptr[2];
160         ptr[2] = tmp;
161         ptr += 3;
162      }
163   }
164
165   // We know BMP's don't have any transparency
166   bitmap->setHasTransparency(false);
167
168   return true;
169}
170
171static bool sWriteBMP(GBitmap *bitmap, Stream &stream, U32 compressionLevel)
172{
173   TORQUE_UNUSED( compressionLevel );  // BMP does not use compression
174
175   BITMAPINFOHEADER  bi;
176   BITMAPFILEHEADER  bf;
177
178   bi.biSize            = sizeof(BITMAPINFOHEADER);
179   bi.biWidth           = bitmap->getWidth();
180   bi.biHeight          = bitmap->getHeight();         //our data is top-down
181   bi.biPlanes = 1;
182
183   if(bitmap->getFormat() == GFXFormatR8G8B8)
184   {
185      bi.biBitCount = 24;
186      bi.biCompression = BI_RGB;
187      bi.biClrUsed = 0;
188   }
189   else
190   {
191      bi.biBitCount = 0;
192      bi.biCompression = BI_RGB; // Removes warning C4701 on line
193      AssertISV(false, "GBitmap::writeMSBmp - only support R8G8B8 formats!");
194   }
195
196   U32   width  = bitmap->getWidth();
197   U32   height = bitmap->getHeight();
198
199   U32 bytesPP = bi.biBitCount >> 3;
200   bi.biSizeImage       = width * height * bytesPP;
201   bi.biXPelsPerMeter   = 0;
202   bi.biYPelsPerMeter   = 0;
203   bi.biClrUsed         = 0;
204   bi.biClrImportant    = 0;
205
206   bf.bfType   = makeFourCCTag('B','M',0,0);     //Type of file 'BM'
207   bf.bfOffBits= sizeof(BITMAPINFOHEADER)
208               + sizeof(BITMAPFILEHEADER)
209               + (sizeof(RGBQUAD)*bi.biClrUsed);
210   bf.bfSize            = bf.bfOffBits + bi.biSizeImage;
211   bf.bfReserved1       = 0;
212   bf.bfReserved2       = 0;
213
214   stream.write(bf.bfType);
215   stream.write(bf.bfSize);
216   stream.write(bf.bfReserved1);
217   stream.write(bf.bfReserved2);
218   stream.write(bf.bfOffBits);
219
220   stream.write(bi.biSize);
221   stream.write(bi.biWidth);
222   stream.write(bi.biHeight);
223   stream.write(bi.biPlanes);
224   stream.write(bi.biBitCount);
225   stream.write(bi.biCompression);
226   stream.write(bi.biSizeImage);
227   stream.write(bi.biXPelsPerMeter);
228   stream.write(bi.biYPelsPerMeter);
229   stream.write(bi.biClrUsed);
230   stream.write(bi.biClrImportant);
231
232   //write the bitmap bits
233   U8* pMSUpsideDownBits = new U8[bi.biSizeImage];
234   for (U32 i = 0; i < height; i++)
235   {
236      const U8* pSrc = bitmap->getAddress(0, i);
237      U8* pDst = pMSUpsideDownBits + (height - i - 1) * width * bytesPP;
238
239      dMemcpy(pDst, pSrc, width * bytesPP);
240   }
241
242   stream.write(bi.biSizeImage, pMSUpsideDownBits);
243   delete [] pMSUpsideDownBits;
244
245   return stream.getStatus() == Stream::Ok;
246}
247