proper init, initial header file write, huffman generation done

This commit is contained in:
Muaz Ahmad 2023-12-04 16:45:30 +05:00
parent 10d387e036
commit 4bc436d92b
3 changed files with 40 additions and 24 deletions

View file

@ -58,7 +58,7 @@ fn get_opts() !util.Options {
pub fn main() !void {
const opts = try get_opts();
var buffs = try util.Buffers.init(std.heap.page_allocator, opts.width, opts.height, 1000, opts.quality);
var buffs = try util.Buffers.init(std.heap.page_allocator, opts.width, opts.height, opts.quality);
defer buffs.deinit();
var thread_manager = try threads.ThreadManager.init(std.heap.page_allocator, opts.n_quant_jobs, buffs.Q_Lum, buffs.Q_Chrom);

View file

@ -13,9 +13,13 @@ const Huffman = std.AutoHashMap(u8, HuffCode);
// n_bits: u8,
// value: u16,
// };
const HuffCode = u16;
const HuffCode = struct {
value: u16,
n_bits: u5,
};
const HuffmanMeta = struct {
bits: [33]u8,
total_n: usize,
huffval: [256]u8,
};
@ -25,7 +29,7 @@ const Scan = struct {
dc_diffs: [3]i16,
rles: [3]RLE_Seq,
freqs: [4][]u32,
huffs: [4]*Huffman,
huffs: [4]Huffman,
const Self = @This();
@ -36,15 +40,12 @@ const Scan = struct {
RLE_Seq.init(alloc_root),
RLE_Seq.init(alloc_root),
RLE_Seq.init(alloc_root),
}, .freqs = [4][]u32{ try alloc.alloc(u32, 13), try alloc.alloc(u32, 257), try alloc.alloc(u32, 13), try alloc.alloc(u32, 257) }, .huffs = [4]*Huffman{
try alloc.create(Huffman),
try alloc.create(Huffman),
try alloc.create(Huffman),
try alloc.create(Huffman),
}, .freqs = [4][]u32{ try alloc.alloc(u32, 13), try alloc.alloc(u32, 257), try alloc.alloc(u32, 13), try alloc.alloc(u32, 257) }, .huffs = [4]Huffman{
Huffman.init(alloc_root),
Huffman.init(alloc_root),
Huffman.init(alloc_root),
Huffman.init(alloc_root),
} };
for (0..4) |i| {
self.huffs[i].* = Huffman.init(alloc);
}
return self;
}
fn deinit(self: *Self) void {
@ -54,7 +55,7 @@ const Scan = struct {
}
}
fn do_rle_freq_pass(self: *Self, buff: *const util.Buffers) !void {
fn do_rle_freq_pass(self: *Self, buff: *const util.Buffers, f: std.fs.File) !void {
const h = buff.Y_quant.len;
const w = buff.Y_quant[0].len;
@ -71,16 +72,14 @@ 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();
try self.generate_huffmans(f);
}
fn generate_huffmans(self: *Self) !void {
for (0..4) |i_freq| {
const huffman_meta = gen_huffman(self.freqs[i_freq]);
_ = huffman_meta;
var huff = self.huffs[i_freq];
std.debug.print("{any}\n", .{huff});
try huff.put(0, 1);
fn generate_huffmans(self: *Self, f: std.fs.File) !void {
for (0..4) |i| {
const huff_meta = gen_huffman(self.freqs[i]);
try gen_codes(&self.huffs[i], huff_meta);
try dump_huffman(f, huff_meta);
}
}
};
@ -227,6 +226,7 @@ inline fn gen_huffman(freqs: []u32) HuffmanMeta {
return .{
.bits = bits,
.huffval = huffval,
.total_n = k,
};
}
@ -295,11 +295,29 @@ fn parse_block(block: *util.BlockQuantized, dc_diff: *i16, rle: *RLE_Seq, dc_fre
});
}
fn write_headers(f: std.fs.File, buff: *const util.Buffers) !void {
var out_buff = [6]u8{ 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84 } ++ [1]u8{0x00} ++ [_]u8{0x00} ** 64 ++ [1]u8{0x01} ++ [_]u8{0x00} ** 64;
for (0..64) |i| {
out_buff[7 + i] = @intFromFloat(buff.Q_Lum[i]);
out_buff[7 + i + 65] = @intFromFloat(buff.Q_Chrom[i]);
}
_ = try f.write(&out_buff);
}
fn dump_huffman(f: std.fs.File, huff_meta: HuffmanMeta) !void {
_ = huff_meta;
_ = f;
}
pub fn generate_jpg(buff: util.Buffers, alloc: std.mem.Allocator) !void {
var scan_data = try Scan.init(alloc);
defer scan_data.deinit();
try scan_data.do_rle_freq_pass(&buff);
var f = try std.fs.cwd().createFile("out.jpg", .{});
defer f.close();
try write_headers(f, &buff);
try scan_data.do_rle_freq_pass(&buff, f);
// rle, huffman pass
// file headers

View file

@ -77,11 +77,10 @@ pub const Buffers = struct {
num_blocks: u32,
input_buff: []u8,
output_buff: []u8,
const Self = @This();
pub fn init(root_alloc: std.mem.Allocator, w: usize, h: usize, output_buff_len: usize, q: f16) !Self {
pub fn init(root_alloc: std.mem.Allocator, w: usize, h: usize, q: f16) !Self {
var arena = std.heap.ArenaAllocator.init(root_alloc);
var alloc = arena.allocator();
const block_w = w / 16;
@ -103,7 +102,6 @@ pub const Buffers = struct {
.num_blocks = @truncate(w * h * 3 / 2 / 64),
.input_buff = try alloc.alloc(u8, w * 8),
.output_buff = try alloc.alloc(u8, output_buff_len),
};
for (0..block_h) |i| {
buffs.Y[i] = try alloc.alloc([4]Block, block_w);