tge/engine/dgl/bitmapBmp.cc
2017-04-17 06:17:10 -06:00

204 lines
5.6 KiB
C++
Executable File

//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "dgl/gBitmap.h"
#include "dgl/gPalette.h"
#include "core/stream.h"
#include "platform/platform.h"
// structures mirror those defined by the win32 API
struct RGBQUAD {
U8 rgbBlue;
U8 rgbGreen;
U8 rgbRed;
U8 rgbReserved;
};
struct BITMAPFILEHEADER {
U16 bfType;
U32 bfSize;
U16 bfReserved1;
U16 bfReserved2;
U32 bfOffBits;
};
struct BITMAPINFOHEADER{
U32 biSize;
S32 biWidth;
S32 biHeight;
U16 biPlanes;
U16 biBitCount;
U32 biCompression;
U32 biSizeImage;
S32 biXPelsPerMeter;
S32 biYPelsPerMeter;
U32 biClrUsed;
U32 biClrImportant;
};
// constants for the biCompression field
#define BI_RGB 0L
#define BI_RLE8 1L
#define BI_RLE4 2L
#define BI_BITFIELDS 3L
//------------------------------------------------------------------------------
//-------------------------------------- Supplimentary I/O (Partially located in
// bitmapPng.cc)
//
bool GBitmap::readMSBmp(Stream& stream)
{
BITMAPINFOHEADER bi;
BITMAPFILEHEADER bf;
RGBQUAD rgb[256];
stream.read(&bf.bfType);
stream.read(&bf.bfSize);
stream.read(&bf.bfReserved1);
stream.read(&bf.bfReserved2);
stream.read(&bf.bfOffBits);
stream.read(&bi.biSize);
stream.read(&bi.biWidth);
stream.read(&bi.biHeight);
stream.read(&bi.biPlanes);
stream.read(&bi.biBitCount);
stream.read(&bi.biCompression);
stream.read(&bi.biSizeImage);
stream.read(&bi.biXPelsPerMeter);
stream.read(&bi.biYPelsPerMeter);
stream.read(&bi.biClrUsed);
stream.read(&bi.biClrImportant);
BitmapFormat fmt = RGB;
if(bi.biBitCount == 8)
{
fmt = Palettized;
if(!bi.biClrUsed)
bi.biClrUsed = 256;
stream.read(sizeof(RGBQUAD) * bi.biClrUsed, rgb);
pPalette = new GPalette;
for (U32 i = 0; i < 256; i++)
{
(pPalette->getColors())[i].red = rgb[i].rgbRed;
(pPalette->getColors())[i].green = rgb[i].rgbGreen;
(pPalette->getColors())[i].blue = rgb[i].rgbBlue;
(pPalette->getColors())[i].alpha = 255;
}
}
U8 *rowBuffer = new U8[bi.biWidth * 4];
allocateBitmap(bi.biWidth, bi.biHeight, false, fmt);
S32 width = getWidth();
S32 height = getHeight();
for(int i = 0; i < bi.biHeight; i++)
{
U8 *rowDest = getAddress(0, height - i - 1);
stream.read(bytesPerPixel * width, rowDest);
}
if(bytesPerPixel == 3) // do BGR swap
{
U8 *ptr = getAddress(0,0);
for(int i = 0; i < width * height; i++)
{
U8 tmp = ptr[0];
ptr[0] = ptr[2];
ptr[2] = tmp;
ptr += 3;
}
}
delete[] rowBuffer;
return true;
}
bool GBitmap::writeMSBmp(Stream& io_rStream) const
{
RGBQUAD rgb[256];
BITMAPINFOHEADER bi;
BITMAPFILEHEADER bf;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = getWidth();
bi.biHeight = getHeight(); //our data is top-down
bi.biPlanes = 1;
if(getFormat() == Palettized)
{
bi.biBitCount = 8;
bi.biCompression = BI_RGB;
bi.biClrUsed = 256;
AssertFatal(pPalette != NULL, "Error, must have a palette");
}
else if(getFormat() == RGB)
{
bi.biBitCount = 24;
bi.biCompression = BI_RGB;
bi.biClrUsed = 0;
}
U32 bytesPP = bi.biBitCount >> 3;
bi.biSizeImage = getWidth() * getHeight() * bytesPP;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
bf.bfType = makeFourCCTag('B','M',0,0); //Type of file 'BM'
bf.bfOffBits= sizeof(BITMAPINFOHEADER)
+ sizeof(BITMAPFILEHEADER)
+ (sizeof(RGBQUAD)*bi.biClrUsed);
bf.bfSize = bf.bfOffBits + bi.biSizeImage;
bf.bfReserved1 = 0;
bf.bfReserved2 = 0;
io_rStream.write(bf.bfType);
io_rStream.write(bf.bfSize);
io_rStream.write(bf.bfReserved1);
io_rStream.write(bf.bfReserved2);
io_rStream.write(bf.bfOffBits);
io_rStream.write(bi.biSize);
io_rStream.write(bi.biWidth);
io_rStream.write(bi.biHeight);
io_rStream.write(bi.biPlanes);
io_rStream.write(bi.biBitCount);
io_rStream.write(bi.biCompression);
io_rStream.write(bi.biSizeImage);
io_rStream.write(bi.biXPelsPerMeter);
io_rStream.write(bi.biYPelsPerMeter);
io_rStream.write(bi.biClrUsed);
io_rStream.write(bi.biClrImportant);
if(getFormat() == Palettized)
{
for (S32 ndx=0; ndx<256; ndx++)
{
rgb[ndx].rgbRed = pPalette->getColor(ndx).red;
rgb[ndx].rgbGreen = pPalette->getColor(ndx).green;
rgb[ndx].rgbBlue = pPalette->getColor(ndx).blue;
rgb[ndx].rgbReserved = 0;
}
io_rStream.write(sizeof(RGBQUAD)*256, (U8*)&rgb);
}
//write the bitmap bits
U8* pMSUpsideDownBits = new U8[bi.biSizeImage];
for (U32 i = 0; i < getHeight(); i++) {
const U8* pSrc = getAddress(0, i);
U8* pDst = pMSUpsideDownBits + (getHeight() - i - 1) * getWidth() * bytesPP;
dMemcpy(pDst, pSrc, getWidth() * bytesPP);
}
io_rStream.write(bi.biSizeImage, pMSUpsideDownBits);
delete [] pMSUpsideDownBits;
return io_rStream.getStatus() == Stream::Ok;
}