ReviewOS

also looking at this

home-lang/home

feat(media): implement native JPEG coding and bounded MJPEG streaming

#912
Merged chris wants to merge feat/native-jpeg-mjpeg into main
5 files +442 -263
packages/image/src/jpeg_dct.zigadded+39-0
Changes to packages/image/src/jpeg_dct.zig
@@ -0,0 +1,39 @@
1//! Shared orthonormal JPEG DCT basis and inverse transform (Home, MIT).
2const std = ;
3pub const BASIS: [8]@Vector(8, f32) = blk: {
4 @setEvalBranchQuota(10000);
5 var b: [8]@Vector(8, f32) = undefined;
6 for (0..8) |u| for (0..8) |x| {
7 const scale: f64 = if (u == 0) 0.3535533905932738 else 0.5;
8 b[u][x] = @floatCast(scale * @cos((@as(f64, @floatFromInt(x)) * 2 + 1) * @as(f64, @floatFromInt(u)) * std.math.pi / 16));
9 };
10 break :blk b;
11};
12
13pub fn inverse(block: *[64]i32, quant: *const [64]u16) void {
14 var work: [8][8]f32 = undefined;
15 for (0..8) |v| {
16 var coefficients: @Vector(8, f32) = undefined;
17 inline for (0..8) |u| coefficients[u] = @as(f32, @floatFromInt(block[v * 8 + u])) * @as(f32, @floatFromInt(quant[v * 8 + u]));
18 for (0..8) |x| {
19 var basis: @Vector(8, f32) = undefined;
20 inline for (0..8) |u| basis[u] = BASIS[u][x];
21 work[v][x] = @reduce(.Add, coefficients * basis);
22 }
23 }
24 for (0..8) |y| for (0..8) |x| {
25 var values: @Vector(8, f32) = undefined;
26 var basis: @Vector(8, f32) = undefined;
27 inline for (0..8) |v| {
28 values[v] = work[v][x];
29 basis[v] = BASIS[v][y];
30 }
31 block[y * 8 + x] = @intFromFloat(std.math.clamp(@round(@reduce(.Add, values * basis)) + 128, 0, 255));
32 };
33}
34test "inverse JPEG DC scale and zero AC are exact" {
35 var block: [64]i32 = @splat(0);
36 block[0] = 80;
37 inverse(&block, &@as([64]u16, @splat(1)));
38 for (block) |v| try std.testing.expectEqual(@as(i32, 138), v);
39}