diff --git a/src/coders/rle.cpp b/src/coders/rle.cpp index a13454a5..f049492e 100644 --- a/src/coders/rle.cpp +++ b/src/coders/rle.cpp @@ -1,5 +1,7 @@ #include "rle.hpp" +#include "util/data_io.hpp" + size_t rle::decode(const ubyte* src, size_t srclen, ubyte* dst) { size_t offset = 0; for (size_t i = 0; i < srclen;) { @@ -40,8 +42,8 @@ size_t rle::decode16(const ubyte* src, size_t srclen, ubyte* dst) { auto dst16 = reinterpret_cast(dst); size_t offset = 0; for (size_t i = 0; i < srclen / 2;) { - uint16_t len = src16[i++]; - uint16_t c = src16[i++]; + uint16_t len = dataio::le2h(src16[i++]); + uint16_t c = dataio::le2h(src16[i++]); for (size_t j = 0; j <= len; j++) { dst16[offset++] = c; } @@ -61,16 +63,16 @@ size_t rle::encode16(const ubyte* src, size_t srclen, ubyte* dst) { for (size_t i = 1; i < srclen / 2; i++) { uint16_t cnext = src16[i]; if (cnext != c || counter == 0xFFFF) { - dst16[offset++] = counter; - dst16[offset++] = c; + dst16[offset++] = dataio::h2le(counter); + dst16[offset++] = dataio::h2le(c); c = cnext; counter = 0; } else { counter++; } } - dst16[offset++] = counter; - dst16[offset++] = c; + dst16[offset++] = dataio::h2le(counter); + dst16[offset++] = dataio::h2le(c); return offset * 2; } @@ -80,7 +82,7 @@ size_t extrle::decode(const ubyte* src, size_t srclen, ubyte* dst) { uint len = src[i++]; if (len & 0x80) { len &= 0x7F; - len |= ((uint)src[i++]) << 7; + len |= (static_cast(src[i++])) << 7; } ubyte c = src[i++]; for (size_t j = 0; j <= len; j++) { @@ -122,3 +124,70 @@ size_t extrle::encode(const ubyte* src, size_t srclen, ubyte* dst) { dst[offset++] = c; return offset; } + +size_t extrle::decode16(const ubyte* src, size_t srclen, ubyte* dst8) { + auto dst = reinterpret_cast(dst8); + size_t offset = 0; + for (size_t i = 0; i < srclen;) { + uint len = src[i++]; + bool widechar = len & 0x40; + if (len & 0x80) { + len &= 0x3F; + len |= (static_cast(src[i++])) << 6; + } else { + len &= 0x3F; + } + uint16_t c = src[i++]; + if (widechar) { + c |= ((static_cast(src[i++])) << 8); + } + for (size_t j = 0; j <= len; j++) { + dst[offset++] = c; + } + } + return offset * 2; +} + +size_t extrle::encode16(const ubyte* src8, size_t srclen, ubyte* dst) { + if (srclen == 0) { + return 0; + } + auto src = reinterpret_cast(src8); + size_t offset = 0; + uint counter = 0; + uint16_t c = src[0]; + for (size_t i = 1; i < srclen/2; i++) { + uint16_t cnext = src[i]; + if (cnext != c || counter == max_sequence) { + if (counter >= 0x40) { + dst[offset++] = 0x80 | ((c > 255) << 6) | (counter & 0x3F); + dst[offset++] = counter >> 6; + } else { + dst[offset++] = counter | ((c > 255) << 6); + } + if (c > 255) { + dst[offset++] = c & 0xFF; + dst[offset++] = c >> 8; + } else { + dst[offset++] = c; + } + c = cnext; + counter = 0; + } else { + counter++; + } + } + if (counter >= 0x40) { + dst[offset++] = 0x80 | ((c > 255) << 6) | (counter & 0x3F); + dst[offset++] = counter >> 6; + } else { + dst[offset++] = counter | ((c > 255) << 6); + } + if (c > 255) { + dst[offset++] = c & 0xFF; + dst[offset++] = c >> 8; + } else { + dst[offset++] = c; + } + return offset; +} diff --git a/src/coders/rle.hpp b/src/coders/rle.hpp index eb6c5b1d..c087ac69 100644 --- a/src/coders/rle.hpp +++ b/src/coders/rle.hpp @@ -14,4 +14,8 @@ namespace extrle { constexpr uint max_sequence = 0x7FFF; size_t encode(const ubyte* src, size_t length, ubyte* dst); size_t decode(const ubyte* src, size_t length, ubyte* dst); + + constexpr uint max_sequence16 = 0x3FFF; + size_t encode16(const ubyte* src, size_t length, ubyte* dst); + size_t decode16(const ubyte* src, size_t length, ubyte* dst); } diff --git a/src/util/data_io.hpp b/src/util/data_io.hpp index 4d2d69ab..abf5bfa2 100644 --- a/src/util/data_io.hpp +++ b/src/util/data_io.hpp @@ -33,7 +33,7 @@ namespace dataio { /// @param value source integer /// @return integer with hardware byte-order template - T be2h(T value){ + inline T be2h(T value){ if (is_big_endian()) { return value; } else { diff --git a/test/coders/rle.cpp b/test/coders/rle.cpp index 4ce06d1a..3790fdb1 100644 --- a/test/coders/rle.cpp +++ b/test/coders/rle.cpp @@ -39,3 +39,7 @@ TEST(RLE16, EncodeDecode) { TEST(ExtRLE, EncodeDecode) { test_encode_decode(extrle::encode, extrle::decode); } + +TEST(ExtRLE16, EncodeDecode) { + test_encode_decode(extrle::encode16, extrle::decode16); +}