From 1876207afb38e4431f017242f5a89eac8aa60b56 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Fri, 8 Feb 2019 14:44:34 +0100 Subject: [PATCH] implement RLE decode --- src/abr.cpp | 31 ++++++++++++++++++++++++++++--- src/abr.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/abr.cpp b/src/abr.cpp index 23f6037..9369039 100644 --- a/src/abr.cpp +++ b/src/abr.cpp @@ -134,14 +134,39 @@ std::shared_ptr ABR::parse_vmem() auto rect = rrect(); auto depth2 = ru16(); // again? auto compression = ru8(); // 1 = zip - if (compression != 0 || depth != 8) + if (depth != 8) + { + printf("unsupported depth %d bits\n", depth); + skip(length - 23); + continue; + } + if (compression == 0) + { + int data_size = (depth >> 3) * rect.area(); + ret->channels.emplace_back(depth, rect, compression, rraw(data_size)); + } + else if (compression == 1) + { + auto height = rect.height(); + // contain the compressed length of each scanline + std::vector scanlines; + scanlines.reserve(height); + for (int i = 0; i < height; i++) + scanlines.push_back(ru16()); + std::vector raw; + for (auto sl : scanlines) + { + auto decoded = rrle(sl); + raw.insert(raw.end(), decoded.begin(), decoded.end()); + } + ret->channels.emplace_back(depth, rect, compression, raw); + } + else { printf("unsupported compression mode %d\n", compression); skip(length - 23); continue; } - int data_size = (depth >> 3) * rect.area(); - ret->channels.emplace_back(depth, rect, compression, rraw(data_size)); } snap(); return ret; diff --git a/src/abr.h b/src/abr.h index 2bfb00a..2f8f2f1 100644 --- a/src/abr.h +++ b/src/abr.h @@ -85,6 +85,38 @@ public: skip(bytes); return ret; } + std::vector rrle(size_t encoded_bytes) + { + std::vector data; + int32_t n; + for (int j = 0; j < encoded_bytes;) + { + n = ri8(); + j++; + // force sign + if (n >= 128) + n -= 256; // can this even happen? + // copy the following char -n + 1 times + if (n < 0) + { + // NOP + if (n == -128) + continue; + n = -n + 1; + + j++; + for (int c = 0; c < n; c++) + data.push_back(ru8()); + } + else + { + // read the following n + 1 chars (no compr) + for (int c = 0; c < n + 1; c++, j++) + data.push_back(ru8()); + } + } + return data; + } protected: template inline T align4(T x) { return ((x - T{1}) & (~(T{3}))) + T{4}; } template T read()