aboutsummaryrefslogtreecommitdiff
path: root/engines/sword25/gfx/image/renderedimage.cpp
diff options
context:
space:
mode:
authormd52011-05-13 18:49:14 +0300
committermd52011-05-13 18:49:14 +0300
commit3ec466853aabad51423c2bf15a83ba7a89c5b73a (patch)
treeaa27aeb53d8a50f75a69f1b1043c0a0706b708e5 /engines/sword25/gfx/image/renderedimage.cpp
parentbd2bfe85c97189e72199e5d0554ec4bd192a80b2 (diff)
downloadscummvm-rg350-3ec466853aabad51423c2bf15a83ba7a89c5b73a.tar.gz
scummvm-rg350-3ec466853aabad51423c2bf15a83ba7a89c5b73a.tar.bz2
scummvm-rg350-3ec466853aabad51423c2bf15a83ba7a89c5b73a.zip
SWORD25: Replaced the PNG thumbnail encoding code, used in saved games
- Savegame thumbnails are now created using a flat image format, instead of PNG. This allows us to remove the PNG encoding code used in the engine. Note that the saved games we create cannot be used with the original engine anyway, so this change does not break savegame compatibility with the original game (it's already broken). - Compatibility is preserved with older saved games that were made with ScummVM. - Moved the embedded thumbnail reading code out of the PNG loader class, to stop it from needlessly checking every PNG file. - With this change, libpng is no longer required for the sword25 engine
Diffstat (limited to 'engines/sword25/gfx/image/renderedimage.cpp')
-rw-r--r--engines/sword25/gfx/image/renderedimage.cpp88
1 files changed, 78 insertions, 10 deletions
diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp
index ba858e88d4..44d32f03f7 100644
--- a/engines/sword25/gfx/image/renderedimage.cpp
+++ b/engines/sword25/gfx/image/renderedimage.cpp
@@ -54,6 +54,75 @@ static Common::String generateSavegameFilename(uint slotID) {
// CONSTRUCTION / DESTRUCTION
// -----------------------------------------------------------------------------
+/**
+ * Load a NULL-terminated string from the given stream.
+ */
+static Common::String loadString(Common::SeekableReadStream &in, uint maxSize = 999) {
+ Common::String result;
+
+ while (!in.eos() && (result.size() < maxSize)) {
+ char ch = (char)in.readByte();
+ if (ch == '\0')
+ break;
+
+ result += ch;
+ }
+
+ return result;
+}
+
+static byte *readSavegameThumbnail(const Common::String &filename, uint &fileSize, bool &isPNG) {
+ byte *pFileData;
+ Common::SaveFileManager *sfm = g_system->getSavefileManager();
+ int slotNum = atoi(filename.c_str() + filename.size() - 3);
+ Common::InSaveFile *file = sfm->openForLoading(generateSavegameFilename(slotNum));
+
+ // Seek to the actual PNG image
+ loadString(*file); // Marker (BS25SAVEGAME)
+ loadString(*file); // Version
+ loadString(*file); // Description
+ uint32 compressedGamedataSize = atoi(loadString(*file).c_str());
+ loadString(*file); // Uncompressed game data size
+ file->skip(compressedGamedataSize); // Skip the game data and move to the thumbnail itself
+ uint32 thumbnailStart = file->pos();
+
+ fileSize = file->size() - thumbnailStart;
+
+ // Check if the thumbnail is in our own format, or a PNG file.
+ uint32 header = file->readUint32BE();
+ isPNG = (header != MKTAG('S','C','R','N'));
+ file->seek(-4, SEEK_CUR);
+
+ pFileData = new byte[fileSize];
+ file->read(pFileData, fileSize);
+ delete file;
+
+ return pFileData;
+}
+
+// TODO: Move this method into a more generic image loading class, together with the PNG reading code
+static bool decodeThumbnail(const byte *pFileData, uint fileSize, byte *&pUncompressedData, int &width, int &height, int &pitch) {
+ const byte *src = pFileData + 4; // skip header
+ width = READ_LE_UINT16(src); src += 2;
+ height = READ_LE_UINT16(src); src += 2;
+ pitch = width * 4;
+
+ uint32 totalSize = pitch * height;
+ pUncompressedData = new byte[totalSize];
+ uint32 *dst = (uint32 *)pUncompressedData; // treat as uint32, for pixelformat output
+ const Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24);
+ byte r, g, b;
+
+ for (uint32 i = 0; i < totalSize / 4; i++) {
+ r = *src++;
+ g = *src++;
+ b = *src++;
+ *dst++ = format.RGBToColor(r, g, b);
+ }
+
+ return true;
+}
+
RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
_data(0),
_width(0),
@@ -69,15 +138,10 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
byte *pFileData;
uint fileSize;
+ bool isPNG = true;
+
if (filename.hasPrefix("/saves")) {
- // A savegame thumbnail
- Common::SaveFileManager *sfm = g_system->getSavefileManager();
- int slotNum = atoi(filename.c_str() + filename.size() - 3);
- Common::InSaveFile *file = sfm->openForLoading(generateSavegameFilename(slotNum));
- fileSize = file->size();
- pFileData = new byte[fileSize];
- file->read(pFileData, fileSize);
- delete file;
+ pFileData = readSavegameThumbnail(filename, fileSize, isPNG);
} else {
pFileData = pPackage->getFile(filename, &fileSize);
}
@@ -98,7 +162,12 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
// Uncompress the image
int pitch;
- if (!PNGLoader::decodeImage(pFileData, fileSize, _data, _width, _height, pitch)) {
+ if (isPNG)
+ result = PNGLoader::decodeImage(pFileData, fileSize, _data, _width, _height, pitch);
+ else
+ result = decodeThumbnail(pFileData, fileSize, _data, _width, _height, pitch);
+
+ if (!result) {
error("Could not decode image.");
delete[] pFileData;
return;
@@ -109,7 +178,6 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
_doCleanup = true;
- result = true;
return;
}