1 /* sane - Scanner Access Now Easy.
2
3 Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
4
5 This file is part of the SANE package.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <https://www.gnu.org/licenses/>.
19
20 As a special exception, the authors of SANE give permission for
21 additional uses of the libraries contained in this release of SANE.
22
23 The exception is that, if you link a SANE library with other files
24 to produce an executable, this does not by itself cause the
25 resulting executable to be covered by the GNU General Public
26 License. Your use of that executable is in no way restricted on
27 account of linking the SANE library code into it.
28
29 This exception does not, however, invalidate any other reasons why
30 the executable file might be covered by the GNU General Public
31 License.
32
33 If you submit changes to SANE to the maintainers to be included in
34 a subsequent release, you agree by submitting the changes that
35 those changes may be distributed with this exception intact.
36
37 If you write modifications of your own for SANE, it is your choice
38 whether to permit this exception to apply to your modifications.
39 If you do not wish that, delete this exception notice.
40 */
41
42 #define DEBUG_DECLARE_ONLY
43
44 #include "image.h"
45
46 #include <array>
47
48 namespace genesys {
49
50 struct PixelFormatDesc
51 {
52 PixelFormat format;
53 unsigned depth;
54 unsigned channels;
55 ColorOrder order;
56 };
57
58 const PixelFormatDesc s_known_pixel_formats[] = {
59 { PixelFormat::I1, 1, 1, ColorOrder::RGB },
60 { PixelFormat::I8, 8, 1, ColorOrder::RGB },
61 { PixelFormat::I16, 16, 1, ColorOrder::RGB },
62 { PixelFormat::RGB111, 1, 3, ColorOrder::RGB },
63 { PixelFormat::RGB888, 8, 3, ColorOrder::RGB },
64 { PixelFormat::RGB161616, 16, 3, ColorOrder::RGB },
65 { PixelFormat::BGR888, 8, 3, ColorOrder::BGR },
66 { PixelFormat::BGR161616, 16, 3, ColorOrder::BGR },
67 };
68
69
get_pixel_format_color_order(PixelFormat format)70 ColorOrder get_pixel_format_color_order(PixelFormat format)
71 {
72 for (const auto& desc : s_known_pixel_formats) {
73 if (desc.format == format)
74 return desc.order;
75 }
76 throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
77 }
78
79
get_pixel_format_depth(PixelFormat format)80 unsigned get_pixel_format_depth(PixelFormat format)
81 {
82 for (const auto& desc : s_known_pixel_formats) {
83 if (desc.format == format)
84 return desc.depth;
85 }
86 throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
87 }
88
get_pixel_channels(PixelFormat format)89 unsigned get_pixel_channels(PixelFormat format)
90 {
91 for (const auto& desc : s_known_pixel_formats) {
92 if (desc.format == format)
93 return desc.channels;
94 }
95 throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
96 }
97
get_pixel_row_bytes(PixelFormat format,std::size_t width)98 std::size_t get_pixel_row_bytes(PixelFormat format, std::size_t width)
99 {
100 std::size_t depth = get_pixel_format_depth(format) * get_pixel_channels(format);
101 std::size_t total_bits = depth * width;
102 return total_bits / 8 + ((total_bits % 8 > 0) ? 1 : 0);
103 }
104
get_pixels_from_row_bytes(PixelFormat format,std::size_t row_bytes)105 std::size_t get_pixels_from_row_bytes(PixelFormat format, std::size_t row_bytes)
106 {
107 std::size_t depth = get_pixel_format_depth(format) * get_pixel_channels(format);
108 return (row_bytes * 8) / depth;
109 }
110
create_pixel_format(unsigned depth,unsigned channels,ColorOrder order)111 PixelFormat create_pixel_format(unsigned depth, unsigned channels, ColorOrder order)
112 {
113 for (const auto& desc : s_known_pixel_formats) {
114 if (desc.depth == depth && desc.channels == channels && desc.order == order) {
115 return desc.format;
116 }
117 }
118 throw SaneException("Unknown pixel format %d %d %d", depth, channels,
119 static_cast<unsigned>(order));
120 }
121
read_bit(const std::uint8_t * data,std::size_t x)122 static inline unsigned read_bit(const std::uint8_t* data, std::size_t x)
123 {
124 return (data[x / 8] >> (7 - (x % 8))) & 0x1;
125 }
126
write_bit(std::uint8_t * data,std::size_t x,unsigned value)127 static inline void write_bit(std::uint8_t* data, std::size_t x, unsigned value)
128 {
129 value = (value & 0x1) << (7 - (x % 8));
130 std::uint8_t mask = 0x1 << (7 - (x % 8));
131
132 data[x / 8] = (data[x / 8] & ~mask) | (value & mask);
133 }
134
get_pixel_from_row(const std::uint8_t * data,std::size_t x,PixelFormat format)135 Pixel get_pixel_from_row(const std::uint8_t* data, std::size_t x, PixelFormat format)
136 {
137 switch (format) {
138 case PixelFormat::I1: {
139 std::uint16_t val = read_bit(data, x) ? 0xffff : 0x0000;
140 return Pixel(val, val, val);
141 }
142 case PixelFormat::RGB111: {
143 x *= 3;
144 std::uint16_t r = read_bit(data, x) ? 0xffff : 0x0000;
145 std::uint16_t g = read_bit(data, x + 1) ? 0xffff : 0x0000;
146 std::uint16_t b = read_bit(data, x + 2) ? 0xffff : 0x0000;
147 return Pixel(r, g, b);
148 }
149 case PixelFormat::I8: {
150 std::uint16_t val = std::uint16_t(data[x]) | (data[x] << 8);
151 return Pixel(val, val, val);
152 }
153 case PixelFormat::I16: {
154 x *= 2;
155 std::uint16_t val = std::uint16_t(data[x]) | (data[x + 1] << 8);
156 return Pixel(val, val, val);
157 }
158 case PixelFormat::RGB888: {
159 x *= 3;
160 std::uint16_t r = std::uint16_t(data[x]) | (data[x] << 8);
161 std::uint16_t g = std::uint16_t(data[x + 1]) | (data[x + 1] << 8);
162 std::uint16_t b = std::uint16_t(data[x + 2]) | (data[x + 2] << 8);
163 return Pixel(r, g, b);
164 }
165 case PixelFormat::BGR888: {
166 x *= 3;
167 std::uint16_t b = std::uint16_t(data[x]) | (data[x] << 8);
168 std::uint16_t g = std::uint16_t(data[x + 1]) | (data[x + 1] << 8);
169 std::uint16_t r = std::uint16_t(data[x + 2]) | (data[x + 2] << 8);
170 return Pixel(r, g, b);
171 }
172 case PixelFormat::RGB161616: {
173 x *= 6;
174 std::uint16_t r = std::uint16_t(data[x]) | (data[x + 1] << 8);
175 std::uint16_t g = std::uint16_t(data[x + 2]) | (data[x + 3] << 8);
176 std::uint16_t b = std::uint16_t(data[x + 4]) | (data[x + 5] << 8);
177 return Pixel(r, g, b);
178 }
179 case PixelFormat::BGR161616: {
180 x *= 6;
181 std::uint16_t b = std::uint16_t(data[x]) | (data[x + 1] << 8);
182 std::uint16_t g = std::uint16_t(data[x + 2]) | (data[x + 3] << 8);
183 std::uint16_t r = std::uint16_t(data[x + 4]) | (data[x + 5] << 8);
184 return Pixel(r, g, b);
185 }
186 default:
187 throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
188 }
189 }
190
set_pixel_to_row(std::uint8_t * data,std::size_t x,Pixel pixel,PixelFormat format)191 void set_pixel_to_row(std::uint8_t* data, std::size_t x, Pixel pixel, PixelFormat format)
192 {
193 switch (format) {
194 case PixelFormat::I1:
195 write_bit(data, x, pixel.r & 0x8000 ? 1 : 0);
196 return;
197 case PixelFormat::RGB111: {
198 x *= 3;
199 write_bit(data, x, pixel.r & 0x8000 ? 1 : 0);
200 write_bit(data, x + 1,pixel.g & 0x8000 ? 1 : 0);
201 write_bit(data, x + 2, pixel.b & 0x8000 ? 1 : 0);
202 return;
203 }
204 case PixelFormat::I8: {
205 float val = (pixel.r >> 8) * 0.3f;
206 val += (pixel.g >> 8) * 0.59f;
207 val += (pixel.b >> 8) * 0.11f;
208 data[x] = static_cast<std::uint16_t>(val);
209 return;
210 }
211 case PixelFormat::I16: {
212 x *= 2;
213 float val = pixel.r * 0.3f;
214 val += pixel.g * 0.59f;
215 val += pixel.b * 0.11f;
216 auto val16 = static_cast<std::uint16_t>(val);
217 data[x] = val16 & 0xff;
218 data[x + 1] = (val16 >> 8) & 0xff;
219 return;
220 }
221 case PixelFormat::RGB888: {
222 x *= 3;
223 data[x] = pixel.r >> 8;
224 data[x + 1] = pixel.g >> 8;
225 data[x + 2] = pixel.b >> 8;
226 return;
227 }
228 case PixelFormat::BGR888: {
229 x *= 3;
230 data[x] = pixel.b >> 8;
231 data[x + 1] = pixel.g >> 8;
232 data[x + 2] = pixel.r >> 8;
233 return;
234 }
235 case PixelFormat::RGB161616: {
236 x *= 6;
237 data[x] = pixel.r & 0xff;
238 data[x + 1] = (pixel.r >> 8) & 0xff;
239 data[x + 2] = pixel.g & 0xff;
240 data[x + 3] = (pixel.g >> 8) & 0xff;
241 data[x + 4] = pixel.b & 0xff;
242 data[x + 5] = (pixel.b >> 8) & 0xff;
243 return;
244 }
245 case PixelFormat::BGR161616:
246 x *= 6;
247 data[x] = pixel.b & 0xff;
248 data[x + 1] = (pixel.b >> 8) & 0xff;
249 data[x + 2] = pixel.g & 0xff;
250 data[x + 3] = (pixel.g >> 8) & 0xff;
251 data[x + 4] = pixel.r & 0xff;
252 data[x + 5] = (pixel.r >> 8) & 0xff;
253 return;
254 default:
255 throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
256 }
257 }
258
get_raw_pixel_from_row(const std::uint8_t * data,std::size_t x,PixelFormat format)259 RawPixel get_raw_pixel_from_row(const std::uint8_t* data, std::size_t x, PixelFormat format)
260 {
261 switch (format) {
262 case PixelFormat::I1:
263 return RawPixel(read_bit(data, x));
264 case PixelFormat::RGB111: {
265 x *= 3;
266 return RawPixel(read_bit(data, x) << 2 |
267 (read_bit(data, x + 1) << 1) |
268 (read_bit(data, x + 2)));
269 }
270 case PixelFormat::I8:
271 return RawPixel(data[x]);
272 case PixelFormat::I16: {
273 x *= 2;
274 return RawPixel(data[x], data[x + 1]);
275 }
276 case PixelFormat::RGB888:
277 case PixelFormat::BGR888: {
278 x *= 3;
279 return RawPixel(data[x], data[x + 1], data[x + 2]);
280 }
281 case PixelFormat::RGB161616:
282 case PixelFormat::BGR161616: {
283 x *= 6;
284 return RawPixel(data[x], data[x + 1], data[x + 2],
285 data[x + 3], data[x + 4], data[x + 5]);
286 }
287 default:
288 throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
289 }
290 }
291
set_raw_pixel_to_row(std::uint8_t * data,std::size_t x,RawPixel pixel,PixelFormat format)292 void set_raw_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel, PixelFormat format)
293 {
294 switch (format) {
295 case PixelFormat::I1:
296 write_bit(data, x, pixel.data[0] & 0x1);
297 return;
298 case PixelFormat::RGB111: {
299 x *= 3;
300 write_bit(data, x, (pixel.data[0] >> 2) & 0x1);
301 write_bit(data, x + 1, (pixel.data[0] >> 1) & 0x1);
302 write_bit(data, x + 2, (pixel.data[0]) & 0x1);
303 return;
304 }
305 case PixelFormat::I8:
306 data[x] = pixel.data[0];
307 return;
308 case PixelFormat::I16: {
309 x *= 2;
310 data[x] = pixel.data[0];
311 data[x + 1] = pixel.data[1];
312 return;
313 }
314 case PixelFormat::RGB888:
315 case PixelFormat::BGR888: {
316 x *= 3;
317 data[x] = pixel.data[0];
318 data[x + 1] = pixel.data[1];
319 data[x + 2] = pixel.data[2];
320 return;
321 }
322 case PixelFormat::RGB161616:
323 case PixelFormat::BGR161616: {
324 x *= 6;
325 data[x] = pixel.data[0];
326 data[x + 1] = pixel.data[1];
327 data[x + 2] = pixel.data[2];
328 data[x + 3] = pixel.data[3];
329 data[x + 4] = pixel.data[4];
330 data[x + 5] = pixel.data[5];
331 return;
332 }
333 default:
334 throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
335 }
336 }
337
get_raw_channel_from_row(const std::uint8_t * data,std::size_t x,unsigned channel,PixelFormat format)338 std::uint16_t get_raw_channel_from_row(const std::uint8_t* data, std::size_t x, unsigned channel,
339 PixelFormat format)
340 {
341 switch (format) {
342 case PixelFormat::I1:
343 return read_bit(data, x);
344 case PixelFormat::RGB111:
345 return read_bit(data, x * 3 + channel);
346 case PixelFormat::I8:
347 return data[x];
348 case PixelFormat::I16: {
349 x *= 2;
350 return data[x] | (data[x + 1] << 8);
351 }
352 case PixelFormat::RGB888:
353 case PixelFormat::BGR888:
354 return data[x * 3 + channel];
355 case PixelFormat::RGB161616:
356 case PixelFormat::BGR161616:
357 return data[x * 6 + channel * 2] | (data[x * 6 + channel * 2 + 1]) << 8;
358 default:
359 throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
360 }
361 }
362
set_raw_channel_to_row(std::uint8_t * data,std::size_t x,unsigned channel,std::uint16_t pixel,PixelFormat format)363 void set_raw_channel_to_row(std::uint8_t* data, std::size_t x, unsigned channel,
364 std::uint16_t pixel, PixelFormat format)
365 {
366 switch (format) {
367 case PixelFormat::I1:
368 write_bit(data, x, pixel & 0x1);
369 return;
370 case PixelFormat::RGB111: {
371 write_bit(data, x * 3 + channel, pixel & 0x1);
372 return;
373 }
374 case PixelFormat::I8:
375 data[x] = pixel;
376 return;
377 case PixelFormat::I16: {
378 x *= 2;
379 data[x] = pixel;
380 data[x + 1] = pixel >> 8;
381 return;
382 }
383 case PixelFormat::RGB888:
384 case PixelFormat::BGR888: {
385 x *= 3;
386 data[x + channel] = pixel;
387 return;
388 }
389 case PixelFormat::RGB161616:
390 case PixelFormat::BGR161616: {
391 x *= 6;
392 data[x + channel * 2] = pixel;
393 data[x + channel * 2 + 1] = pixel >> 8;
394 return;
395 }
396 default:
397 throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
398 }
399 }
400
401 template<PixelFormat Format>
get_pixel_from_row(const std::uint8_t * data,std::size_t x)402 Pixel get_pixel_from_row(const std::uint8_t* data, std::size_t x)
403 {
404 return get_pixel_from_row(data, x, Format);
405 }
406
407 template<PixelFormat Format>
set_pixel_to_row(std::uint8_t * data,std::size_t x,Pixel pixel)408 void set_pixel_to_row(std::uint8_t* data, std::size_t x, Pixel pixel)
409 {
410 set_pixel_to_row(data, x, pixel, Format);
411 }
412
413 template<PixelFormat Format>
get_raw_pixel_from_row(const std::uint8_t * data,std::size_t x)414 RawPixel get_raw_pixel_from_row(const std::uint8_t* data, std::size_t x)
415 {
416 return get_raw_pixel_from_row(data, x, Format);
417 }
418
419 template<PixelFormat Format>
set_raw_pixel_to_row(std::uint8_t * data,std::size_t x,RawPixel pixel)420 void set_raw_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel)
421 {
422 set_raw_pixel_to_row(data, x, pixel, Format);
423 }
424
425 template<PixelFormat Format>
get_raw_channel_from_row(const std::uint8_t * data,std::size_t x,unsigned channel)426 std::uint16_t get_raw_channel_from_row(const std::uint8_t* data, std::size_t x, unsigned channel)
427 {
428 return get_raw_channel_from_row(data, x, channel, Format);
429 }
430
431 template<PixelFormat Format>
set_raw_channel_to_row(std::uint8_t * data,std::size_t x,unsigned channel,std::uint16_t pixel)432 void set_raw_channel_to_row(std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel)
433 {
434 set_raw_channel_to_row(data, x, channel, pixel, Format);
435 }
436
437 template Pixel get_pixel_from_row<PixelFormat::I1>(const std::uint8_t* data, std::size_t x);
438 template Pixel get_pixel_from_row<PixelFormat::RGB111>(const std::uint8_t* data, std::size_t x);
439 template Pixel get_pixel_from_row<PixelFormat::I8>(const std::uint8_t* data, std::size_t x);
440 template Pixel get_pixel_from_row<PixelFormat::RGB888>(const std::uint8_t* data, std::size_t x);
441 template Pixel get_pixel_from_row<PixelFormat::BGR888>(const std::uint8_t* data, std::size_t x);
442 template Pixel get_pixel_from_row<PixelFormat::I16>(const std::uint8_t* data, std::size_t x);
443 template Pixel get_pixel_from_row<PixelFormat::RGB161616>(const std::uint8_t* data, std::size_t x);
444 template Pixel get_pixel_from_row<PixelFormat::BGR161616>(const std::uint8_t* data, std::size_t x);
445
446 template RawPixel get_raw_pixel_from_row<PixelFormat::I1>(const std::uint8_t* data, std::size_t x);
447 template RawPixel get_raw_pixel_from_row<PixelFormat::RGB111>(const std::uint8_t* data, std::size_t x);
448 template RawPixel get_raw_pixel_from_row<PixelFormat::I8>(const std::uint8_t* data, std::size_t x);
449 template RawPixel get_raw_pixel_from_row<PixelFormat::RGB888>(const std::uint8_t* data, std::size_t x);
450 template RawPixel get_raw_pixel_from_row<PixelFormat::BGR888>(const std::uint8_t* data, std::size_t x);
451 template RawPixel get_raw_pixel_from_row<PixelFormat::I16>(const std::uint8_t* data, std::size_t x);
452 template RawPixel get_raw_pixel_from_row<PixelFormat::RGB161616>(const std::uint8_t* data, std::size_t x);
453 template RawPixel get_raw_pixel_from_row<PixelFormat::BGR161616>(const std::uint8_t* data, std::size_t x);
454
455 template std::uint16_t get_raw_channel_from_row<PixelFormat::I1>(
456 const std::uint8_t* data, std::size_t x, unsigned channel);
457 template std::uint16_t get_raw_channel_from_row<PixelFormat::RGB111>(
458 const std::uint8_t* data, std::size_t x, unsigned channel);
459 template std::uint16_t get_raw_channel_from_row<PixelFormat::I8>(
460 const std::uint8_t* data, std::size_t x, unsigned channel);
461 template std::uint16_t get_raw_channel_from_row<PixelFormat::RGB888>(
462 const std::uint8_t* data, std::size_t x, unsigned channel);
463 template std::uint16_t get_raw_channel_from_row<PixelFormat::BGR888>(
464 const std::uint8_t* data, std::size_t x, unsigned channel);
465 template std::uint16_t get_raw_channel_from_row<PixelFormat::I16>(
466 const std::uint8_t* data, std::size_t x, unsigned channel);
467 template std::uint16_t get_raw_channel_from_row<PixelFormat::RGB161616>(
468 const std::uint8_t* data, std::size_t x, unsigned channel);
469 template std::uint16_t get_raw_channel_from_row<PixelFormat::BGR161616>
470 (const std::uint8_t* data, std::size_t x, unsigned channel);
471
472 template void set_pixel_to_row<PixelFormat::I1>(std::uint8_t* data, std::size_t x, Pixel pixel);
473 template void set_pixel_to_row<PixelFormat::RGB111>(std::uint8_t* data, std::size_t x, Pixel pixel);
474 template void set_pixel_to_row<PixelFormat::I8>(std::uint8_t* data, std::size_t x, Pixel pixel);
475 template void set_pixel_to_row<PixelFormat::RGB888>(std::uint8_t* data, std::size_t x, Pixel pixel);
476 template void set_pixel_to_row<PixelFormat::BGR888>(std::uint8_t* data, std::size_t x, Pixel pixel);
477 template void set_pixel_to_row<PixelFormat::I16>(std::uint8_t* data, std::size_t x, Pixel pixel);
478 template void set_pixel_to_row<PixelFormat::RGB161616>(std::uint8_t* data, std::size_t x, Pixel pixel);
479 template void set_pixel_to_row<PixelFormat::BGR161616>(std::uint8_t* data, std::size_t x, Pixel pixel);
480
481 template void set_raw_pixel_to_row<PixelFormat::I1>(std::uint8_t* data, std::size_t x, RawPixel pixel);
482 template void set_raw_pixel_to_row<PixelFormat::RGB111>(std::uint8_t* data, std::size_t x, RawPixel pixel);
483 template void set_raw_pixel_to_row<PixelFormat::I8>(std::uint8_t* data, std::size_t x, RawPixel pixel);
484 template void set_raw_pixel_to_row<PixelFormat::RGB888>(std::uint8_t* data, std::size_t x, RawPixel pixel);
485 template void set_raw_pixel_to_row<PixelFormat::BGR888>(std::uint8_t* data, std::size_t x, RawPixel pixel);
486 template void set_raw_pixel_to_row<PixelFormat::I16>(std::uint8_t* data, std::size_t x, RawPixel pixel);
487 template void set_raw_pixel_to_row<PixelFormat::RGB161616>(std::uint8_t* data, std::size_t x, RawPixel pixel);
488 template void set_raw_pixel_to_row<PixelFormat::BGR161616>(std::uint8_t* data, std::size_t x, RawPixel pixel);
489
490 template void set_raw_channel_to_row<PixelFormat::I1>(
491 std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
492 template void set_raw_channel_to_row<PixelFormat::RGB111>(
493 std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
494 template void set_raw_channel_to_row<PixelFormat::I8>(
495 std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
496 template void set_raw_channel_to_row<PixelFormat::RGB888>(
497 std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
498 template void set_raw_channel_to_row<PixelFormat::BGR888>(
499 std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
500 template void set_raw_channel_to_row<PixelFormat::I16>(
501 std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
502 template void set_raw_channel_to_row<PixelFormat::RGB161616>(
503 std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
504 template void set_raw_channel_to_row<PixelFormat::BGR161616>(
505 std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
506
507 } // namespace genesys
508