Files
Webcam/include/framework/picture/pict_bmp.cpp

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;
}
//-----------------------------------------------------------------------------