diff --git a/image/pict.cpp b/image/pict.cpp index 392a6f298b3..d4c79b1dadb 100644 --- a/image/pict.cpp +++ b/image/pict.cpp @@ -68,6 +68,9 @@ void PICTDecoder::setupOpcodesCommon() { OPCODE(0x0011, o_versionOp, "VersionOp"); OPCODE(0x001E, o_nop, "DefHilite"); OPCODE(0x0028, o_longText, "LongText"); + OPCODE(0x0091, o_bitsRgn, "BitsRgn"); + OPCODE(0x0099, o_packBitsRgn, "PackBitsRgn"); + OPCODE(0x00A0, o_shortComment, "ShortComment"); OPCODE(0x00A1, o_longComment, "LongComment"); OPCODE(0x00FF, o_opEndPic, "OpEndPic"); OPCODE(0x0C00, o_headerOp, "HeaderOp"); @@ -161,6 +164,20 @@ void PICTDecoder::o_longText(Common::SeekableReadStream &stream) { stream.skip(stream.readByte()); } +void PICTDecoder::o_bitsRgn(Common::SeekableReadStream &stream) { + // Copy unpacked data with clipped region (8bpp or lower) + unpackBitsRgn(stream, false); +} + +void PICTDecoder::o_packBitsRgn(Common::SeekableReadStream &stream) { + unpackBitsRgn(stream, true); +} + +void PICTDecoder::o_shortComment(Common::SeekableReadStream &stream) { + // Ignore + stream.readUint16BE(); +} + void PICTDecoder::o_longComment(Common::SeekableReadStream &stream) { // Ignore stream.readUint16BE(); @@ -452,6 +469,89 @@ void PICTDecoder::unpackBitsRect(Common::SeekableReadStream &stream, bool withPa delete[] buffer; } +void PICTDecoder::unpackBitsRgn(Common::SeekableReadStream &stream, bool compressed) { + int x1, x2, y1, y2; + int size = 0; + stream.skip(2); // Skip rowBytes + + if (!_outputSurface) { + _outputSurface = new Graphics::Surface(); + _outputSurface->create(_imageRect.width(), _imageRect.height(), Graphics::PixelFormat::createFormatCLUT8()); + } + + y1 = stream.readSint16BE(); + x1 = stream.readSint16BE(); + y2 = stream.readSint16BE(); + x2 = stream.readSint16BE(); + + stream.skip(8); // Skip srcRect + stream.skip(8); // Skip dstRect + stream.skip(2); // Skip mode + stream.skip(stream.readUint16BE() - 2); + + int x = 0; + int y = 0; + byte value; + + if (!compressed) { + for (y = y1; y < y2 && y < _imageRect.height(); y++) { + byte b = stream.readByte(); + byte bit = 0x80; + + for (x = x1; x < x2 && x < _imageRect.width(); x++) { + if (b & bit) + _outputSurface->setPixel(x, y, 0x0F); + else + _outputSurface->setPixel(x, y, 0x00); + + bit >>= 1; + + if (bit == 0) { + b = stream.readByte(); + bit = 0x80; + } + } + } + } else { + for (y = y1; y < y2 && y < _imageRect.height(); y++) { + x = x1; + size = stream.readByte(); + + while (size > 0) { + byte count = stream.readByte(); + size--; + + bool repeat; + + if (count >= 128) { + // Repeat value + count = 256 - count; + repeat = true; + value = stream.readByte(); + size--; + } else { + // Copy values + repeat = false; + value = 0; + } + + for (int j = 0; j <= count; j++) { + if (!repeat) { + value = stream.readByte(); + size--; + } + for (int k = 7; k >= 0 && x < x2 && x < _imageRect.width(); k--, x++) { + if (value & (1 << k)) + _outputSurface->setPixel(x, y, 0x0F); + else + _outputSurface->setPixel(x, y, 0x00); + } + } + } + } + } +} + void PICTDecoder::unpackBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bitsPerPixel, byte bytesPerPixel) { uint32 dataDecoded = 0; byte bytesPerDecode = (bytesPerPixel == 2) ? 2 : 1; diff --git a/image/pict.h b/image/pict.h index bb0c1c4405e..0a38a96bc94 100644 --- a/image/pict.h +++ b/image/pict.h @@ -95,6 +95,7 @@ private: int _version; // Utility Functions + void unpackBitsRgn(Common::SeekableReadStream &stream, bool compressed); void unpackBitsRect(Common::SeekableReadStream &stream, bool withPalette); void unpackBitsLine(byte *out, uint32 length, Common::SeekableReadStream *stream, byte bitsPerPixel, byte bytesPerPixel); void skipBitsRect(Common::SeekableReadStream &stream, bool withPalette); @@ -123,6 +124,9 @@ private: DECLARE_OPCODE(o_txRatio); DECLARE_OPCODE(o_versionOp); DECLARE_OPCODE(o_longText); + DECLARE_OPCODE(o_bitsRgn); + DECLARE_OPCODE(o_packBitsRgn); + DECLARE_OPCODE(o_shortComment); DECLARE_OPCODE(o_longComment); DECLARE_OPCODE(o_opEndPic); DECLARE_OPCODE(o_headerOp);