3 changed files with 80 additions and 138 deletions
@ -0,0 +1,78 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <cstddef> |
||||||
|
#include <cstdint> |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
namespace devilution { |
||||||
|
|
||||||
|
inline void AppendCl2TransparentRun(unsigned width, std::vector<uint8_t> &out) |
||||||
|
{ |
||||||
|
while (width >= 0x7F) { |
||||||
|
out.push_back(0x7F); |
||||||
|
width -= 0x7F; |
||||||
|
} |
||||||
|
if (width == 0) |
||||||
|
return; |
||||||
|
out.push_back(width); |
||||||
|
} |
||||||
|
|
||||||
|
inline void AppendCl2FillRun(uint8_t color, unsigned width, std::vector<uint8_t> &out) |
||||||
|
{ |
||||||
|
while (width >= 0x3F) { |
||||||
|
out.push_back(0x80); |
||||||
|
out.push_back(color); |
||||||
|
width -= 0x3F; |
||||||
|
} |
||||||
|
if (width == 0) |
||||||
|
return; |
||||||
|
out.push_back(0xBF - width); |
||||||
|
out.push_back(color); |
||||||
|
} |
||||||
|
|
||||||
|
inline void AppendCl2PixelsRun(const uint8_t *src, unsigned width, std::vector<uint8_t> &out) |
||||||
|
{ |
||||||
|
while (width >= 0x41) { |
||||||
|
out.push_back(0xBF); |
||||||
|
for (size_t i = 0; i < 0x41; ++i) |
||||||
|
out.push_back(src[i]); |
||||||
|
width -= 0x41; |
||||||
|
src += 0x41; |
||||||
|
} |
||||||
|
if (width == 0) |
||||||
|
return; |
||||||
|
out.push_back(256 - width); |
||||||
|
for (size_t i = 0; i < width; ++i) |
||||||
|
out.push_back(src[i]); |
||||||
|
} |
||||||
|
|
||||||
|
inline void AppendCl2PixelsOrFillRun(const uint8_t *src, unsigned length, std::vector<uint8_t> &out) |
||||||
|
{ |
||||||
|
const uint8_t *begin = src; |
||||||
|
const uint8_t *prevColorBegin = src; |
||||||
|
unsigned prevColorRunLength = 1; |
||||||
|
uint8_t prevColor = *src++; |
||||||
|
while (--length > 0) { |
||||||
|
const uint8_t color = *src; |
||||||
|
if (prevColor == color) { |
||||||
|
++prevColorRunLength; |
||||||
|
} else { |
||||||
|
// A tunable parameter that decides at which minimum length we encode a fill run.
|
||||||
|
// 3 appears to be optimal for most of our data (much better than 2, rarely very slightly worse than 4).
|
||||||
|
constexpr unsigned MinFillRunLength = 3; |
||||||
|
if (prevColorRunLength >= MinFillRunLength) { |
||||||
|
AppendCl2PixelsRun(begin, prevColorBegin - begin, out); |
||||||
|
AppendCl2FillRun(prevColor, prevColorRunLength, out); |
||||||
|
begin = src; |
||||||
|
} |
||||||
|
prevColorBegin = src; |
||||||
|
prevColorRunLength = 1; |
||||||
|
prevColor = color; |
||||||
|
} |
||||||
|
++src; |
||||||
|
} |
||||||
|
AppendCl2PixelsRun(begin, prevColorBegin - begin, out); |
||||||
|
AppendCl2FillRun(prevColor, prevColorRunLength, out); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace devilution
|
||||||
Loading…
Reference in new issue