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   PROFILE_SCOPE(sReadBMP);
 97   BITMAPINFOHEADER  bi;
 98   BITMAPFILEHEADER  bf;
 99   RGBQUAD           rgb[256];
100
101   stream.read(&bf.bfType);
102   stream.read(&bf.bfSize);
103   stream.read(&bf.bfReserved1);
104   stream.read(&bf.bfReserved2);
105   stream.read(&bf.bfOffBits);
106
107   stream.read(&bi.biSize);
108   stream.read(&bi.biWidth);
109   stream.read(&bi.biHeight);
110   stream.read(&bi.biPlanes);
111   stream.read(&bi.biBitCount);
112   stream.read(&bi.biCompression);
113   stream.read(&bi.biSizeImage);
114   stream.read(&bi.biXPelsPerMeter);
115   stream.read(&bi.biYPelsPerMeter);
116   stream.read(&bi.biClrUsed);
117   stream.read(&bi.biClrImportant);
118
119   GFXFormat fmt = GFXFormatR8G8B8;
120   if(bi.biBitCount == 8)
121   {
122      // read in texture palette
123      if(!bi.biClrUsed)
124         bi.biClrUsed = 256;
125      stream.read(sizeof(RGBQUAD) * bi.biClrUsed, rgb);
126   }
127   bitmap->allocateBitmap(bi.biWidth, bi.biHeight, false, fmt);
128   U32   width  = bitmap->getWidth();
129   U32   height = bitmap->getHeight();
130   U32   bytesPerPixel = bitmap->getBytesPerPixel();
131
132   for(U32 i = 0; i < bi.biHeight; i++)
133   {
134      U8 *rowDest = bitmap->getAddress(0, height - i - 1);
135      if (bi.biBitCount == 8)
136      {
137         // use palette...don't worry about being slow
138         for (S32 j=0; j<width; j++)
139         {
140            U8 palIdx;
141            stream.read(&palIdx);
142            U8 * pixelLocation = &rowDest[j*bytesPerPixel];
143            pixelLocation[0] = rgb[palIdx].rgbRed;
144            pixelLocation[1] = rgb[palIdx].rgbGreen;
145            pixelLocation[2] = rgb[palIdx].rgbBlue;
146            if (bytesPerPixel==3)
147               pixelLocation[3] = 255;
148         }
149      }
150      else
151         stream.read(bytesPerPixel * width, rowDest);
152   }
153
154   if(bytesPerPixel == 3 && bi.biBitCount != 8) // do BGR swap
155   {
156      U8 *ptr = bitmap->getAddress(0,0);
157      for(S32 i = 0; i < width * height; i++)
158      {
159         U8 tmp = ptr[0];
160         ptr[0] = ptr[2];
161         ptr[2] = tmp;
162         ptr += 3;
163      }
164   }
165
166   // We know BMP's don't have any transparency
167   bitmap->setHasTransparency(false);
168
169   return true;
170}
171
172static bool sWriteBMP(GBitmap *bitmap, Stream &stream, U32 compressionLevel)
173{
174   TORQUE_UNUSED( compressionLevel );  // BMP does not use compression
175
176   BITMAPINFOHEADER  bi;
177   BITMAPFILEHEADER  bf;
178
179   bi.biSize            = sizeof(BITMAPINFOHEADER);
180   bi.biWidth           = bitmap->getWidth();
181   bi.biHeight          = bitmap->getHeight();         //our data is top-down
182   bi.biPlanes = 1;
183
184   if(bitmap->getFormat() == GFXFormatR8G8B8)
185   {
186      bi.biBitCount = 24;
187      bi.biCompression = BI_RGB;
188      bi.biClrUsed = 0;
189   }
190   else
191   {
192      bi.biBitCount = 0;
193      bi.biCompression = BI_RGB; // Removes warning C4701 on line
194      AssertISV(false, "GBitmap::writeMSBmp - only support R8G8B8 formats!");
195   }
196
197   U32   width  = bitmap->getWidth();
198   U32   height = bitmap->getHeight();
199
200   U32 bytesPP = bi.biBitCount >> 3;
201   bi.biSizeImage       = width * height * bytesPP;
202   bi.biXPelsPerMeter   = 0;
203   bi.biYPelsPerMeter   = 0;
204   bi.biClrUsed         = 0;
205   bi.biClrImportant    = 0;
206
207   bf.bfType   = makeFourCCTag('B','M',0,0);     //Type of file 'BM'
208   bf.bfOffBits= sizeof(BITMAPINFOHEADER)
209               + sizeof(BITMAPFILEHEADER)
210               + (sizeof(RGBQUAD)*bi.biClrUsed);
211   bf.bfSize            = bf.bfOffBits + bi.biSizeImage;
212   bf.bfReserved1       = 0;
213   bf.bfReserved2       = 0;
214
215   stream.write(bf.bfType);
216   stream.write(bf.bfSize);
217   stream.write(bf.bfReserved1);
218   stream.write(bf.bfReserved2);
219   stream.write(bf.bfOffBits);
220
221   stream.write(bi.biSize);
222   stream.write(bi.biWidth);
223   stream.write(bi.biHeight);
224   stream.write(bi.biPlanes);
225   stream.write(bi.biBitCount);
226   stream.write(bi.biCompression);
227   stream.write(bi.biSizeImage);
228   stream.write(bi.biXPelsPerMeter);
229   stream.write(bi.biYPelsPerMeter);
230   stream.write(bi.biClrUsed);
231   stream.write(bi.biClrImportant);
232
233   //write the bitmap bits
234   U8* pMSUpsideDownBits = new U8[bi.biSizeImage];
235   for (U32 i = 0; i < height; i++)
236   {
237      const U8* pSrc = bitmap->getAddress(0, i);
238      U8* pDst = pMSUpsideDownBits + (height - i - 1) * width * bytesPP;
239
240      dMemcpy(pDst, pSrc, width * bytesPP);
241   }
242
243   stream.write(bi.biSizeImage, pMSUpsideDownBits);
244   delete [] pMSUpsideDownBits;
245
246   return stream.getStatus() == Stream::Ok;
247}
248