-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathencoder.zig
71 lines (55 loc) · 1.96 KB
/
encoder.zig
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
const std = @import("std");
const qoi = @import("qoiz.zig");
const Pixel = qoi.Pixel;
const Chunk = qoi.Chunk;
const Header = qoi.Chunk;
const Span = qoi.Span;
const Format = qoi.Format;
const mem = std.mem;
pub fn ChunkIterator(comptime format: Format) type {
return struct {
pixels: []const format.Type(),
pos: usize = 0,
seen: [64]Pixel = mem.zeroes([64]Pixel),
previous: Pixel = .{ .r = 0, .g = 0, .b = 0 },
const Self = @This();
pub fn next(self: *Self) ?Chunk {
if (self.pos >= self.pixels.len) return null;
var run: usize = 0;
while (run + self.pos < self.pixels.len and run < 62) : (run += 1) {
const pixel = format.pixel(self.pixels[self.pos + run]);
if (!std.meta.eql(pixel, self.previous)) break;
}
if (run > 0) {
self.pos += run;
// NOTE: -1 bias
return .{ .run = .{ .run = @intCast(run - 1) } };
}
const current = format.pixel(self.pixels[self.pos]);
self.pos += 1;
const index = current.hash();
defer self.previous = current;
defer self.seen[index] = current;
if (std.meta.eql(current, self.seen[index])) return .{
.index = .{ .index = index },
};
if (current.diff(self.previous)) |diff| return .{ .diff = diff };
if (current.luma(self.previous)) |luma| return .{ .luma = luma };
if (current.a == self.previous.a) return .{
.rgb = .{
.r = current.r,
.g = current.g,
.b = current.b,
},
};
return .{
.rgba = .{
.r = current.r,
.g = current.g,
.b = current.b,
.a = current.a,
},
};
}
};
}