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.
25 #include "graphics/imagedec.h"
27 #include "common/file.h"
33 class BMPDecoder
: public ImageDecoder
{
36 virtual ~BMPDecoder() {}
38 bool decodeable(Common::SeekableReadStream
&stream
);
39 Surface
*decodeImage(Common::SeekableReadStream
&stream
, const PixelFormat
&format
);
57 uint32 pixelsPerMeterX
;
58 uint32 pixelsPerMeterY
;
60 uint32 colorsImportant
;
64 bool BMPDecoder::decodeable(Common::SeekableReadStream
&stream
) {
67 header
.type
= stream
.readUint16BE();
68 header
.size
= stream
.readUint32LE();
70 // TODO: maybe improve this detection
71 if (header
.size
== 0 || header
.type
!= 'BM')
77 Surface
*BMPDecoder::decodeImage(Common::SeekableReadStream
&stream
, const PixelFormat
&format
) {
78 if (!decodeable(stream
)) {
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') {
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) {
116 uint8 r
= 0, g
= 0, b
= 0;
117 Surface
*newSurf
= new Surface
;
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
);
131 stream
.seek(pitchAdd
, SEEK_CUR
);
132 curPixel
-= newSurf
->w
*2;
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
);
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
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
];
175 return decoder
->decodeImage(stream
, format
);
177 } // end of namespace Graphics