8 #include <fmt/format.h>
20 stream = std::move(streamPtr);
21 if (stream && stream->good()) {
22 return extractHeaders();
27 bool DC6::extractHeaders()
29 static_assert(std::is_trivially_copyable<Header>(),
"DC6::Header must be trivially copyable");
30 static_assert(
sizeof(Header) == 6 *
sizeof(uint32_t),
"DC6::Header struct needs to be packed");
31 stream->read(&header,
sizeof(header));
32 if (stream->fail())
return false;
35 frameHeaders.resize(framesNumber);
37 framePointers.resize(framesNumber);
38 stream->read(framePointers.data(),
sizeof(uint32_t) * framesNumber);
39 if (stream->fail())
return false;
41 for (
size_t i = 0; i < framesNumber; ++i)
43 FrameHeader& frameHeader = frameHeaders[i];
44 stream->seek(framePointers[i], IStream::beg);
46 static_assert(std::is_trivially_copyable<FrameHeader>(),
47 "DC6::FrameHeader must be trivially copyable");
48 static_assert(
sizeof(FrameHeader) == 8 *
sizeof(uint32_t),
49 "DC6::FrameHeader struct needs to be packed");
50 stream->read(&frameHeader,
sizeof(frameHeader));
51 if (stream->fail())
return false;
58 const FrameHeader& fHeader = frameHeaders[frameNumber];
60 std::vector<uint8_t> data(static_cast<size_t>(fHeader.
width * fHeader.
height));
68 assert(stream !=
nullptr);
69 stream->seek(framePointers[frameNumber] +
sizeof(
FrameHeader), IStream::beg);
70 const FrameHeader& fHeader = frameHeaders[frameNumber];
78 int x = 0, y = fHeader.
height - 1;
80 while (rawIndex < fHeader.
length)
82 int val = stream->getc();
84 if (stream->eof())
return false;
85 uint8_t chunkSize =
static_cast<uint8_t
>(val);
86 if (chunkSize == 0x80)
91 else if (chunkSize & 0x80)
93 x += chunkSize & 0x7F;
97 assert(chunkSize + x <= fHeader.
width);
98 stream->read(data + x + fHeader.
width * y, chunkSize);
99 rawIndex += chunkSize;
101 if (stream->eof())
return false;
104 assert(fHeader.
length == rawIndex);
108 void DC6::exportToPPM(
const char* ppmFilenameBase,
const Palette& palette)
const
110 for (
size_t dir = 0; dir < header.
directions; ++dir)
112 for (
size_t frameInDir = 0; frameInDir < header.
framesPerDir; ++frameInDir)
116 Utils::exportToPPM(fmt::format(
"{}{}-{}.ppm", ppmFilenameBase, dir, frameInDir).c_str(),
117 data.data(), frameHeaders[frame].width, frameHeaders[frame].height,
std::vector< uint8_t > decompressFrame(size_t frameNumber) const
Decompress the given frame.
bool initDecoder(StreamPtr &&streamPtr)
Start decoding the stream and preparing data.
bool decompressFrameIn(size_t frameNumber, uint8_t *data) const
Same as decompressFrame but will output the data in a given buffer.
Helper to load a Diablo 2 palette (.pal/.dat format)