138 lines
3.2 KiB
C++
138 lines
3.2 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
------------------------------------------------------------------------------*/
|
|
|
|
|
|
#include "picture/pict.h"
|
|
#include "picture/pict_io.h"
|
|
#include "log/log.h"
|
|
|
|
using namespace GS;
|
|
|
|
#define IMGBMP_BI_RGB 0
|
|
#define IMGBMP_BI_RLE8 1
|
|
#define IMGBMP_BI_RLE4 2
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool PictureIO::BmpLoad(Picture &picture, IO::Handle &handle)
|
|
{
|
|
handle.Rewind();
|
|
size_t size = handle.GetSize();
|
|
if (size < 10)
|
|
return false;
|
|
|
|
// Magic number
|
|
if ((handle.Read <char> () != 'B') || (handle.Read <char> () != 'M'))
|
|
return false;
|
|
|
|
handle.Seek(8);
|
|
uint OffBits = handle.Read <uint> (), width, height;
|
|
ushort bpp;
|
|
|
|
if (handle.Read <uint> () == 40) // we met a BITMAPCOREHEADER
|
|
{
|
|
width = handle.Read <uint> ();
|
|
height = handle.Read <uint> ();
|
|
}
|
|
else // we met a BITMAPINFOHEADER
|
|
{
|
|
width = handle.Read <ushort> ();
|
|
height = handle.Read <ushort> ();
|
|
}
|
|
handle.Seek(2);
|
|
bpp = handle.Read <ushort> ();
|
|
|
|
if ((bpp != 8) && (bpp != 24) && (bpp != 32))
|
|
__ERR__(__LOG_E__ << "BMP format unhandled (neither RGB8, RGB24 or BGR8).\n", false)
|
|
|
|
// Decode bitmap data.
|
|
if (!picture.AllocAs(width, height, PixelFormat::BGR8))
|
|
__ERR__(__LOG_E__ << "Failed to allocate output buffer.\n", false)
|
|
|
|
uint *rgb = (uint *)picture.GetData();
|
|
Array <uchar> bmp(size - OffBits);
|
|
if (!bmp)
|
|
__ERR__(__LOG_E__ << "Failed to allocate input framebuffer.\n", false)
|
|
|
|
uchar *_bmp = &bmp[0];
|
|
handle.Seek(OffBits, GS::IO::Base::SeekStart);
|
|
handle.Read((void *)_bmp, OffBits);
|
|
|
|
rgb += (picture.GetHeight() - 1) * picture.GetWidth();
|
|
|
|
// Load palette
|
|
Array <uint> palette;
|
|
|
|
if (bpp < 16)
|
|
{
|
|
__LOG__ << "Picture is palletized.\n";
|
|
if (palette.Allocate(1 << bpp))
|
|
{
|
|
char cbuf[4];
|
|
handle.Seek(54, GS::IO::Base::SeekStart);
|
|
for (int n = 0; n < (1 << bpp); ++n)
|
|
{
|
|
handle.Read(cbuf, 4);
|
|
palette[n] = (cbuf[3] << 24) + (cbuf[2] << 16) + (cbuf[1] << 8) + cbuf[0];
|
|
}
|
|
}
|
|
else
|
|
__ERR__(__LOG_E__ << "Failed to allocate palette.\n", false)
|
|
}
|
|
|
|
// Even width
|
|
switch (bpp)
|
|
{
|
|
case 8:
|
|
{
|
|
// 32 bit 0 padding.
|
|
uint pad = 0;
|
|
if (picture.GetWidth() & 3)
|
|
pad = 4 - (picture.GetWidth() & 3);
|
|
|
|
for (uint c2 = 0; c2 < picture.GetHeight(); c2++)
|
|
{
|
|
for (uint c = 0; c < picture.GetWidth(); c++)
|
|
rgb[c] = palette[*_bmp++];
|
|
_bmp += pad;
|
|
rgb -= picture.GetWidth();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 16:
|
|
break;
|
|
|
|
case 24:
|
|
for (uint c2 = 0; c2 < picture.GetHeight(); c2++)
|
|
{
|
|
for (uint c = 0; c < picture.GetWidth(); c++)
|
|
{
|
|
rgb[c] = (_bmp[2] << 16) + (_bmp[1] << 8) + _bmp[0];
|
|
_bmp += 3;
|
|
}
|
|
uint dt = 3 * picture.GetWidth();
|
|
if (dt & 3)
|
|
_bmp += (4 - (dt & 3));
|
|
rgb -= picture.GetWidth();
|
|
}
|
|
break;
|
|
|
|
case 32:
|
|
for (uint c2 = 0; c2 < picture.GetHeight(); c2++)
|
|
{
|
|
for (uint c = 0; c < picture.GetWidth(); c++)
|
|
{
|
|
rgb[c] = (_bmp[2] << 16) + (_bmp[1] << 8) + _bmp[0];
|
|
_bmp += 4;
|
|
}
|
|
rgb -= picture.GetWidth();
|
|
}
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
//-----------------------------------------------------------------------------
|