| author | |
| committer | |
| log | 64cfdaabc303a26095c5b5f9146f87ba6997a031 |
| tree | 8909bf3f5f9e57dcdea3dca18cf6aac4bc53e7c6 |
| parent | 5aaaebb7f77a6737c10dd7be77926019e0f32ab4 |
4 files changed, 69 insertions(+), 2 deletions(-)
YUV.zig created+45| ... | ... | @@ -0,0 +1,45 @@ |
| 1 | const std = @import("std"); | |
| 2 | const Self = @This(); | |
| 3 | const color = @import("./mod.zig"); | |
| 4 | const _x = @import("./_x.zig"); | |
| 5 | const vec4 = @Vector(4, f32); | |
| 6 | ||
| 7 | y: f32, // [ 0 .. 1 ] | |
| 8 | u: f32, // [ -0.436 .. +0.436 ] | |
| 9 | v: f32, // [ -0.615 .. +0.615 ] | |
| 10 | a: f32, // [ 0 .. 1 ] | |
| 11 | ||
| 12 | pub fn initYUVA(y: f32, u: f32, v: f32, a: f32) Self { | |
| 13 | return Self{ | |
| 14 | .y = y, | |
| 15 | .u = u, | |
| 16 | .v = v, | |
| 17 | .a = a, | |
| 18 | }; | |
| 19 | } | |
| 20 | ||
| 21 | pub fn initYUV(y: f32, u: f32, v: f32) Self { | |
| 22 | return initYUVA(y, u, v, 255); | |
| 23 | } | |
| 24 | ||
| 25 | pub fn eql(x: Self, y: Self) bool { | |
| 26 | return x.y == y.y and x.u == y.u and x.v == y.v and x.a == y.a; | |
| 27 | } | |
| 28 | ||
| 29 | pub usingnamespace _x.mixin(@This(), f32, .y, .u, .v); | |
| 30 | ||
| 31 | // https://web.archive.org/web/20180423091842/http://www.equasys.de/colorconversion.html | |
| 32 | pub fn to_srgb(x: Self) color.sRGB { | |
| 33 | // zig fmt: off | |
| 34 | const y, const u, const v, const a = x.to_array(); | |
| 35 | const r = y * 1.000 + u * 0.000 + v * 1.140; | |
| 36 | const g = y * 1.000 + u * -0.395 + v * -0.581; | |
| 37 | const b = y * 1.000 + u * 2.032 + v * 0.000; | |
| 38 | return color.sRGB.from_float(.{ r, g, b, a }); | |
| 39 | // zig fmt: on | |
| 40 | } | |
| 41 | ||
| 42 | pub fn normal(x: Self) vec4 { | |
| 43 | const v: vec4 = x.to_array(); | |
| 44 | return v * @as(vec4, .{ 255, 255, 255, 1 }); | |
| 45 | } |
mod.zig+1| ... | ... | @@ -7,3 +7,4 @@ pub const CMYK = @import("./CMYK.zig"); |
| 7 | 7 | pub const HSL = @import("./HSL.zig"); |
| 8 | 8 | pub const HSV = @import("./HSV.zig"); |
| 9 | 9 | pub const YCbCr = @import("./YCbCr.zig"); |
| 10 | pub const YUV = @import("./YUV.zig"); |
sRGB.zig+14-2| ... | ... | @@ -4,6 +4,7 @@ const std = @import("std"); |
| 4 | 4 | const Self = @This(); |
| 5 | 5 | const color = @import("./mod.zig"); |
| 6 | 6 | const _x = @import("./_x.zig"); |
| 7 | const vec4 = @Vector(4, f32); | |
| 7 | 8 | |
| 8 | 9 | r: u8, // red value |
| 9 | 10 | g: u8, // green value |
| ... | ... | @@ -104,8 +105,8 @@ pub fn to_float(x: Self) Float { |
| 104 | 105 | }; |
| 105 | 106 | } |
| 106 | 107 | |
| 107 | pub fn from_float(y: @Vector(4, f32)) Self { | |
| 108 | const r, const g, const b, const a = y * @as(@Vector(4, f32), @splat(255.0)); | |
| 108 | pub fn from_float(y: vec4) Self { | |
| 109 | const r, const g, const b, const a = y * @as(vec4, @splat(255.0)); | |
| 109 | 110 | return .{ |
| 110 | 111 | .r = @intFromFloat(r), |
| 111 | 112 | .g = @intFromFloat(g), |
| ... | ... | @@ -174,3 +175,14 @@ pub fn to_ycbcr(x: Self) color.YCbCr { |
| 174 | 175 | }); |
| 175 | 176 | // zig fmt: on |
| 176 | 177 | } |
| 178 | ||
| 179 | // https://web.archive.org/web/20180423091842/http://www.equasys.de/colorconversion.html | |
| 180 | pub fn to_yuv(x: Self) color.YUV { | |
| 181 | // zig fmt: off | |
| 182 | const r, const g, const b, const a = x.to_vec() / @as(vec4, @splat(255)); | |
| 183 | const y = r * 0.299 + g * 0.587 + b * 0.114; | |
| 184 | const u = r * -0.147 + g * -0.289 + b * 0.436; | |
| 185 | const v = r * 0.615 + g * -0.515 + b * -0.100; | |
| 186 | return color.YUV.initYUVA(y, u, v, a); | |
| 187 | // zig fmt: on | |
| 188 | } |
test.zig+9| ... | ... | @@ -72,4 +72,13 @@ test { |
| 72 | 72 | try expect(o.to_ycbcr().to_array()).toEqual(.{ 166, 173, 65, 255 }); |
| 73 | 73 | try expect(o.to_ycbcr().to_srgb().to_array()).toEqual(.{ 77, 195, 245, 255 }); |
| 74 | 74 | } |
| 75 | { | |
| 76 | // Y: 166.244, U: 39.741, V: -76.541 | |
| 77 | const y, const u, const v, const a = o.to_yuv().normal(); | |
| 78 | try std.testing.expectApproxEqAbs(166.244, y, 0.001); | |
| 79 | try std.testing.expectApproxEqAbs(39.723, u, 0.001); | |
| 80 | try std.testing.expectApproxEqAbs(-76.539, v, 0.001); | |
| 81 | try std.testing.expect(a == 1.0); | |
| 82 | try expect(o.to_yuv().to_srgb().to_array()).toEqual(.{ 78, 195, 246, 255 }); | |
| 83 | } | |
| 75 | 84 | } |