/* ScummVM - Scumm Interpreter * Copyright (C) 2006 The ScummVM project * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $URL$ * $Id$ */ #include "graphics/imagedec.h" #include "common/system.h" #include "common/file.h" namespace Graphics { // // BMP Decoder // class BMPDecoder : public ImageDecoder { public: BMPDecoder() {} virtual ~BMPDecoder() {} bool decodeable(Common::SeekableReadStream &stream); Surface *decodeImage(Common::SeekableReadStream &stream); struct BitmapHeader { uint16 type; uint32 size; uint16 res1; uint16 res2; uint32 imageOffset; }; struct InfoHeader { uint32 size; uint32 width; uint32 height; uint16 planes; uint16 bitsPerPixel; uint32 compression; uint32 imageSize; uint32 pixelsPerMeterX; uint32 pixelsPerMeterY; uint32 colorsUsed; uint32 colorsImportant; }; }; bool BMPDecoder::decodeable(Common::SeekableReadStream &stream) { BitmapHeader header; stream.seek(0); header.type = stream.readUint16BE(); header.size = stream.readUint32LE(); // TODO: maybe improve this detection if (header.size == 0 || header.type != 'BM') return false; return true; } Surface *BMPDecoder::decodeImage(Common::SeekableReadStream &stream) { if (!decodeable(stream)) { return 0; } BitmapHeader header; InfoHeader info; stream.seek(0); header.type = stream.readUint16BE(); header.size = stream.readUint32LE(); header.res1 = stream.readUint16LE(); header.res2 = stream.readUint16LE(); header.imageOffset = stream.readUint32LE(); if (header.size == 0 || header.type != 'BM') { stream.seek(0); return 0; } info.size = stream.readUint32LE(); info.width = stream.readUint32LE(); info.height = stream.readUint32LE(); info.planes = stream.readUint16LE(); info.bitsPerPixel = stream.readUint16LE(); info.compression = stream.readUint32LE(); info.imageSize = stream.readUint32LE(); info.pixelsPerMeterX = stream.readUint32LE(); info.pixelsPerMeterY = stream.readUint32LE(); info.colorsUsed = stream.readUint32LE(); info.colorsImportant = stream.readUint32LE(); stream.seek(header.imageOffset); if (info.bitsPerPixel != 24) { stream.seek(0); return 0; } uint8 r = 0, g = 0, b = 0; Surface *newSurf = new Surface; assert(newSurf); newSurf->create(info.width, info.height, sizeof(OverlayColor)); assert(newSurf->pixels); OverlayColor *curPixel = (OverlayColor*)newSurf->pixels + (newSurf->h-1) * newSurf->w; int pitchAdd = info.width % 4; for (int i = 0; i < newSurf->h; ++i) { for (int i2 = 0; i2 < newSurf->w; ++i2) { b = stream.readByte(); g = stream.readByte(); r = stream.readByte(); *curPixel = g_system->RGBToColor(r, g, b); ++curPixel; } stream.seek(pitchAdd, SEEK_CUR); curPixel -= newSurf->w*2; } stream.seek(0); return newSurf; } #pragma mark - Surface *ImageDecoder::loadFile(const Common::String &name) { Surface *newSurf = 0; Common::File imageFile; if (imageFile.open(name)) { newSurf = loadFile(imageFile); } return newSurf; } Surface *ImageDecoder::loadFile(Common::SeekableReadStream &stream) { // TODO: implement support for bzipped memory // FIXME: this is not a very nice solution but it should work // for the moment, we should use a different way to get all // decoders static BMPDecoder bmpDecoder; static ImageDecoder *decoderList[] = { &bmpDecoder, // for uncompressed .BMP files 0 }; ImageDecoder *decoder = 0; for (int i = 0; decoderList[i] != 0; ++i) { if (decoderList[i]->decodeable(stream)) { decoder = decoderList[i]; break; } } if (!decoder) return 0; return decoder->decodeImage(stream); } } // end of namespace Graphics