-
Notifications
You must be signed in to change notification settings - Fork 1
/
023_smile_alpha_mask.zig
163 lines (146 loc) · 8.03 KB
/
023_smile_alpha_mask.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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// SPDX-License-Identifier: 0BSD
// Copyright © 2024 Chris Marchesi
//! Case: Render a smile (similar to 001_smile_rgb.zig and 002_smile_rgba.zig),
//! but use an alpha mask as the template image instead of iterating over the
//! image data every single time. Demonstrates basic composting onto a surface.
const debug = @import("std").debug;
const mem = @import("std").mem;
const z2d = @import("z2d");
pub const filename = "023_smile_alpha_mask";
pub fn render(alloc: mem.Allocator) !z2d.Surface {
const w = image.width * 2 + 10;
const h = image.height * 2 + 10;
var result_sfc = try z2d.Surface.init(
surface_type,
alloc,
w,
h,
);
// Our template alpha8 mask surface
var mask_sfc = try z2d.Surface.init(
.image_surface_alpha8,
alloc,
image.width,
image.height,
);
defer mask_sfc.deinit(alloc);
var x: i32 = 0;
var y: i32 = 0;
for (image.data[0..image.data.len]) |c| {
if (c == '\n') {
y += 1;
x = 0;
continue;
}
const px: z2d.Pixel = if (c == '0') .{ .alpha8 = .{ .a = 255 } } else .{ .alpha8 = .{ .a = 0 } };
mask_sfc.putPixel(x, y, px);
x += 1;
}
// 1st smile
//
// We used to do a simple iterate over and handle foreground and background
// on a per-pixel basis (see 001_smile_rgb.zig or 002_smile_rgba.zig).
// However, since this is a compositing test, we need to go what is
// ultimately a much more complicated route, one that actually, funny
// enough, uses much more memory (we need 3 extra buffers of the HxW of the
// smile itself) and is likely orders of magnitude slower (the composition
// operations iterate pixel-by-pixel). This is actually a good
// demonstration of the tradeoffs of both methods and why for simple tasks
// you are probably better off just writing directly.
// Create a working surface and paint it with the background color
var background_sfc = try z2d.Surface.initPixel(backgrounds[0], alloc, image.width, image.height);
defer background_sfc.deinit(alloc);
// Make our foreground surface
var foreground_sfc = try z2d.Surface.initPixel(foregrounds[0], alloc, image.width, image.height);
defer foreground_sfc.deinit(alloc);
// Apply mask to foreground
foreground_sfc.dstIn(&mask_sfc, 0, 0);
// Apply foreground to background
background_sfc.srcOver(&foreground_sfc, 0, 0);
// Composite our working surface at our first offset co-ordinates
result_sfc.srcOver(&background_sfc, 12, 13);
// 2nd smile
//
// Re-paint with the second background color.
background_sfc.paintPixel(backgrounds[1]);
// Re-paint foreground and apply mask
foreground_sfc.paintPixel(foregrounds[1]);
foreground_sfc.dstIn(&mask_sfc, 0, 0);
// Apply foreground to background
background_sfc.srcOver(&foreground_sfc, 0, 0);
// Composite our working surface at our second offset co-ordinates
result_sfc.srcOver(&background_sfc, w / 2 - 7, 13);
// 3rd smile
//
// Re-paint with the third background color.
background_sfc.paintPixel(backgrounds[2]);
// Re-paint foreground and apply mask
foreground_sfc.paintPixel(foregrounds[2]);
foreground_sfc.dstIn(&mask_sfc, 0, 0);
// Apply foreground to background
background_sfc.srcOver(&foreground_sfc, 0, 0);
// Composite our working surface at our second offset co-ordinates
result_sfc.srcOver(&background_sfc, w / 4 + 2, h / 2 - 7);
// done!
return result_sfc;
}
const surface_type: z2d.surface.SurfaceType = .image_surface_rgba;
const foregrounds: [3]z2d.Pixel = .{
.{ .rgba = (z2d.pixel.RGBA{ .r = 0xC5, .g = 0x0F, .b = 0x1F, .a = 0xFF }).multiply() }, // Red
.{ .rgba = (z2d.pixel.RGBA{ .r = 0x88, .g = 0x17, .b = 0x98, .a = 0xFF }).multiply() }, // Purple
.{ .rgba = (z2d.pixel.RGBA{ .r = 0xFC, .g = 0x7F, .b = 0x11, .a = 0xFF }).multiply() }, // Orange
};
const backgrounds: [3]z2d.Pixel = .{
.{ .rgba = (z2d.pixel.RGBA{ .r = 0xC1, .g = 0x9C, .b = 0x10, .a = 0x99 }).multiply() }, // Yellow-ish green
.{ .rgba = (z2d.pixel.RGBA{ .r = 0x3A, .g = 0x96, .b = 0xDD, .a = 0x99 }).multiply() }, // Blue
.{ .rgba = (z2d.pixel.RGBA{ .r = 0x01, .g = 0x24, .b = 0x86, .a = 0x99 }).multiply() }, // Deep blue
};
const image = .{
.width = 83,
.height = 41,
// Smile grabbed from stackoverflow here:
// https://codegolf.stackexchange.com/a/16857
.data =
\\ 0000000000000000000000000
\\ 00000000000000000000000000000000000
\\ 0000000000000000000000000000000000000000000
\\ 0000000000000000000000000000000000000000000000000
\\ 00000000000000000000000000000000000000000000000000000
\\ 000000000000000000000000000000000000000000000000000000000
\\ 0000000000000000000000000000000000000000000000000000000000000
\\ 00000000000000000000000000000000000000000000000000000000000000000
\\ 0000000000000000000000000000000000000000000000000000000000000000000
\\ 00000000000000000000000000000000000000000000000000000000000000000000000
\\ 0000000000000000000000000000000000000000000000000000000000000000000000000
\\ 000000000000000000000000000000000000000000000000000000000000000000000000000
\\ 0000000000000000 000000000000000000000000000000000000000 0000000000000000
\\ 0000000000000000 0000000000000000000000000000000000000 0000000000000000
\\ 000000000000000 00000000000000000000000000000000000 000000000000000
\\ 0000000000000000 00000000000000000000000000000000000 0000000000000000
\\ 0000000000000000 00000000000000000000000000000000000 0000000000000000
\\00000000000000000 00000000000000000000000000000000000 00000000000000000
\\00000000000000000 00000000000000000000000000000000000 00000000000000000
\\000000000000000000 0000000000000000000000000000000000000 000000000000000000
\\00000000000000000000000000000000000000000000000000000000000000000000000000000000000
\\00000000000000000000000000000000000000000000000000000000000000000000000000000000000
\\00000000000000000000000000000000000000000000000000000000000000000000000000000000000
\\00000000000000000000000000000000000000000000000000000000000000000000000000000000000
\\ 000000000000000000000000000000000000000000000000000000000000000000000000000000000
\\ 0000000000000000 0000000000000000
\\ 000000000000000 000000000000000
\\ 0000000000000000 0000000000000000
\\ 00000000000000000 00000000000000000
\\ 00000000000000000 00000000000000000
\\ 000000000000000000 000000000000000000
\\ 0000000000000000000 0000000000000000000
\\ 00000000000000000000 00000000000000000000
\\ 00000000000000000000000 00000000000000000000000
\\ 0000000000000000000000000000000000000000000000000000000000000
\\ 000000000000000000000000000000000000000000000000000000000
\\ 00000000000000000000000000000000000000000000000000000
\\ 0000000000000000000000000000000000000000000000000
\\ 0000000000000000000000000000000000000000000
\\ 00000000000000000000000000000000000
\\ 0000000000000000000000000
,
};