aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/vkeybd/virtual-keyboard-parser.cpp14
-rw-r--r--engines/hugo/dialogs.cpp15
-rw-r--r--graphics/decoders/bmp.cpp159
-rw-r--r--graphics/decoders/bmp.h (renamed from graphics/imagedec.h)43
-rw-r--r--graphics/decoders/image_decoder.h85
-rw-r--r--graphics/imagedec.cpp176
-rw-r--r--graphics/module.mk4
-rw-r--r--gui/ThemeEngine.cpp15
8 files changed, 294 insertions, 217 deletions
diff --git a/backends/vkeybd/virtual-keyboard-parser.cpp b/backends/vkeybd/virtual-keyboard-parser.cpp
index 1958113578..bb8286d1f5 100644
--- a/backends/vkeybd/virtual-keyboard-parser.cpp
+++ b/backends/vkeybd/virtual-keyboard-parser.cpp
@@ -34,7 +34,7 @@
#include "common/tokenizer.h"
#include "common/stream.h"
-#include "graphics/imagedec.h"
+#include "graphics/decoders/bmp.h"
namespace Common {
@@ -266,11 +266,15 @@ bool VirtualKeyboardParser::parserCallback_layout(ParserNode *node) {
const Graphics::PixelFormat format = g_system->getOverlayFormat();
- _mode->image = Graphics::ImageDecoder::loadFile(*file, format);
- delete file;
+ {
+ Graphics::BitmapDecoder bmp;
+ if (!bmp.loadStream(*file))
+ return parserError("Error loading bitmap '" + _mode->bitmapName + "'");
+
+ _mode->image = bmp.getSurface()->convertTo(format);
+ }
- if (!_mode->image)
- return parserError("Error loading bitmap '" + _mode->bitmapName + "'");
+ delete file;
int r, g, b;
if (node->values.contains("transparent_color")) {
diff --git a/engines/hugo/dialogs.cpp b/engines/hugo/dialogs.cpp
index c43cdd7b46..e0b0198470 100644
--- a/engines/hugo/dialogs.cpp
+++ b/engines/hugo/dialogs.cpp
@@ -21,7 +21,7 @@
*/
#include "common/substream.h"
-#include "graphics/imagedec.h"
+#include "graphics/decoders/bmp.h"
#include "gui/gui-manager.h"
#include "gui/ThemeEval.h"
@@ -128,7 +128,16 @@ void TopMenu::loadBmpArr(Common::SeekableReadStream &in) {
uint16 bmpSize = in.readUint16BE();
uint32 filPos = in.pos();
Common::SeekableSubReadStream stream(&in, filPos, filPos + bmpSize);
- arrayBmp[i * 2] = Graphics::ImageDecoder::loadFile(stream, g_system->getOverlayFormat());
+
+ Graphics::BitmapDecoder bitmapDecoder;
+ if (!bitmapDecoder.loadStream(stream))
+ error("TopMenu::loadBmpArr(): Could not load bitmap");
+
+ const Graphics::Surface *bitmapSrc = bitmapDecoder.getSurface();
+ if (bitmapSrc->format.bytesPerPixel == 1)
+ error("TopMenu::loadBmpArr(): Unhandled paletted image");
+
+ arrayBmp[i * 2] = bitmapSrc->convertTo(g_system->getOverlayFormat());
arrayBmp[i * 2 + 1] = new Graphics::Surface();
arrayBmp[i * 2 + 1]->create(arrayBmp[i * 2]->w * 2, arrayBmp[i * 2]->h * 2, g_system->getOverlayFormat());
byte *src = (byte *)arrayBmp[i * 2]->pixels;
@@ -154,7 +163,7 @@ void TopMenu::loadBmpArr(Common::SeekableReadStream &in) {
}
}
- in.skip(bmpSize);
+ in.seek(filPos + bmpSize);
}
}
diff --git a/graphics/decoders/bmp.cpp b/graphics/decoders/bmp.cpp
new file mode 100644
index 0000000000..0d44881d7c
--- /dev/null
+++ b/graphics/decoders/bmp.cpp
@@ -0,0 +1,159 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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.
+ */
+
+#include "common/stream.h"
+#include "common/textconsole.h"
+
+#include "graphics/pixelformat.h"
+#include "graphics/surface.h"
+#include "graphics/decoders/bmp.h"
+
+namespace Graphics {
+
+BitmapDecoder::BitmapDecoder() {
+ _surface = 0;
+ _palette = 0;
+}
+
+BitmapDecoder::~BitmapDecoder() {
+ destroy();
+}
+
+void BitmapDecoder::destroy() {
+ if (_surface) {
+ _surface->free();
+ delete _surface; _surface = 0;
+ }
+
+ delete[] _palette; _palette = 0;
+}
+
+bool BitmapDecoder::loadStream(Common::SeekableReadStream &stream) {
+ destroy();
+
+ if (stream.readByte() != 'B')
+ return false;
+
+ if (stream.readByte() != 'M')
+ return false;
+
+ /* uint32 fileSize = */ stream.readUint32LE();
+ /* uint16 res1 = */ stream.readUint16LE();
+ /* uint16 res2 = */ stream.readUint16LE();
+ uint32 imageOffset = stream.readUint32LE();
+
+ uint32 infoSize = stream.readUint32LE();
+ if (infoSize != 40) {
+ warning("Only Windows v3 bitmaps are supported");
+ return false;
+ }
+
+ uint32 width = stream.readUint32LE();
+ int32 height = stream.readSint32LE();
+
+ if (width == 0 || height == 0)
+ return false;
+
+ if (height < 0) {
+ warning("Right-side up bitmaps not supported");
+ return false;
+ }
+
+ /* uint16 planes = */ stream.readUint16LE();
+ uint16 bitsPerPixel = stream.readUint16LE();
+
+ if (bitsPerPixel != 8 && bitsPerPixel != 24) {
+ warning("%dbpp bitmaps not supported", bitsPerPixel);
+ return false;
+ }
+
+ uint32 compression = stream.readUint32LE();
+
+ if (compression != 0) {
+ warning("Compressed bitmaps not supported");
+ return false;
+ }
+
+ /* uint32 imageSize = */ stream.readUint32LE();
+ /* uint32 pixelsPerMeterX = */ stream.readUint32LE();
+ /* uint32 pixelsPerMeterY = */ stream.readUint32LE();
+ uint32 colorsUsed = stream.readUint32LE();
+ /* uint32 colorsImportant = */ stream.readUint32LE();
+
+ if (colorsUsed == 0)
+ colorsUsed = 256;
+
+ if (bitsPerPixel == 8) {
+ // Read the palette
+ _palette = new byte[colorsUsed * 3];
+ for (uint16 i = 0; i < colorsUsed; i++) {
+ _palette[i * 3 + 2] = stream.readByte();
+ _palette[i * 3 + 1] = stream.readByte();
+ _palette[i * 3 + 0] = stream.readByte();
+ stream.readByte();
+ }
+ }
+
+ // Start us at the beginning of the image
+ stream.seek(imageOffset);
+
+ Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8();
+
+ // BGRA for 24bpp
+ if (bitsPerPixel == 24)
+ format = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0);
+
+ _surface = new Graphics::Surface();
+ _surface->create(width, height, format);
+
+ int srcPitch = width * (bitsPerPixel >> 3);
+ const int extraDataLength = (srcPitch % 4) ? 4 - (srcPitch % 4) : 0;
+
+ if (bitsPerPixel == 8) {
+ byte *dst = (byte *)_surface->pixels;
+
+ for (int32 i = 0; i < height; i++) {
+ stream.read(dst + (height - i - 1) * width, width);
+ stream.skip(extraDataLength);
+ }
+ } else {
+ byte *dst = (byte *)_surface->pixels + (height - 1) * _surface->pitch;
+
+ for (int32 i = 0; i < height; i++) {
+ for (uint32 j = 0; j < width; j++) {
+ byte b = stream.readByte();
+ byte g = stream.readByte();
+ byte r = stream.readByte();
+ uint32 color = format.RGBToColor(r, g, b);
+
+ *((uint32 *)dst) = color;
+ dst += format.bytesPerPixel;
+ }
+
+ stream.skip(extraDataLength);
+ dst -= _surface->pitch * 2;
+ }
+ }
+
+ return true;
+}
+
+} // End of namespace Graphics
diff --git a/graphics/imagedec.h b/graphics/decoders/bmp.h
index b03b8bc36b..e11b12fad6 100644
--- a/graphics/imagedec.h
+++ b/graphics/decoders/bmp.h
@@ -19,11 +19,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef GRAPHICS_IMAGEDEC_H
-#define GRAPHICS_IMAGEDEC_H
+#ifndef GRAPHICS_DECODERS_BMP_H
+#define GRAPHICS_DECODERS_BMP_H
#include "common/scummsys.h"
#include "common/str.h"
+#include "graphics/decoders/image_decoder.h"
namespace Common{
class SeekableReadStream;
@@ -34,32 +35,22 @@ namespace Graphics {
struct PixelFormat;
struct Surface;
-class ImageDecoder {
+class BitmapDecoder : public ImageDecoder {
public:
- virtual ~ImageDecoder() {}
-
- static Surface *loadFile(const Common::String &name, const PixelFormat &format);
- static Surface *loadFile(Common::SeekableReadStream &stream, const PixelFormat &format);
-
- /**
- * checks if the data can be decoded by this decoder
- *
- * @param stream memory read stream
- * @return true if it can be decoded, otherwise false
- */
- virtual bool decodeable(Common::SeekableReadStream &stream) = 0;
-
- /**
- * decodes the data and returns an pointer to the resulting surface.
- * Surface::free() must be called by the user also it must be deleted
- * with delete;
- *
- * @param stream the memory stream which should be decoded
- * @param format the pixel format used to generate the surface
- * @return returns a new surface if the image could be decoded, otherwise 0
- */
- virtual Surface *decodeImage(Common::SeekableReadStream &stream, const PixelFormat &format) = 0;
+ BitmapDecoder();
+ virtual ~BitmapDecoder();
+
+ // ImageDecoder API
+ void destroy();
+ virtual bool loadStream(Common::SeekableReadStream &stream);
+ virtual const Surface *getSurface() const { return _surface; }
+ virtual const byte *getPalette() { return _palette; }
+
+private:
+ Surface *_surface;
+ byte *_palette;
};
+
} // End of namespace Graphics
#endif
diff --git a/graphics/decoders/image_decoder.h b/graphics/decoders/image_decoder.h
new file mode 100644
index 0000000000..e768f7f9a2
--- /dev/null
+++ b/graphics/decoders/image_decoder.h
@@ -0,0 +1,85 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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.
+ */
+
+#ifndef GRAPHICS_DECODERS_IMAGEDECODER_H
+#define GRAPHICS_DECODERS_IMAGEDECODER_H
+
+#include "common/scummsys.h"
+#include "common/str.h"
+
+namespace Common{
+class SeekableReadStream;
+}
+
+namespace Graphics {
+
+struct PixelFormat;
+struct Surface;
+
+/**
+ * A representation of an image decoder that maintains ownership of the surface
+ * and palette it decodes to.
+ */
+class ImageDecoder {
+public:
+ virtual ~ImageDecoder() {}
+
+ /**
+ * Load an image from the specified stream
+ *
+ * @param stream the input stream
+ * @return whether loading the file succeeded
+ * @see getSurface
+ * @see getPalette
+ */
+ virtual bool loadStream(Common::SeekableReadStream &stream) = 0;
+
+ /**
+ * Destroy this decoder's surface and palette
+ */
+ virtual void destroy() = 0;
+
+ /**
+ * Get the decoded surface
+ *
+ * This surface is owned by this ImageDecoder and will remain valid
+ * until destroy() or loadStream() is called, or until this ImageDecoder's
+ * destructor is called.
+ *
+ * @return the decoded surface, or 0 if no surface is present
+ */
+ virtual const Surface *getSurface() const = 0;
+
+ /**
+ * Get the decoded palette
+ *
+ * This palette is owned by this ImageDecoder and will remain valid
+ * until destroy() or loadStream() is called, or until this ImageDecoder's
+ * destructor is called.
+ *
+ * @return the decoded palette, or 0 if no palette is present
+ */
+ virtual const byte *getPalette() const { return 0; }
+};
+
+} // End of namespace Graphics
+
+#endif
diff --git a/graphics/imagedec.cpp b/graphics/imagedec.cpp
deleted file mode 100644
index 9552f095fa..0000000000
--- a/graphics/imagedec.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * 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.
- */
-
-#include "graphics/imagedec.h"
-#include "graphics/pixelformat.h"
-#include "graphics/surface.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, const PixelFormat &format);
-
- 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, const PixelFormat &format) {
- 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, format);
- 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 = format.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, const PixelFormat &format) {
- Surface *newSurf = 0;
-
- Common::File imageFile;
- if (imageFile.open(name)) {
- newSurf = loadFile(imageFile, format);
- }
-
- return newSurf;
-}
-
-Surface *ImageDecoder::loadFile(Common::SeekableReadStream &stream, const PixelFormat &format) {
- // 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, format);
-}
-} // End of namespace Graphics
diff --git a/graphics/module.mk b/graphics/module.mk
index 1e84b2425d..5c1d313ca9 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -12,7 +12,6 @@ MODULE_OBJS := \
fonts/ttf.o \
fonts/winfont.o \
iff.o \
- imagedec.o \
jpeg.o \
maccursor.o \
pict.o \
@@ -26,7 +25,8 @@ MODULE_OBJS := \
VectorRenderer.o \
VectorRendererSpec.o \
wincursor.o \
- yuv_to_rgb.o
+ yuv_to_rgb.o \
+ decoders/bmp.o
ifdef USE_SCALERS
MODULE_OBJS += \
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 2cb1635e20..bcfd41e05b 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -30,11 +30,11 @@
#include "graphics/cursorman.h"
#include "graphics/fontman.h"
-#include "graphics/imagedec.h"
#include "graphics/surface.h"
#include "graphics/VectorRenderer.h"
#include "graphics/fonts/bdf.h"
#include "graphics/fonts/ttf.h"
+#include "graphics/decoders/bmp.h"
#include "gui/widget.h"
#include "gui/ThemeEngine.h"
@@ -620,20 +620,25 @@ bool ThemeEngine::addBitmap(const Common::String &filename) {
if (surf)
return true;
- // If not, try to load the bitmap via the ImageDecoder class.
+ // If not, try to load the bitmap via the BitmapDecoder class.
+ Graphics::BitmapDecoder bitmapDecoder;
+ const Graphics::Surface *srcSurface = 0;
Common::ArchiveMemberList members;
_themeFiles.listMatchingMembers(members, filename);
for (Common::ArchiveMemberList::const_iterator i = members.begin(), end = members.end(); i != end; ++i) {
Common::SeekableReadStream *stream = (*i)->createReadStream();
if (stream) {
- surf = Graphics::ImageDecoder::loadFile(*stream, _overlayFormat);
+ bitmapDecoder.loadStream(*stream);
+ srcSurface = bitmapDecoder.getSurface();
delete stream;
-
- if (surf)
+ if (srcSurface)
break;
}
}
+ if (srcSurface && srcSurface->format.bytesPerPixel != 1)
+ surf = srcSurface->convertTo(_overlayFormat);
+
// Store the surface into our hashmap (attention, may store NULL entries!)
_bitmaps[filename] = surf;