diff --git a/src/output.zig b/src/output.zig index a5ab332..7feae3a 100644 --- a/src/output.zig +++ b/src/output.zig @@ -58,9 +58,73 @@ const Scan = struct { try parse_block(&buff.V_quant[x][y], &self.dc_diffs[2], &self.rles[2], self.freqs[2], self.freqs[3]); } } + try self.generate_huffmans(); + } + + fn generate_huffmans(self: *Self) !void { + for (0..4) |i| { + try gen_huffman(&self.huffs[i], self.freqs[i]); + } } }; +inline fn get_idx_min2(freqs: []u32) ?struct { usize, usize } { + var min1: u32 = undefined; + var min1_idx: usize = undefined; + var min2: u32 = undefined; + var min2_idx: usize = undefined; + var is_init_1 = false; + var is_init_2 = false; + for (0..freqs.len) |i| { + if (freqs[i] == 0) continue; + if (!is_init_1) { + min1 = freqs[i]; + min1_idx = i; + } else if (!is_init_2) { + if (freqs[i] < min1) { + min2 = min1; + min2_idx = min1_idx; + min1 = freqs[i]; + min1_idx = i; + } else { + min2 = freqs[i]; + min2_idx = i; + } + } else if (freqs[i] < min1) { + min1 = freqs[i]; + min1_idx = i; + } else if (freqs[i] < min2) { + min2 = freqs[i]; + min2_idx = i; + } + } + return if (is_init_2) .{ + min1_idx, + min2_idx, + } else null; +} + +inline fn gen_huffman(huff: *Huffman, freqs: []u32) !void { + _ = huff; + var codesizes = [_]u8{0} ** 257; + var others = [_]u9{0x1ff} ** 257; + + while (get_idx_min2(freqs)) |tmp| { + var v1 = tmp.@"0"; + var v2 = tmp.@"1"; + freqs[v1] += freqs[v2]; + codesizes[v1] += 1; + while (others[v1] != 0x1ff) : (codesizes[v1] += 1) { + v1 = others[v1]; + } + others[v1] = @truncate(v2); + codesizes[v2] += 1; + while (others[v2] != 0x1ff) : (codesizes[v2] += 1) { + v2 = others[v2]; + } + } +} + inline fn get_size(n: i16) u8 { if (n == 0) { return 0;