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