summaryrefslogtreecommitdiff
path: root/src/jpg/scan.zig
blob: d47b453f4b14e3dbbe4224ffd67d09dd7178ac81 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
const std = @import("std");

const Self = @This();

pub const Component = struct {
    selector: u8,
    dc_selector: u4,
    ac_selector: u4,
};

components: []Component,
selection_start: u8,
selection_end: u8,
params: packed union {
    approximation_bit_position: u8,
    point_transform: u4,
},
data: []u8,

pub fn read(gpa: std.mem.Allocator, reader: *std.Io.Reader) !Self {
    const count = try reader.takeByte();
    var self: Self = undefined;

    self.components = try gpa.alloc(Component, count);
    errdefer gpa.free(self.components);

    for (self.components) |*component| {
        component.selector = try reader.takeByte();
        const entropy_selector = try reader.takeByte();
        component.dc_selector = @truncate(entropy_selector >> 4);
        component.ac_selector = @truncate(entropy_selector);
    }

    self.selection_start = try reader.takeByte();
    self.selection_end = try reader.takeByte();
    self.params = @bitCast(try reader.takeByte());

    var aw: std.Io.Writer.Allocating = .init(gpa);

    var size = try reader.streamDelimiter(&aw.writer, 0xff);
    while ((try reader.peek(2))[1] == 0) {
        try aw.writer.writeByte(0xff);
        reader.toss(2);
        size = try reader.streamDelimiter(&aw.writer, 0xff);
    }

    self.data = try aw.toOwnedSlice();

    return self;
}

pub fn deinit(self: *Self, gpa: std.mem.Allocator) void {
    gpa.free(self.components);
    gpa.free(self.data);
    self.* = undefined;
}