Browse Source

Unify CLX pixel encoding code

pull/5191/head
Gleb Mazovetskiy 4 years ago committed by Anders Jenbo
parent
commit
ef46d99ccc
  1. 70
      Source/utils/cel_to_clx.cpp
  2. 78
      Source/utils/clx_write.hpp
  3. 70
      Source/utils/pcx_to_clx.cpp

70
Source/utils/cel_to_clx.cpp

@ -10,6 +10,7 @@
#endif
#include "appfat.h"
#include "utils/clx_write.hpp"
#include "utils/endian.hpp"
namespace devilution {
@ -27,75 +28,6 @@ constexpr uint8_t GetCelTransparentWidth(uint8_t control)
return -static_cast<int8_t>(control);
}
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);
}
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);
}
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]);
}
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
OwnedClxSpriteListOrSheet CelToClx(const uint8_t *data, size_t size, PointerOrValue<uint16_t> widthOrWidths)

78
Source/utils/clx_write.hpp

@ -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

70
Source/utils/pcx_to_clx.cpp

@ -8,6 +8,7 @@
#include <vector>
#include "appfat.h"
#include "utils/clx_write.hpp"
#include "utils/endian.hpp"
#include "utils/pcx.hpp"
#include "utils/stdcompat/cstddef.hpp"
@ -25,75 +26,6 @@ namespace devilution {
namespace {
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);
}
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);
}
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]);
}
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);
}
size_t GetReservationSize(size_t pcxSize)
{
// For the most part, CL2 is smaller than PCX, with a few exceptions.

Loading…
Cancel
Save