aboutsummaryrefslogtreecommitdiff
path: root/graphics
diff options
context:
space:
mode:
authorStephen Kennedy2008-09-26 21:53:08 +0000
committerStephen Kennedy2008-09-26 21:53:08 +0000
commita7bb113e83c88fad3a23d408caa99f918fdb610a (patch)
tree698dd9d85abaa6a20957bfb9c0e006e9dd1dc8b3 /graphics
parent11c0a3bdedcdf5eb2618b9db67b559663fb93320 (diff)
parentc1385076cbc57f1a4a52946a46b3ea06ecf37f37 (diff)
downloadscummvm-rg350-a7bb113e83c88fad3a23d408caa99f918fdb610a.tar.gz
scummvm-rg350-a7bb113e83c88fad3a23d408caa99f918fdb610a.tar.bz2
scummvm-rg350-a7bb113e83c88fad3a23d408caa99f918fdb610a.zip
Merged revisions 33452-33453,33455-33459,33463-33464,33466-33471,33473-33474,33478,33490,33492,33495-33496,33509-33512,33518-33519,33522-33527,33529-33530,33537,33541,33544,33546,33550,33552-33554,33556,33558,33561-33562,33565,33568,33570,33574,33576,33578-33581,33584-33587,33590,33596,33604-33611,33614-33615,33617-33618,33620-33621,33623,33626-33627,33632-33633,33635,33637,33639-33640,33642-33645,33648,33654-33655,33664,33667-33670,33673-33674,33678,33682,33686-33691,33693,33696,33698,33700,33703,33708,33710,33712-33714,33716,33719,33721-33723,33725-33727,33729-33730,33733,33736,33742,33754,33756,33758,33761,33763,33766,33777,33781-33788,33790,33792-33793,33795,33797,33805,33807-33812,33815-33817,33819,33822,33826,33829,33837,33839,33844,33847,33858-33861,33864,33871-33873,33875,33877-33879,33886,33889-33892,33894,33896,33900,33902-33903,33919,33928,33930,33932-33936,33938-33940,33942-33943,33948,33950,33953,33967,33973,33976,33978,33980,33985,33991,33993,33999-34000,34006,34009,34011,34013,34015,34019,34021-34023,34025,34027-34028,34030,34032-34034,34036,34038-34039,34041,34046-34048,34050-34055,34057,34059-34065,34067,34072,34074,34076,34078-34081,34084,34086-34087,34089-34090,34093,34096-34102,34104,34107,34113,34116,34119,34122,34124,34126,34128,34131-34132,34135,34138,34141,34144,34146,34149,34152-34154,34156-34157,34160,34163-34164,34169,34173,34179-34194,34196-34198,34200-34201,34205-34206,34208-34217,34219-34225,34227-34228,34234-34237,34239-34249,34251-34279,34281-34284,34286-34288,34290-34320,34323-34324,34326,34328-34329,34332,34334,34336,34338-34340,34343-34353,34356-34357,34359-34371,34373,34375,34378,34381-34382,34384-34385,34389-34391,34393-34394,34396-34397,34399-34405,34407-34409,34411,34413,34415,34417-34420,34423-34426,34428-34438,34440-34454,34456-34458,34460,34462-34469,34472,34474,34479-34481,34483-34498,34501-34505,34508,34511-34518,34520-34524,34526-34563,34566-34569,34571-34590,34592,34595-34599,34602-34603,34605,34613-34615,34617,34619-34624,34627-34628,34630-34639,34642-34649 via svnmerge from
https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk svn-id: r34654
Diffstat (limited to 'graphics')
-rw-r--r--graphics/dxa_player.cpp1
-rw-r--r--graphics/dxa_player.h6
-rw-r--r--graphics/font.cpp1
-rw-r--r--graphics/iff.cpp9
-rw-r--r--graphics/imageman.cpp74
-rw-r--r--graphics/imageman.h17
-rw-r--r--graphics/module.mk3
-rw-r--r--graphics/scaler.h16
-rw-r--r--graphics/scaler/hq2x_i386.asm5
-rw-r--r--graphics/scaler/hq3x_i386.asm5
-rw-r--r--graphics/scaler/thumbnail_intern.cpp (renamed from graphics/scaler/thumbnail.cpp)91
-rw-r--r--graphics/surface.cpp5
-rw-r--r--graphics/surface.h19
-rw-r--r--graphics/thumbnail.cpp174
-rw-r--r--graphics/thumbnail.h69
15 files changed, 384 insertions, 111 deletions
diff --git a/graphics/dxa_player.cpp b/graphics/dxa_player.cpp
index 28a1bc4dbd..f4c93a51f1 100644
--- a/graphics/dxa_player.cpp
+++ b/graphics/dxa_player.cpp
@@ -24,6 +24,7 @@
*/
#include "common/endian.h"
+#include "common/file.h"
#include "graphics/dxa_player.h"
#include "common/util.h"
diff --git a/graphics/dxa_player.h b/graphics/dxa_player.h
index 5415e440d2..dbe39bbcee 100644
--- a/graphics/dxa_player.h
+++ b/graphics/dxa_player.h
@@ -27,11 +27,7 @@
#define GRAPHICS_DXA_PLAYER_H
#include "common/scummsys.h"
-#include "common/file.h"
-
-namespace Common {
- class File;
-}
+#include "common/stream.h"
namespace Graphics {
diff --git a/graphics/font.cpp b/graphics/font.cpp
index 0b0405b4b4..0f67899706 100644
--- a/graphics/font.cpp
+++ b/graphics/font.cpp
@@ -513,6 +513,7 @@ int bdf_read_bitmaps(Common::SeekableReadStream &fp, NewFontData* pf) {
}
/* read the next non-comment line, returns buf or NULL if EOF*/
+// TODO: Can we use SeekableReadStream::readLine resp. readLine_NEW instead?
char *bdf_getline(Common::SeekableReadStream &fp, char *buf, int len) {
int c;
char *b;
diff --git a/graphics/iff.cpp b/graphics/iff.cpp
index 514fba9cc0..b3846c5d26 100644
--- a/graphics/iff.cpp
+++ b/graphics/iff.cpp
@@ -219,7 +219,7 @@ void PBMDecoder::readBODY(Common::IFFChunk& chunk) {
switch (_bitmapHeader.pack) {
case 0:
- while (!chunk.eos()) {
+ while (!chunk.hasReadAll()) {
((byte*)_surface->pixels)[si++] = chunk.readByte();
}
break;
@@ -245,7 +245,9 @@ PackBitsReadStream::~PackBitsReadStream() {
}
bool PackBitsReadStream::eos() const {
- return _input->eos() & (_rStoragePos == _wStoragePos);
+ //FIXME: eos definition needs to be changed in parallaction engine
+ // which is the only place where this class is used
+ return _input->eos() && (_rStoragePos == _wStoragePos);
}
uint32 PackBitsReadStream::read(void *dataPtr, uint32 dataSize) {
@@ -291,6 +293,9 @@ void PackBitsReadStream::unpack() {
while (_out < _outEnd && !_input->eos()) {
byteRun = _input->readByte();
+ //FIXME: eos definition needs to be changed in parallaction engine
+ // which is the only place where this class is used
+ //if (_input->eos()) break;
if (byteRun <= 127) {
i = byteRun + 1;
for (j = 0; j < i; j++) {
diff --git a/graphics/imageman.cpp b/graphics/imageman.cpp
index 83ffc40c99..44ac7c9e75 100644
--- a/graphics/imageman.cpp
+++ b/graphics/imageman.cpp
@@ -26,14 +26,13 @@
#include "graphics/imageman.h"
#include "graphics/surface.h"
+#include "common/unzip.h"
+
DECLARE_SINGLETON(Graphics::ImageManager);
namespace Graphics {
-ImageManager::ImageManager() : _surfaces()
-#ifdef USE_ZLIB
-, _archives()
-#endif
-{
+
+ImageManager::ImageManager() {
}
ImageManager::~ImageManager() {
@@ -44,36 +43,21 @@ ImageManager::~ImageManager() {
*pos = 0;
}
_surfaces.clear();
-#ifdef USE_ZLIB
- for (ZipIterator pos2 = _archives.begin(); pos2 != _archives.end(); ++pos2) {
- unzClose(pos2->file);
- }
- _archives.clear();
-#endif
}
bool ImageManager::addArchive(const Common::String &name) {
#ifdef USE_ZLIB
- unzFile newFile = unzOpen(name.c_str());
- if (!newFile)
+ Common::ZipArchive *arch = new Common::ZipArchive(name);
+ if (!arch || !arch->isOpen())
return false;
- Archive arch;
- arch.file = newFile;
- arch.filename = name;
- _archives.push_back(arch);
+ _archives.add(name, Common::ArchivePtr(arch));
#endif
return true;
}
-void ImageManager::remArchive(const Common::String &name) {
+void ImageManager::removeArchive(const Common::String &name) {
#ifdef USE_ZLIB
- for (ZipIterator pos = _archives.begin(); pos != _archives.end(); ++pos) {
- if (pos->filename.compareToIgnoreCase(name) == 0) {
- unzClose(pos->file);
- _archives.erase(pos);
- break;
- }
- }
+ _archives.remove(name);
#endif
}
@@ -86,39 +70,21 @@ bool ImageManager::registerSurface(const Common::String &name, Surface *surf) {
if (!newHandle)
return false;
- if (!surf) {
+ if (!surf)
surf = ImageDecoder::loadFile(name);
- if (!surf) {
+
#ifdef USE_ZLIB
- ZipIterator file = _archives.end();
- for (ZipIterator pos = _archives.begin(); pos != _archives.end(); ++pos) {
- if (unzLocateFile(pos->file, name.c_str(), 2) == UNZ_OK) {
- file = pos;
- break;
- }
- }
-
- if (file == _archives.end())
- return false;
-
- unz_file_info fileInfo;
- unzOpenCurrentFile(file->file);
- unzGetCurrentFileInfo(file->file, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
- uint8 *buffer = new uint8[fileInfo.uncompressed_size];
- assert(buffer);
- unzReadCurrentFile(file->file, buffer, fileInfo.uncompressed_size);
- unzCloseCurrentFile(file->file);
- Common::MemoryReadStream stream(buffer, fileInfo.uncompressed_size);
- surf = ImageDecoder::loadFile(stream);
- delete[] buffer;
-
- if (!surf)
- return false;
-#else
- return false;
-#endif
+ if (!surf) {
+ Common::SeekableReadStream *stream = _archives.openFile(name);
+ if (stream) {
+ surf = ImageDecoder::loadFile(*stream);
+ delete stream;
}
}
+#endif
+
+ if (!surf)
+ return false;
newHandle->surface = surf;
newHandle->name = name;
diff --git a/graphics/imageman.h b/graphics/imageman.h
index c3b56c311f..f555b4c844 100644
--- a/graphics/imageman.h
+++ b/graphics/imageman.h
@@ -26,12 +26,14 @@
#define GRAPHICS_IMAGEMAN_H
#include "common/scummsys.h"
+
+#include "common/archive.h"
#include "common/singleton.h"
#include "common/str.h"
#include "common/list.h"
-#include "common/unzip.h"
namespace Graphics {
+
struct Surface;
class ImageManager : public Common::Singleton<ImageManager> {
@@ -53,7 +55,7 @@ public:
*
* @param name the name of the archive
*/
- void remArchive(const Common::String &name);
+ void removeArchive(const Common::String &name);
/**
* registers a surface to the ImageManager.
@@ -93,20 +95,11 @@ private:
Surface *surface;
};
typedef Common::List<Entry*>::iterator Iterator;
-#ifdef USE_ZLIB
- struct Archive {
- unzFile file;
- Common::String filename;
- };
- typedef Common::List<Archive>::iterator ZipIterator;
-#endif
Iterator searchHandle(const Common::String &name);
Common::List<Entry*> _surfaces;
-#ifdef USE_ZLIB
- Common::List<Archive> _archives;
-#endif
+ Common::SearchSet _archives;
};
} // end of namespace Graphics
diff --git a/graphics/module.mk b/graphics/module.mk
index a44042a044..6a5f7f9e22 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -15,8 +15,9 @@ MODULE_OBJS := \
mpeg_player.o \
primitives.o \
scaler.o \
- scaler/thumbnail.o \
+ scaler/thumbnail_intern.o \
surface.o \
+ thumbnail.o \
surface-keycolored.o
ifndef DISABLE_SCALERS
diff --git a/graphics/scaler.h b/graphics/scaler.h
index 2cf3f66239..95900de412 100644
--- a/graphics/scaler.h
+++ b/graphics/scaler.h
@@ -78,10 +78,22 @@ enum {
extern void createThumbnail(const uint8* src, uint32 srcPitch, uint8* dstPtr, uint32 dstPitch, int width, int height);
/**
- * creates a thumbnail from the current screen (without overlay)
+ * Creates a thumbnail from the current screen (without overlay).
+ *
* @param surf a surface (will always have 16 bpp after this for now)
* @return false if a error occured
*/
-extern bool createThumbnailFromScreen(Graphics::Surface* surf);
+extern bool createThumbnailFromScreen(Graphics::Surface *surf);
+
+/**
+ * Creates a thumbnail from a buffer.
+ *
+ * @param surf destination surface (will always have 16 bpp after this for now)
+ * @param pixels raw pixel data
+ * @param w width
+ * @param h height
+ * @param palette palette in RGB format
+ */
+extern bool createThumbnail(Graphics::Surface *surf, const uint8 *pixels, int w, int h, const uint8 *palette);
#endif
diff --git a/graphics/scaler/hq2x_i386.asm b/graphics/scaler/hq2x_i386.asm
index ed194441ed..f176c340c1 100644
--- a/graphics/scaler/hq2x_i386.asm
+++ b/graphics/scaler/hq2x_i386.asm
@@ -1840,3 +1840,8 @@ FuncTable2:
dd ..@cross8, ..@flag0, ..@flag0, ..@flag0,
dd ..@flag0, ..@flag0, ..@flag0, ..@flag0
+
+%ifidn __OUTPUT_FORMAT__,elf
+section .note.GNU-stack noalloc noexec nowrite progbits
+%endif
+
diff --git a/graphics/scaler/hq3x_i386.asm b/graphics/scaler/hq3x_i386.asm
index e713fdd51a..8ffb2d5aba 100644
--- a/graphics/scaler/hq3x_i386.asm
+++ b/graphics/scaler/hq3x_i386.asm
@@ -2432,3 +2432,8 @@ FuncTable2:
dd ..@cross8, ..@flag0, ..@flag0, ..@flag0,
dd ..@flag0, ..@flag0, ..@flag0, ..@flag0
+
+%ifidn __OUTPUT_FORMAT__,elf
+section .note.GNU-stack noalloc noexec nowrite progbits
+%endif
+
diff --git a/graphics/scaler/thumbnail.cpp b/graphics/scaler/thumbnail_intern.cpp
index f1caa5d2e5..bdfa0ff5f6 100644
--- a/graphics/scaler/thumbnail.cpp
+++ b/graphics/scaler/thumbnail_intern.cpp
@@ -126,70 +126,93 @@ static bool grabScreen565(Graphics::Surface *surf) {
return true;
}
-bool createThumbnailFromScreen(Graphics::Surface* surf) {
- assert(surf);
-
- int screenWidth = g_system->getWidth();
- int screenHeight = g_system->getHeight();
-
- Graphics::Surface screen;
-
- if (!grabScreen565(&screen))
- return false;
+static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) {
+ uint16 width = in.w;
+ uint16 inHeight = in.h;
- uint16 width = screenWidth;
-
- if (screenWidth < 320) {
+ if (width < 320) {
// Special case to handle MM NES (uses a screen width of 256)
width = 320;
// center MM NES screen
Graphics::Surface newscreen;
- newscreen.create(width, screen.h, screen.bytesPerPixel);
+ newscreen.create(width, in.h, in.bytesPerPixel);
- uint8 *dst = (uint8*)newscreen.getBasePtr((320 - screenWidth) / 2, 0);
- uint8 *src = (uint8*)screen.getBasePtr(0, 0);
- uint16 height = screen.h;
+ uint8 *dst = (uint8*)newscreen.getBasePtr((320 - in.w) / 2, 0);
+ const uint8 *src = (uint8*)in.getBasePtr(0, 0);
+ uint16 height = in.h;
while (height--) {
- memcpy(dst, src, screen.pitch);
+ memcpy(dst, src, in.pitch);
dst += newscreen.pitch;
- src += screen.pitch;
+ src += in.pitch;
}
- screen.free();
- screen = newscreen;
- } else if (screenWidth == 720) {
+ in.free();
+ in = newscreen;
+ } else if (width == 720) {
// Special case to handle Hercules mode
width = 640;
- screenHeight = 400;
+ inHeight = 400;
// cut off menu and so on..
Graphics::Surface newscreen;
- newscreen.create(width, 400, screen.bytesPerPixel);
+ newscreen.create(width, 400, in.bytesPerPixel);
- uint8 *dst = (uint8*)newscreen.getBasePtr(0, (400 - 240) / 2);
- uint8 *src = (uint8*)screen.getBasePtr(41, 28);
+ uint8 *dst = (uint8*)in.getBasePtr(0, (400 - 240) / 2);
+ const uint8 *src = (uint8*)in.getBasePtr(41, 28);
for (int y = 0; y < 240; ++y) {
- memcpy(dst, src, 640 * screen.bytesPerPixel);
+ memcpy(dst, src, 640 * in.bytesPerPixel);
dst += newscreen.pitch;
- src += screen.pitch;
+ src += in.pitch;
}
- screen.free();
- screen = newscreen;
+ in.free();
+ in = newscreen;
}
- uint16 newHeight = !(screenHeight % 240) ? kThumbnailHeight2 : kThumbnailHeight1;
+ uint16 newHeight = !(inHeight % 240) ? kThumbnailHeight2 : kThumbnailHeight1;
int gBitFormatBackUp = gBitFormat;
gBitFormat = 565;
- surf->create(kThumbnailWidth, newHeight, sizeof(uint16));
- createThumbnail((const uint8*)screen.pixels, width * sizeof(uint16), (uint8*)surf->pixels, surf->pitch, width, screenHeight);
+ out.create(kThumbnailWidth, newHeight, sizeof(uint16));
+ createThumbnail((const uint8 *)in.pixels, width * sizeof(uint16), (uint8 *)out.pixels, out.pitch, width, inHeight);
gBitFormat = gBitFormatBackUp;
- screen.free();
+ in.free();
return true;
}
+
+bool createThumbnailFromScreen(Graphics::Surface* surf) {
+ assert(surf);
+
+ Graphics::Surface screen;
+
+ if (!grabScreen565(&screen))
+ return false;
+
+ return createThumbnail(*surf, screen);
+}
+
+bool createThumbnail(Graphics::Surface *surf, const uint8 *pixels, int w, int h, const uint8 *palette) {
+ assert(surf);
+
+ Graphics::Surface screen;
+ screen.create(w, h, 2);
+
+ for (uint y = 0; y < screen.h; ++y) {
+ for (uint x = 0; x < screen.w; ++x) {
+ byte r, g, b;
+ r = palette[pixels[y * w + x] * 3];
+ g = palette[pixels[y * w + x] * 3 + 1];
+ b = palette[pixels[y * w + x] * 3 + 2];
+
+ ((uint16 *)screen.pixels)[y * screen.w + x] = RGBToColor<ColorMasks<565> >(r, g, b);
+ }
+ }
+
+ return createThumbnail(*surf, screen);
+}
+
diff --git a/graphics/surface.cpp b/graphics/surface.cpp
index a9f3e75886..263a4fd23b 100644
--- a/graphics/surface.cpp
+++ b/graphics/surface.cpp
@@ -66,6 +66,11 @@ void Surface::free() {
bytesPerPixel = 0;
}
+void Surface::copyFrom(const Surface &surf) {
+ create(surf.w, surf.h, surf.bytesPerPixel);
+ memcpy(pixels, surf.pixels, h * pitch);
+}
+
void Surface::hLine(int x, int y, int x2, uint32 color) {
// Clipping
if (y < 0 || y >= h)
diff --git a/graphics/surface.h b/graphics/surface.h
index ff1ddda695..747bda9a26 100644
--- a/graphics/surface.h
+++ b/graphics/surface.h
@@ -30,7 +30,6 @@
namespace Graphics {
-
/**
* An arbitrary graphics surface, which can be the target (or source) of blit
* operations, font rendering, etc.
@@ -67,6 +66,12 @@ struct Surface {
*/
void free();
+ /**
+ * Copies data from another Surface, this calls *free* on the current surface, to assure
+ * it being clean.
+ */
+ void copyFrom(const Surface &surf);
+
void drawLine(int x0, int y0, int x1, int y1, uint32 color);
void hLine(int x, int y, int x2, uint32 color);
void vLine(int x, int y, int y2, uint32 color);
@@ -76,6 +81,18 @@ struct Surface {
void move(int dx, int dy, int height);
};
+/**
+ * For safe deletion of surface with SharedPtr.
+ * The deleter assures Surface::free is called on
+ * deletion.
+ */
+struct SharedPtrSurfaceDeleter {
+ void operator()(Surface *ptr) {
+ ptr->free();
+ delete ptr;
+ }
+};
+
} // End of namespace Graphics
diff --git a/graphics/thumbnail.cpp b/graphics/thumbnail.cpp
new file mode 100644
index 0000000000..905fea3d93
--- /dev/null
+++ b/graphics/thumbnail.cpp
@@ -0,0 +1,174 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "graphics/thumbnail.h"
+#include "graphics/scaler.h"
+#include "common/endian.h"
+#include "common/system.h"
+
+namespace Graphics {
+
+namespace {
+#define THMB_VERSION 1
+
+struct ThumbnailHeader {
+ uint32 type;
+ uint32 size;
+ byte version;
+ uint16 width, height;
+ byte bpp;
+};
+
+#define ThumbnailHeaderSize (4+4+1+2+2+1)
+
+inline void colorToRGB(uint16 color, uint8 &r, uint8 &g, uint8 &b) {
+ r = (((color >> 11) & 0x1F) << 3);
+ g = (((color >> 5) & 0x3F) << 2);
+ b = ((color&0x1F) << 3);
+}
+
+bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool outputWarnings) {
+ header.type = in.readUint32BE();
+ // We also accept the bad 'BMHT' header here, for the sake of compatibility
+ // with some older savegames which were written incorrectly due to a bug in
+ // ScummVM which wrote the thumb header type incorrectly on LE systems.
+ if (header.type != MKID_BE('THMB') && header.type != MKID_BE('BMHT')) {
+ if (outputWarnings)
+ warning("couldn't find thumbnail header type");
+ return false;
+ }
+
+ header.size = in.readUint32BE();
+ header.version = in.readByte();
+
+ if (header.version > THMB_VERSION) {
+ if (outputWarnings)
+ warning("trying to load a newer thumbnail version: %d instead of %d", header.version, THMB_VERSION);
+ return false;
+ }
+
+ header.width = in.readUint16BE();
+ header.height = in.readUint16BE();
+ header.bpp = in.readByte();
+
+ return true;
+}
+} // end of anonymous namespace
+
+bool checkThumbnailHeader(Common::SeekableReadStream &in) {
+ uint32 position = in.pos();
+ ThumbnailHeader header;
+
+ bool hasHeader = loadHeader(in, header, false);
+
+ in.seek(position, SEEK_SET);
+
+ return hasHeader;
+}
+
+bool skipThumbnailHeader(Common::SeekableReadStream &in) {
+ uint32 position = in.pos();
+ ThumbnailHeader header;
+
+ if (!loadHeader(in, header, false)) {
+ in.seek(position, SEEK_SET);
+ return false;
+ }
+
+ in.seek(header.size - (in.pos() - position), SEEK_CUR);
+ return true;
+}
+
+bool loadThumbnail(Common::SeekableReadStream &in, Graphics::Surface &to) {
+ ThumbnailHeader header;
+
+ if (!loadHeader(in, header, true))
+ return false;
+
+ if (header.bpp != 2) {
+ warning("trying to load thumbnail with unsupported bit depth %d", header.bpp);
+ return false;
+ }
+
+ to.create(header.width, header.height, sizeof(OverlayColor));
+
+ OverlayColor *pixels = (OverlayColor *)to.pixels;
+ for (int y = 0; y < to.h; ++y) {
+ for (int x = 0; x < to.w; ++x) {
+ uint8 r, g, b;
+ colorToRGB(in.readUint16BE(), r, g, b);
+
+ // converting to current OSystem Color
+ *pixels++ = g_system->RGBToColor(r, g, b);
+ }
+ }
+
+ return true;
+}
+
+bool saveThumbnail(Common::WriteStream &out) {
+ Graphics::Surface thumb;
+
+ if (!createThumbnailFromScreen(&thumb)) {
+ warning("Couldn't create thumbnail from screen, aborting thumbnail save");
+ return false;
+ }
+
+ bool success = saveThumbnail(out, thumb);
+ thumb.free();
+
+ return success;
+}
+
+bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb) {
+ if (thumb.bytesPerPixel != 2) {
+ warning("trying to save thumbnail with bpp different than 2");
+ return false;
+ }
+
+ ThumbnailHeader header;
+ header.type = MKID_BE('THMB');
+ header.size = ThumbnailHeaderSize + thumb.w*thumb.h*thumb.bytesPerPixel;
+ header.version = THMB_VERSION;
+ header.width = thumb.w;
+ header.height = thumb.h;
+ header.bpp = thumb.bytesPerPixel;
+
+ out.writeUint32BE(header.type);
+ out.writeUint32BE(header.size);
+ out.writeByte(header.version);
+ out.writeUint16BE(header.width);
+ out.writeUint16BE(header.height);
+ out.writeByte(header.bpp);
+
+ // TODO: for later this shouldn't be casted to uint16...
+ uint16 *pixels = (uint16 *)thumb.pixels;
+ for (uint16 p = 0; p < thumb.w*thumb.h; ++p, ++pixels)
+ out.writeUint16BE(*pixels);
+
+ return true;
+}
+
+} // end of namespace Graphics
+
diff --git a/graphics/thumbnail.h b/graphics/thumbnail.h
new file mode 100644
index 0000000000..0553306519
--- /dev/null
+++ b/graphics/thumbnail.h
@@ -0,0 +1,69 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef GRAPHICS_THUMBNAIL_H
+#define GRAPHICS_THUMBNAIL_H
+
+#include "common/stream.h"
+#include "graphics/surface.h"
+
+namespace Graphics {
+
+/**
+ * Checks for presence of the thumbnail save header.
+ * Seeks automatically back to start position after check.
+ *
+ * @param in stream to check for header
+ */
+bool checkThumbnailHeader(Common::SeekableReadStream &in);
+
+/**
+ * Skips a thumbnail header, if present.
+ *
+ * @param in stream to process
+ */
+bool skipThumbnailHeader(Common::SeekableReadStream &in);
+
+/**
+ * Lodas a thumbnail from the given input stream.
+ * The loaded thumbnail will be automatically converted to the
+ * current overlay pixelformat.
+ */
+bool loadThumbnail(Common::SeekableReadStream &in, Graphics::Surface &to);
+
+/**
+ * Saves a thumbnail to the given write stream.
+ * Automatically creates a thumbnail from screen contents.
+ */
+bool saveThumbnail(Common::WriteStream &out);
+
+/**
+ * Saves a (given) thumbnail to the given write stream.
+ */
+bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb);
+
+} // end of namespace Graphics
+
+#endif
+