diff options
author | md5 | 2011-05-13 18:49:14 +0300 |
---|---|---|
committer | md5 | 2011-05-13 18:49:14 +0300 |
commit | 3ec466853aabad51423c2bf15a83ba7a89c5b73a (patch) | |
tree | aa27aeb53d8a50f75a69f1b1043c0a0706b708e5 /engines/sword25/gfx/image/renderedimage.cpp | |
parent | bd2bfe85c97189e72199e5d0554ec4bd192a80b2 (diff) | |
download | scummvm-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.cpp | 88 |
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; } |