implement RLE decode
This commit is contained in:
31
src/abr.cpp
31
src/abr.cpp
@@ -134,14 +134,39 @@ std::shared_ptr<ABR::Image> ABR::parse_vmem()
|
|||||||
auto rect = rrect();
|
auto rect = rrect();
|
||||||
auto depth2 = ru16(); // again?
|
auto depth2 = ru16(); // again?
|
||||||
auto compression = ru8(); // 1 = zip
|
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<uint16_t> scanlines;
|
||||||
|
scanlines.reserve(height);
|
||||||
|
for (int i = 0; i < height; i++)
|
||||||
|
scanlines.push_back(ru16());
|
||||||
|
std::vector<uint8_t> 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);
|
printf("unsupported compression mode %d\n", compression);
|
||||||
skip(length - 23);
|
skip(length - 23);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int data_size = (depth >> 3) * rect.area();
|
|
||||||
ret->channels.emplace_back(depth, rect, compression, rraw(data_size));
|
|
||||||
}
|
}
|
||||||
snap();
|
snap();
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
32
src/abr.h
32
src/abr.h
@@ -85,6 +85,38 @@ public:
|
|||||||
skip(bytes);
|
skip(bytes);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
std::vector<uint8_t> rrle(size_t encoded_bytes)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> 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:
|
protected:
|
||||||
template<typename T> inline T align4(T x) { return ((x - T{1}) & (~(T{3}))) + T{4}; }
|
template<typename T> inline T align4(T x) { return ((x - T{1}) & (~(T{3}))) + T{4}; }
|
||||||
template<typename T> T read()
|
template<typename T> T read()
|
||||||
|
|||||||
Reference in New Issue
Block a user