diff --git a/Common/ac/spritefile.cpp b/Common/ac/spritefile.cpp index 333824d5ce..77887458d0 100644 --- a/Common/ac/spritefile.cpp +++ b/Common/ac/spritefile.cpp @@ -404,7 +404,7 @@ HError SpriteFile::LoadSprite(sprkey_t index, Common::Bitmap *&sprite) ReadSprHeader(hdr, _stream.get(), _version, _compress); if (hdr.BPP == 0) return HError::None(); // empty slot, this is normal int bpp = hdr.BPP, w = hdr.Width, h = hdr.Height; - Bitmap *image = BitmapHelper::CreateBitmap(w, h, bpp * 8); + std::unique_ptr image(BitmapHelper::CreateBitmap(w, h, bpp * 8)); if (image == nullptr) { return new Error(String::FromFormat("LoadSprite: failed to allocate bitmap %d (%dx%d%d).", @@ -434,22 +434,28 @@ HError SpriteFile::LoadSprite(sprkey_t index, Common::Bitmap *&sprite) (uint32_t)_stream->ReadInt32() : (w * h * bpp); if (hdr.Compress != kSprCompress_None) { + // TODO: rewrite this to only make a choice once the SpriteFile is initialized + // and use either function ptr or a decompressing stream class object if (in_data_size == 0) { - delete image; return new Error(String::FromFormat("LoadSprite: bad compressed data for sprite %d.", index)); } + bool result; switch (hdr.Compress) { - case kSprCompress_RLE: rle_decompress(im_data.Buf, im_data.Size, im_data.BPP, _stream.get()); + case kSprCompress_RLE: result = rle_decompress(im_data.Buf, im_data.Size, im_data.BPP, _stream.get()); break; - case kSprCompress_LZW: lzw_decompress(im_data.Buf, im_data.Size, im_data.BPP, _stream.get(), in_data_size); + case kSprCompress_LZW: result = lzw_decompress(im_data.Buf, im_data.Size, im_data.BPP, _stream.get(), in_data_size); break; - case kSprCompress_Deflate: inflate_decompress(im_data.Buf, im_data.Size, im_data.BPP, _stream.get(), in_data_size); + case kSprCompress_Deflate: result = inflate_decompress(im_data.Buf, im_data.Size, im_data.BPP, _stream.get(), in_data_size); break; - default: assert(!"Unsupported compression type!"); break; + default: assert(!"Unsupported compression type!"); result = false; break; } // TODO: test that not more than data_size was read! + if (!result) + { + return new Error(String::FromFormat("LoadSprite: failed to decompress pixel array for sprite %d.", index)); + } } // Otherwise (no compression) read directly else @@ -470,10 +476,10 @@ HError SpriteFile::LoadSprite(sprkey_t index, Common::Bitmap *&sprite) // Finally revert storage options if (pal_bpp > 0) { - UnpackIndexedBitmap(image, im_data.Buf, im_data.Size, palette, hdr.PalCount); + UnpackIndexedBitmap(image.get(), im_data.Buf, im_data.Size, palette, hdr.PalCount); } - sprite = image; + sprite = image.release(); // FIXME: pass unique_ptr in this function _curPos = index + 1; // mark correct pos return HError::None(); } @@ -693,20 +699,23 @@ void SpriteFileWriter::WriteBitmap(Bitmap *image) SpriteCompression compress = kSprCompress_None; if (_compress != kSprCompress_None) { + // TODO: rewrite this to only make a choice once the SpriteFile is initialized + // and use either function ptr or a decompressing stream class object compress = _compress; VectorStream mems(_membuf, kStream_Write); + bool result; switch (compress) { - case kSprCompress_RLE: rle_compress(im_data.Buf, im_data.Size, im_data.BPP, &mems); + case kSprCompress_RLE: result = rle_compress(im_data.Buf, im_data.Size, im_data.BPP, &mems); break; - case kSprCompress_LZW: lzw_compress(im_data.Buf, im_data.Size, im_data.BPP, &mems); + case kSprCompress_LZW: result = lzw_compress(im_data.Buf, im_data.Size, im_data.BPP, &mems); break; - case kSprCompress_Deflate: deflate_compress(im_data.Buf, im_data.Size, im_data.BPP, &mems); + case kSprCompress_Deflate: result = deflate_compress(im_data.Buf, im_data.Size, im_data.BPP, &mems); break; - default: assert(!"Unsupported compression type!"); break; + default: assert(!"Unsupported compression type!"); result = false; break; } // mark to write as a plain byte array - im_data = ImBufferCPtr(&_membuf[0], _membuf.size(), 1); + im_data = result ? ImBufferCPtr(&_membuf[0], _membuf.size(), 1) : ImBufferCPtr(); } // Write the final data diff --git a/Common/util/compress.cpp b/Common/util/compress.cpp index 59d489cfff..cc959b02a8 100644 --- a/Common/util/compress.cpp +++ b/Common/util/compress.cpp @@ -11,12 +11,11 @@ // http://www.opensource.org/licenses/artistic-license-2.0.php // //============================================================================= - #include "util/compress.h" #include #include -#include #include +#include #include "ac/common.h" // quit, update_polled_stuff #include "gfx/bitmap.h" #include "util/lzw.h" @@ -24,7 +23,6 @@ #if AGS_PLATFORM_ENDIAN_BIG #include "util/bbop.h" #endif -#include using namespace AGS::Common; @@ -149,8 +147,6 @@ static int cunpackbitl(uint8_t *line, size_t size, Stream *in) while (n < size) { int ix = in->ReadByte(); // get index byte - if (in->HasErrors()) - break; signed char cx = ix; if (cx == -128) @@ -178,7 +174,7 @@ static int cunpackbitl(uint8_t *line, size_t size, Stream *in) } } - return in->HasErrors() ? -1 : 0; + return 0; } static int cunpackbitl16(uint16_t *line, size_t size, Stream *in) @@ -187,8 +183,6 @@ static int cunpackbitl16(uint16_t *line, size_t size, Stream *in) while (n < size) { int ix = in->ReadByte(); // get index byte - if (in->HasErrors()) - break; signed char cx = ix; if (cx == -128) @@ -216,7 +210,7 @@ static int cunpackbitl16(uint16_t *line, size_t size, Stream *in) } } - return in->HasErrors() ? -1 : 0; + return 0; } static int cunpackbitl32(uint32_t *line, size_t size, Stream *in) @@ -225,8 +219,6 @@ static int cunpackbitl32(uint32_t *line, size_t size, Stream *in) while (n < size) { int ix = in->ReadByte(); // get index byte - if (in->HasErrors()) - break; signed char cx = ix; if (cx == -128) @@ -254,10 +246,10 @@ static int cunpackbitl32(uint32_t *line, size_t size, Stream *in) } } - return in->HasErrors() ? -1 : 0; + return 0; } -void rle_compress(const uint8_t *data, size_t data_sz, int image_bpp, Stream *out) +bool rle_compress(const uint8_t *data, size_t data_sz, int image_bpp, Stream *out) { switch (image_bpp) { @@ -266,9 +258,10 @@ void rle_compress(const uint8_t *data, size_t data_sz, int image_bpp, Stream *ou case 4: cpackbitl32(reinterpret_cast(data), data_sz / sizeof(uint32_t), out); break; default: assert(0); break; } + return true; } -void rle_decompress(uint8_t *data, size_t data_sz, int image_bpp, Stream *in) +bool rle_decompress(uint8_t *data, size_t data_sz, int image_bpp, Stream *in) { switch (image_bpp) { @@ -277,6 +270,7 @@ void rle_decompress(uint8_t *data, size_t data_sz, int image_bpp, Stream *in) case 4: cunpackbitl32(reinterpret_cast(data), data_sz / sizeof(uint32_t), in); break; default: assert(0); break; } + return true; } void save_rle_bitmap8(Stream *out, const Bitmap *bmp, const RGB (*pal)[256]) @@ -342,29 +336,29 @@ void skip_rle_bitmap8(Stream *in) // LZW //----------------------------------------------------------------------------- -void lzw_compress(const uint8_t *data, size_t data_sz, int /*image_bpp*/, Stream *out) +bool lzw_compress(const uint8_t *data, size_t data_sz, int /*image_bpp*/, Stream *out) { // LZW algorithm that we use fails on sequence less than 16 bytes. if (data_sz < 16) { out->Write(data, data_sz); - return; + return true; } MemoryStream mem_in(data, data_sz); - lzwcompress(&mem_in, out); + return lzwcompress(&mem_in, out); } -void lzw_decompress(uint8_t *data, size_t data_sz, int /*image_bpp*/, Stream *in, size_t in_sz) +bool lzw_decompress(uint8_t *data, size_t data_sz, int /*image_bpp*/, Stream *in, size_t in_sz) { // LZW algorithm that we use fails on sequence less than 16 bytes. if (data_sz < 16) { in->Read(data, data_sz); - return; + return true; } std::vector in_buf(in_sz); in->Read(in_buf.data(), in_sz); - lzwexpand(in_buf.data(), in_sz, data, data_sz); + return lzwexpand(in_buf.data(), in_sz, data, data_sz); } void save_lzw(Stream *out, const Bitmap *bmpp, const RGB (*pal)[256]) @@ -458,14 +452,11 @@ bool z_deflate(Stream* input, Stream* output) { int ret = deflateInit(&stream, Z_DEFAULT_COMPRESSION); if (ret != Z_OK) { - std::cerr << "Error initializing compression" << std::endl; return false; } - stream.data_type = 0; - - char inbuf[1024]; - char outbuf[1024]; + uint8_t inbuf[1024]; + uint8_t outbuf[1024]; stream.avail_in = input->Read(inbuf, sizeof(inbuf)); while (stream.avail_in > 0) { @@ -485,21 +476,15 @@ bool z_deflate(Stream* input, Stream* output) { } (void)deflateEnd(&stream); - return true; } bool z_inflate(const uint8_t* src, size_t src_sz, uint8_t* dst, size_t dst_sz) { z_stream stream; - stream.zalloc = Z_NULL; - stream.zfree = Z_NULL; - stream.opaque = Z_NULL; - stream.avail_in = 0; - stream.next_in = Z_NULL; + memset(&stream, 0, sizeof(stream)); int ret = inflateInit(&stream); if (ret != Z_OK) { - std::cerr << "Error initializing decompression" << std::endl; return false; } @@ -515,7 +500,6 @@ bool z_inflate(const uint8_t* src, size_t src_sz, uint8_t* dst, size_t dst_sz) { case Z_DATA_ERROR: case Z_MEM_ERROR: case Z_BUF_ERROR: - std::cerr << "Error decompressing data" << std::endl; (void)inflateEnd(&stream); return false; default: @@ -525,19 +509,18 @@ bool z_inflate(const uint8_t* src, size_t src_sz, uint8_t* dst, size_t dst_sz) { } while (stream.avail_out > 0); (void)inflateEnd(&stream); - return true; } -void deflate_compress(const uint8_t* data, size_t data_sz, int /*image_bpp*/, Stream* out) +bool deflate_compress(const uint8_t* data, size_t data_sz, int /*image_bpp*/, Stream* out) { MemoryStream mem_in(data, data_sz); - z_deflate(&mem_in, out); + return z_deflate(&mem_in, out); } -void inflate_decompress(uint8_t* data, size_t data_sz, int /*image_bpp*/, Stream* in, size_t in_sz) +bool inflate_decompress(uint8_t* data, size_t data_sz, int /*image_bpp*/, Stream* in, size_t in_sz) { std::vector in_buf(in_sz); in->Read(in_buf.data(), in_sz); - z_inflate(in_buf.data(), in_sz, data, data_sz); + return z_inflate(in_buf.data(), in_sz, data, data_sz); } diff --git a/Common/util/compress.h b/Common/util/compress.h index e5c9551e78..fbb64d4717 100644 --- a/Common/util/compress.h +++ b/Common/util/compress.h @@ -24,8 +24,8 @@ namespace AGS { namespace Common { class Stream; class Bitmap; } } using namespace AGS; // FIXME later // RLE compression -void rle_compress(const uint8_t *data, size_t data_sz, int image_bpp, Common::Stream *out); -void rle_decompress(uint8_t *data, size_t data_sz, int image_bpp, Common::Stream *in); +bool rle_compress(const uint8_t *data, size_t data_sz, int image_bpp, Common::Stream *out); +bool rle_decompress(uint8_t *data, size_t data_sz, int image_bpp, Common::Stream *in); // Packs a 8-bit bitmap using RLE compression, and writes into stream along with the palette void save_rle_bitmap8(Common::Stream *out, const Common::Bitmap *bmp, const RGB (*pal)[256] = nullptr); // Reads a 8-bit bitmap with palette from the stream and unpacks from RLE @@ -34,15 +34,15 @@ std::unique_ptr load_rle_bitmap8(Common::Stream *in, RGB (*pal)[ void skip_rle_bitmap8(Common::Stream *in); // LZW compression -void lzw_compress(const uint8_t *data, size_t data_sz, int image_bpp, Common::Stream *out); -void lzw_decompress(uint8_t *data, size_t data_sz, int image_bpp, Common::Stream *in, size_t in_sz); +bool lzw_compress(const uint8_t *data, size_t data_sz, int image_bpp, Common::Stream *out); +bool lzw_decompress(uint8_t *data, size_t data_sz, int image_bpp, Common::Stream *in, size_t in_sz); // Saves bitmap with an optional palette compressed by LZW void save_lzw(Common::Stream *out, const Common::Bitmap *bmpp, const RGB (*pal)[256] = nullptr); // Loads bitmap decompressing std::unique_ptr load_lzw(Common::Stream *in, int dst_bpp, RGB (*pal)[256] = nullptr); // Deflate compression -void deflate_compress(const uint8_t* data, size_t data_sz, int image_bpp, Common::Stream* out); -void inflate_decompress(uint8_t* data, size_t data_sz, int image_bpp, Common::Stream* in, size_t in_sz); +bool deflate_compress(const uint8_t* data, size_t data_sz, int image_bpp, Common::Stream* out); +bool inflate_decompress(uint8_t* data, size_t data_sz, int image_bpp, Common::Stream* in, size_t in_sz); #endif // __AC_COMPRESS_H