/* ----------------------------------------------------------------------------- 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 () != 'B') || (handle.Read () != 'M')) return false; handle.Seek(8); uint OffBits = handle.Read (), width, height; ushort bpp; if (handle.Read () == 40) // we met a BITMAPCOREHEADER { width = handle.Read (); height = handle.Read (); } else // we met a BITMAPINFOHEADER { width = handle.Read (); height = handle.Read (); } handle.Seek(2); bpp = handle.Read (); 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 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 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; } //-----------------------------------------------------------------------------