Speech bubbles can point down right.
[scummvm-innocent.git] / graphics / imagedec.cpp
blobb02ab7ac47ce3f495095776fa65c2bfe677ee8ae
1 /* ScummVM - Graphic Adventure Engine
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * $URL$
22 * $Id$
25 #include "graphics/imagedec.h"
27 #include "common/file.h"
29 namespace Graphics {
31 // BMP Decoder
33 class BMPDecoder : public ImageDecoder {
34 public:
35 BMPDecoder() {}
36 virtual ~BMPDecoder() {}
38 bool decodeable(Common::SeekableReadStream &stream);
39 Surface *decodeImage(Common::SeekableReadStream &stream, const PixelFormat &format);
41 struct BitmapHeader {
42 uint16 type;
43 uint32 size;
44 uint16 res1;
45 uint16 res2;
46 uint32 imageOffset;
49 struct InfoHeader {
50 uint32 size;
51 uint32 width;
52 uint32 height;
53 uint16 planes;
54 uint16 bitsPerPixel;
55 uint32 compression;
56 uint32 imageSize;
57 uint32 pixelsPerMeterX;
58 uint32 pixelsPerMeterY;
59 uint32 colorsUsed;
60 uint32 colorsImportant;
64 bool BMPDecoder::decodeable(Common::SeekableReadStream &stream) {
65 BitmapHeader header;
66 stream.seek(0);
67 header.type = stream.readUint16BE();
68 header.size = stream.readUint32LE();
70 // TODO: maybe improve this detection
71 if (header.size == 0 || header.type != 'BM')
72 return false;
74 return true;
77 Surface *BMPDecoder::decodeImage(Common::SeekableReadStream &stream, const PixelFormat &format) {
78 if (!decodeable(stream)) {
79 return 0;
82 BitmapHeader header;
83 InfoHeader info;
85 stream.seek(0);
86 header.type = stream.readUint16BE();
87 header.size = stream.readUint32LE();
88 header.res1 = stream.readUint16LE();
89 header.res2 = stream.readUint16LE();
90 header.imageOffset = stream.readUint32LE();
92 if (header.size == 0 || header.type != 'BM') {
93 stream.seek(0);
94 return 0;
97 info.size = stream.readUint32LE();
98 info.width = stream.readUint32LE();
99 info.height = stream.readUint32LE();
100 info.planes = stream.readUint16LE();
101 info.bitsPerPixel = stream.readUint16LE();
102 info.compression = stream.readUint32LE();
103 info.imageSize = stream.readUint32LE();
104 info.pixelsPerMeterX = stream.readUint32LE();
105 info.pixelsPerMeterY = stream.readUint32LE();
106 info.colorsUsed = stream.readUint32LE();
107 info.colorsImportant = stream.readUint32LE();
109 stream.seek(header.imageOffset);
111 if (info.bitsPerPixel != 24) {
112 stream.seek(0);
113 return 0;
116 uint8 r = 0, g = 0, b = 0;
117 Surface *newSurf = new Surface;
118 assert(newSurf);
119 newSurf->create(info.width, info.height, sizeof(OverlayColor));
120 assert(newSurf->pixels);
121 OverlayColor *curPixel = (OverlayColor*)newSurf->pixels + (newSurf->h-1) * newSurf->w;
122 int pitchAdd = info.width % 4;
123 for (int i = 0; i < newSurf->h; ++i) {
124 for (int i2 = 0; i2 < newSurf->w; ++i2) {
125 b = stream.readByte();
126 g = stream.readByte();
127 r = stream.readByte();
128 *curPixel = format.RGBToColor(r, g, b);
129 ++curPixel;
131 stream.seek(pitchAdd, SEEK_CUR);
132 curPixel -= newSurf->w*2;
135 stream.seek(0);
136 return newSurf;
139 #pragma mark -
141 Surface *ImageDecoder::loadFile(const Common::String &name, const PixelFormat &format) {
142 Surface *newSurf = 0;
144 Common::File imageFile;
145 if (imageFile.open(name)) {
146 newSurf = loadFile(imageFile, format);
149 return newSurf;
152 Surface *ImageDecoder::loadFile(Common::SeekableReadStream &stream, const PixelFormat &format) {
153 // TODO: implement support for bzipped memory
155 // FIXME: this is not a very nice solution but it should work
156 // for the moment, we should use a different way to get all
157 // decoders
158 static BMPDecoder bmpDecoder;
159 static ImageDecoder *decoderList[] = {
160 &bmpDecoder, // for uncompressed .BMP files
164 ImageDecoder *decoder = 0;
165 for (int i = 0; decoderList[i] != 0; ++i) {
166 if (decoderList[i]->decodeable(stream)) {
167 decoder = decoderList[i];
168 break;
172 if (!decoder)
173 return 0;
175 return decoder->decodeImage(stream, format);
177 } // end of namespace Graphics