Skip to content

Commit

Permalink
Fixed poor compression ratio of ANS
Browse files Browse the repository at this point in the history
  • Loading branch information
MCJack123 committed Jan 19, 2024
1 parent 63fe6fc commit 8abef54
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 19 deletions.
22 changes: 19 additions & 3 deletions 32vid-player-mini.lua
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,22 @@ if bit32_band(flags, 3) == 1 then
local R = file.read()
local L = 2^R
local Ls = readDict(c and 24 or 32)
if R == 0 then
decodingTable = file.read()
X = nil
return
end
local a = 0
for i = 0, #Ls do Ls[i] = Ls[i] == 0 and 0 or 2^(Ls[i]-1) a = a + Ls[i] end
assert(a == L, a)
decodingTable = {R = R}
local x, step, next, symbol = 0, 0.625 * L + 3, {}, {}
for i = 0, #Ls do
next[i] = Ls[i]
for _ = 1, Ls[i] do x, symbol[x] = (x + step) % L, i end
for _ = 1, Ls[i] do
while symbol[x] do x = (x + 1) % L end
x, symbol[x] = (x + step) % L, i
end
end
for x = 0, L - 1 do
local s = symbol[x]
Expand All @@ -63,6 +71,10 @@ if bit32_band(flags, 3) == 1 then
end
function read(nsym)
local retval = {}
if X == nil then
for i = 1, nsym do retval[i] = decodingTable end
return retval
end
local i = 1
local last = 0
while i <= nsym do
Expand Down Expand Up @@ -105,17 +117,21 @@ for _ = 1, nframes do
local fg = read(width * height)
local dctime = os.epoch "utc" - dcstart
while os.epoch "utc" < start + vframe * 1000 / fps do end
local texta, fga, bga = {}, {}, {}
for y = 0, height - 1 do
local text, fgs, bgs = "", "", ""
for x = 1, width do
text = text .. string.char(128 + screen[y*width+x])
fgs = fgs .. blitColors[fg[y*width+x]]
bgs = bgs .. blitColors[bg[y*width+x]]
end
term.setCursorPos(1, y+1)
term.blit(text, fgs, bgs)
texta[y+1], fga[y+1], bga[y+1] = text, fgs, bgs
end
for i = 0, 15 do term.setPaletteColor(2^i, file.read() / 255, file.read() / 255, file.read() / 255) end
for y = 1, height do
term.setCursorPos(1, y)
term.blit(texta[y], fga[y], bga[y])
end
local delete = {}
for i, v in ipairs(subs) do
if vframe <= v.frame + v.length then
Expand Down
35 changes: 20 additions & 15 deletions src/generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ struct compare_node {bool operator()(tree_node *a, tree_node *b) {

std::string make32vid_cmp(const uchar * characters, const uchar * colors, const std::vector<Vec3b>& palette, int width, int height) {
std::string screen, col, pal;
tree_node screen_nodes[32], color_nodes[24]; // color codes 16-23 = repeat last color 2^(n-15) times
tree_node screen_nodes[32] = {0}, color_nodes[24] = {0}; // color codes 16-23 = repeat last color 2^(n-15) times
tree_node internal[31];
tree_node * internal_next = internal;
uchar * fgcolors = new uchar[width*height];
Expand Down Expand Up @@ -539,26 +539,30 @@ class ANSEncoder {
start = new int32_t[Lsl];
uint32_t * next = new uint32_t[Lsl];
uint8_t * symbol = new uint8_t[L];
memset(symbol, 0xFF, L);
uint32_t sumLs = 0;
const uint32_t step = 0.625 * L + 3;
const uint32_t step = ((L * 5) >> 3) + 3;
for (uint8_t s = 0; s < Lsl; s++) {
const uint32_t v = Ls[s];
const uint32_t ks = R - log2i(v);
nb[s] = (ks << (R+1)) - (v << ks);
start[s] = (int32_t)sumLs - (int32_t)v;
next[s] = v;
for (int i = 0; i < v; i++) {
symbol[X] = s;
X = (X + step) % L;
//std::cout << (int)s << " " << v << "\n";
if (v) {
const uint32_t ks = R - log2i(v);
nb[s] = (ks << (R+1)) - (v << ks);
start[s] = (int32_t)sumLs - (int32_t)v;
next[s] = v;
for (int i = 0; i < v; i++) {
while (symbol[X] != 0xFF) X = (X + 1) % L;
symbol[X] = s;
X = (X + step) % L;
}
sumLs = sumLs + v;
}
sumLs = sumLs + v;
}
// create encoding table
encodingTable = new uint32_t[2*L];
for (uint32_t x = L; x < 2*L; x++) {
const uint8_t s = symbol[x - L];
encodingTable[start[s] + next[s]] = x;
next[s]++;
encodingTable[start[s] + next[s]++] = x;
}
X = L;
// free temps
Expand Down Expand Up @@ -631,6 +635,7 @@ class ANSEncoder {
uint8_t s = symbols[_size-1] & 0x1F;
for (int i = _size-2; i >= 0; i--) {
const uint8_t nbBits = ((X + nb[s]) >> (R + 1));
//std::cout << (int)s << " " << (int)nbBits << "\n";
const uint8_t nexts = symbols[i] & 0x1F;
bitstream[length++] = ((uint32_t)nbBits << 24) | (X & ((1 << nbBits) - 1));
bitCount += nbBits;
Expand Down Expand Up @@ -685,7 +690,7 @@ static uint8_t ansdictcode(uint32_t n) {

std::string make32vid_ans(const uchar * characters, const uchar * colors, const std::vector<Vec3b>& palette, int width, int height) {
std::string screen, col, pal;
uint32_t screen_freq[32], color_freq[24]; // color codes 16-23 = repeat last color 2^(n-15) times
uint32_t screen_freq[32] = {0}, color_freq[24] = {0}; // color codes 16-23 = repeat last color 2^(n-15) times
uchar * fgcolors = new uchar[width*height];
uchar * bgcolors = new uchar[width*height];
uchar *fgnext = fgcolors, *bgnext = bgcolors;
Expand Down Expand Up @@ -797,7 +802,7 @@ std::string make32vid_ans(const uchar * characters, const uchar * colors, const
std::vector<uint32_t> screenLs = ANSEncoder::makeLs(screen_freq, 32, screenR);
if (screenLs.size() == 1) {
// encode a full-screen pattern of the same thing
screen = std::string(16, '\0') + std::string(1, screenLs[0]);
screen = std::string(17, '\0') + std::string(1, screenLs[0]);
} else {
// compress data
screen += screenR;
Expand All @@ -813,7 +818,7 @@ std::string make32vid_ans(const uchar * characters, const uchar * colors, const
std::vector<uint32_t> colorsLs = ANSEncoder::makeLs(color_freq, 24, colorsR);
if (colorsLs.size() == 1) {
// encode a full-screen pattern of the same thing
col = std::string(12, '\0') + std::string(1, colorsLs[0]);
col = std::string(13, '\0') + std::string(1, colorsLs[0]);
} else {
// compress data
col += colorsR;
Expand Down
2 changes: 1 addition & 1 deletion src/sanjuuni.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1061,7 +1061,7 @@ int main(int argc, const char * argv[]) {
if (mode == OutputType::Vid32 && !separateStreams) {
Vid32Chunk combinedChunk;
Vid32Header header;
combinedChunk.nframes = 0;
combinedChunk.nframes = totalFrames;
combinedChunk.type = (uint8_t)Vid32Chunk::Type::Combined;
memcpy(header.magic, "32VD", 4);
header.width = width / 2;
Expand Down

0 comments on commit 8abef54

Please sign in to comment.