zig build-exe main.zig
- The video must be in resolution 1920 x 1080.
./run.sh video-file
- get file "file-out" at current directory
Created
January 1, 2023 06:19
-
-
Save shimamura-sakura/74adc2ad6cbf38905d8a308cbe83e06f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
pub fn Canvas(comptime T: type) type { | |
return struct { | |
const Self = @This(); | |
pix: []T, | |
line: usize, | |
width: usize, | |
height: usize, | |
pub fn getAreaUnsafe(self: Self, l: usize, u: usize, r: usize, d: usize) Self { | |
const beg = u * self.line + l; | |
return .{ | |
.pix = self.pix[beg..self.pix.len], | |
.line = self.line, | |
.width = r - l, | |
.height = d - u, | |
}; | |
} | |
pub fn getAreaStrict(self: Self, l: usize, u: usize, r: usize, d: usize) !Self { | |
if (l > r or u > d or r > self.width or d > self.height) return error.OutOfRange; | |
return self.getAreaUnsafe(l, u, r, d); | |
} | |
pub fn getAreaClamped(self: Self, l: usize, u: usize, r: usize, d: usize) !Self { | |
if (l > r or u > d or l >= self.width or u >= self.height) return error.OutOfRange; | |
return self.getAreaUnsafe(l, u, @min(r, self.width), @min(d, self.height)); | |
} | |
pub fn getLineUnsafe(self: Self, y: usize, l: usize, r: usize) []T { | |
const off = y * self.line; | |
return self.pix[off + l .. off + r]; | |
} | |
pub fn getLineStrict(self: Self, y: usize, l: usize, r: usize) ![]T { | |
if (l > r or r > self.width or y >= self.height) return error.OutOfRange; | |
return self.getLineUnsafe(y, l, r); | |
} | |
pub fn getLineClamped(self: Self, y: usize, l: usize, r: usize) ![]T { | |
if (l > r or l >= self.width or y >= self.height) return error.OutOfRange; | |
return self.getLineUnsafe(y, l, @min(r, self.width)); | |
} | |
pub fn copyFromUnsafe(cpTo: Self, cpFr: Self) void { | |
var y: usize = 0; | |
const w = @min(cpTo.width, cpFr.width); | |
const h = @min(cpTo.height, cpFr.height); | |
while (y < h) : (y += 1) | |
std.mem.copy(T, cpTo.getLineUnsafe(y, 0, w), cpFr.getLineUnsafe(y, 0, w)); | |
} | |
pub fn fill(self: Self, pixel: T) void { | |
var y: usize = 0; | |
while (y < self.height) : (y += 1) | |
std.mem.set(T, self.getLineUnsafe(y, 0, self.width), pixel); | |
} | |
}; | |
} | |
pub fn MyRange(comptime T: type) type { | |
return struct { | |
const Self = @This(); | |
count: usize, | |
value: T, | |
delta: T, | |
addDt: bool, | |
pub fn next(self: *Self) ?T { | |
if (self.count == 0) return null; | |
self.count -= 1; | |
const v = self.value; | |
if (self.count == 0) return v; | |
if (self.addDt) self.value += self.delta else self.value -= self.delta; | |
return v; | |
} | |
}; | |
} | |
pub fn range(comptime T: type, beg: T, end: T) MyRange(T) { | |
return .{ | |
.count = if (end > beg) end - beg + 1 else beg - end + 1, | |
.value = beg, | |
.delta = 1, | |
.addDt = end > beg, | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
const lib = @import("./lib.zig"); | |
const mem = std.mem; | |
const hep: mem.Allocator = std.heap.page_allocator; | |
const RGBPixel = [3]u8; | |
const RGBCanvas = lib.Canvas(RGBPixel); | |
fn cvsToByte(cvs: RGBCanvas) u8 { | |
var r: usize = 0; | |
var g: usize = 0; | |
var b: usize = 0; | |
var n: usize = 0; | |
var y: usize = 0; | |
while (y < cvs.height) : (y += 1) | |
for (cvs.getLineUnsafe(y, 0, cvs.width)) |px| { | |
r += px[0]; | |
g += px[1]; | |
b += px[2]; | |
n += 1; | |
}; | |
r /= n; | |
g /= n; | |
b /= n; | |
// std.debug.print("{b:0<8} {b:0<8} {b:0<8}\n", .{ r, g, b }); | |
return @intCast(u8, 0 | | |
(((r + 0b000_011_11) >> 0) & 0b111_000_00) | | |
(((g + 0b000_011_11) >> 3) & 0b000_111_00) | | |
(((b + 0b000_111_11) >> 6) & 0b000_000_11)); | |
} | |
pub fn main() !void { | |
const inW = 1920; | |
const inH = 1080; | |
const inDat = try hep.alloc(RGBPixel, inW * inH); | |
const inByt = std.mem.sliceAsBytes(inDat); | |
defer hep.free(inDat); | |
const cvIn = RGBCanvas{ | |
.pix = inDat, | |
.line = inW, | |
.width = inW, | |
.height = inH, | |
}; | |
const stdin = std.io.getStdIn().reader(); | |
const file_len = while ((try stdin.readAll(inByt)) == inByt.len) { | |
var magic: [5]u8 = undefined; | |
for (magic) |*b, i| | |
b.* = cvsToByte(cvIn.getAreaUnsafe(i * 16 + 8, 0 + 8, i * 16 + 16, 16)); | |
if (std.mem.eql(u8, &magic, "HELLO") == false) continue; | |
var buffer: [8]u8 = undefined; | |
for (buffer) |*b, i| | |
b.* = cvsToByte(cvIn.getAreaUnsafe(i * 16, 16, i * 16 + 16, 32)); | |
break std.mem.readIntLittle(u64, &buffer); | |
} else return error.MagicNotFound; | |
std.debug.print("[HELLO: file length = {}]\n", .{file_len}); | |
const file_dat = try hep.alloc(u8, @intCast(usize, file_len)); | |
defer hep.free(file_dat); | |
while ((try stdin.readAll(inByt)) == inByt.len) { | |
var magic: [5]u8 = undefined; | |
for (magic) |*b, i| | |
b.* = cvsToByte(cvIn.getAreaUnsafe(i * 16 + 8, 0 + 8, i * 16 + 16, 16)); | |
if (std.mem.eql(u8, &magic, "ABCDE")) break; | |
if (std.mem.eql(u8, &magic, "WORLD") == false) continue; | |
var buffer: [16]u8 = undefined; | |
for (buffer) |*b, i| | |
b.* = cvsToByte(cvIn.getAreaUnsafe(i * 16, 16, i * 16 + 16, 32)); | |
const offset = @intCast(usize, std.mem.readIntLittle(u64, buffer[0..8])); | |
const length = @intCast(usize, std.mem.readIntLittle(u64, buffer[8..16])); | |
std.debug.print("[WORLD: offset = {}, length = {}]\n", .{ offset, length }); | |
for (file_dat[offset .. offset + length]) |*b, i| { | |
const y = (i >> 6) << 4; | |
const x = (i & 0b011_1111) << 4; | |
b.* = cvsToByte(cvIn.getAreaUnsafe(x, y + 32, x + 16, y + 48)); | |
} | |
} else return error.NoData; | |
while ((try stdin.readAll(inByt)) == inByt.len) {} | |
try std.fs.cwd().writeFile("file_out", file_dat); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
set -ue | |
ffmpeg -i "$1" -f rawvideo -pix_fmt rgb24 -y - | ./main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment