bool DIBDecoder::loadStream(Common::SeekableReadStream &stream) { uint32 headerSize = stream.readUint32LE(); if (headerSize != 40) return false; uint32 width = stream.readUint32LE(); uint32 height = stream.readUint32LE(); stream.readUint16LE(); // planes uint16 bitsPerPixel = stream.readUint16LE(); uint32 compression = stream.readUint32BE(); uint32 imageSize = stream.readUint32LE(); /* uint32 pixelsPerMeterX = */ stream.readUint32LE(); /* uint32 pixelsPerMeterY = */ stream.readUint32LE(); _paletteColorCount = stream.readUint32LE(); /* uint32 colorsImportant = */ stream.readUint32LE(); _paletteColorCount = (_paletteColorCount == 0) ? 255: _paletteColorCount; uint16 imageRawSize = stream.size() - 40; Common::SeekableSubReadStream subStream(&stream, 40, stream.size()); _codec = Image::createBitmapCodec(compression, width, height, bitsPerPixel); if (!_codec) return false; _surface = _codec->decodeFrame(subStream); return true; }
GTEST_TEST(SeekableSubReadStreamEndian, streamEndianBE) { static const byte data[4] = { 0x12, 0x34, 0x56, 0x78 }; Common::MemoryReadStream stream(data); Common::SeekableSubReadStreamEndian subStream(&stream, 0, stream.size(), true); EXPECT_EQ(subStream.readUint32(), 305419896); EXPECT_THROW(subStream.readUint32(), Common::Exception); }
std::size_t Parse(const Binary::Container& rawData, ImageVisitor& visitor) { SourceStream stream(rawData); try { const RawHeader& header = stream.Get<RawHeader>(); const uint_t id = fromLE(header.ID); Require(id == ID_OLD || id == ID_NEW); Require(header.Sequence == 0); Require(Math::InRange<uint_t>(header.Sides, MIN_SIDES_COUNT, MAX_SIDES_COUNT)); if (header.HasComment()) { const RawComment& comment = stream.Get<RawComment>(); if (const std::size_t size = fromLE(comment.Size)) { stream.GetData(size); } } const bool compressedData = id == ID_NEW; const bool newCompression = header.Version > 20; if (compressedData) { if (!newCompression) { Dbg("Old compression is not supported."); return 0; } const std::size_t packedSize = rawData.Size() - sizeof(header); const Binary::Container::Ptr packed = rawData.GetSubcontainer(sizeof(header), packedSize); if (const Formats::Packed::Container::Ptr fullDecoded = Formats::Packed::Lha::DecodeRawDataAtLeast(*packed, COMPRESSION_ALGORITHM, MAX_IMAGE_SIZE)) { SourceStream subStream(*fullDecoded); ParseSectors(subStream, visitor); const std::size_t usedInPacked = subStream.GetOffset(); Dbg("Used %1% bytes in packed stream", usedInPacked); if (const Formats::Packed::Container::Ptr decoded = Formats::Packed::Lha::DecodeRawDataAtLeast(*packed, COMPRESSION_ALGORITHM, usedInPacked)) { const std::size_t usedSize = decoded->PackedSize(); return sizeof(header) + usedSize; } } Dbg("Failed to decode lha stream"); return 0; } else { ParseSectors(stream, visitor); } return stream.GetOffset(); } catch (const std::exception&) { return 0; } }
GTEST_TEST(SubReadStream, fromMem) { static const byte data[5] = { 0x12, 0x34, 0x56, 0x78, 0x90 }; Common::MemoryReadStream stream(data); stream.seek(1); Common::SubReadStream subStream(&stream, 3); byte readData[4] = { 0 }; const size_t readCount = subStream.read(readData, 4); EXPECT_EQ(readCount, 3); EXPECT_TRUE(subStream.eos()); EXPECT_EQ(readData[0], data[1]); EXPECT_EQ(readData[1], data[2]); EXPECT_EQ(readData[2], data[3]); }
Common::SeekableReadStream *StuffItArchive::createReadStreamForMember(const Common::String &name) const { if (!_stream || !_map.contains(name)) return 0; const FileEntry &entry = _map[name]; if (entry.compression & 0xF0) error("Unhandled StuffIt encryption"); Common::SeekableSubReadStream subStream(_stream, entry.offset, entry.offset + entry.compressedSize); // We currently only support type 14 compression switch (entry.compression) { case 14: // Installer return decompress14(&subStream, entry.uncompressedSize); default: error("Unhandled StuffIt compression %d", entry.compression); } return 0; }