1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci
3141cc406Sopenharmony_ci   Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
4141cc406Sopenharmony_ci
5141cc406Sopenharmony_ci   This file is part of the SANE package.
6141cc406Sopenharmony_ci
7141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
8141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
9141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
10141cc406Sopenharmony_ci   License, or (at your option) any later version.
11141cc406Sopenharmony_ci
12141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
13141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
14141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15141cc406Sopenharmony_ci   General Public License for more details.
16141cc406Sopenharmony_ci
17141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
18141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
19141cc406Sopenharmony_ci*/
20141cc406Sopenharmony_ci
21141cc406Sopenharmony_ci#define DEBUG_DECLARE_ONLY
22141cc406Sopenharmony_ci
23141cc406Sopenharmony_ci#include "image.h"
24141cc406Sopenharmony_ci
25141cc406Sopenharmony_ci#include <array>
26141cc406Sopenharmony_ci
27141cc406Sopenharmony_cinamespace genesys {
28141cc406Sopenharmony_ci
29141cc406Sopenharmony_cistruct PixelFormatDesc
30141cc406Sopenharmony_ci{
31141cc406Sopenharmony_ci    PixelFormat format;
32141cc406Sopenharmony_ci    unsigned depth;
33141cc406Sopenharmony_ci    unsigned channels;
34141cc406Sopenharmony_ci    ColorOrder order;
35141cc406Sopenharmony_ci};
36141cc406Sopenharmony_ci
37141cc406Sopenharmony_ciconst PixelFormatDesc s_known_pixel_formats[] = {
38141cc406Sopenharmony_ci    { PixelFormat::I1, 1, 1, ColorOrder::RGB },
39141cc406Sopenharmony_ci    { PixelFormat::I8, 8, 1, ColorOrder::RGB },
40141cc406Sopenharmony_ci    { PixelFormat::I16, 16, 1, ColorOrder::RGB },
41141cc406Sopenharmony_ci    { PixelFormat::RGB111, 1, 3, ColorOrder::RGB },
42141cc406Sopenharmony_ci    { PixelFormat::RGB888, 8, 3, ColorOrder::RGB },
43141cc406Sopenharmony_ci    { PixelFormat::RGB161616, 16, 3, ColorOrder::RGB },
44141cc406Sopenharmony_ci    { PixelFormat::BGR888, 8, 3, ColorOrder::BGR },
45141cc406Sopenharmony_ci    { PixelFormat::BGR161616, 16, 3, ColorOrder::BGR },
46141cc406Sopenharmony_ci};
47141cc406Sopenharmony_ci
48141cc406Sopenharmony_ci
49141cc406Sopenharmony_ciColorOrder get_pixel_format_color_order(PixelFormat format)
50141cc406Sopenharmony_ci{
51141cc406Sopenharmony_ci    for (const auto& desc : s_known_pixel_formats) {
52141cc406Sopenharmony_ci        if (desc.format == format)
53141cc406Sopenharmony_ci            return desc.order;
54141cc406Sopenharmony_ci    }
55141cc406Sopenharmony_ci    throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
56141cc406Sopenharmony_ci}
57141cc406Sopenharmony_ci
58141cc406Sopenharmony_ci
59141cc406Sopenharmony_ciunsigned get_pixel_format_depth(PixelFormat format)
60141cc406Sopenharmony_ci{
61141cc406Sopenharmony_ci    for (const auto& desc : s_known_pixel_formats) {
62141cc406Sopenharmony_ci        if (desc.format == format)
63141cc406Sopenharmony_ci            return desc.depth;
64141cc406Sopenharmony_ci    }
65141cc406Sopenharmony_ci    throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
66141cc406Sopenharmony_ci}
67141cc406Sopenharmony_ci
68141cc406Sopenharmony_ciunsigned get_pixel_channels(PixelFormat format)
69141cc406Sopenharmony_ci{
70141cc406Sopenharmony_ci    for (const auto& desc : s_known_pixel_formats) {
71141cc406Sopenharmony_ci        if (desc.format == format)
72141cc406Sopenharmony_ci            return desc.channels;
73141cc406Sopenharmony_ci    }
74141cc406Sopenharmony_ci    throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
75141cc406Sopenharmony_ci}
76141cc406Sopenharmony_ci
77141cc406Sopenharmony_cistd::size_t get_pixel_row_bytes(PixelFormat format, std::size_t width)
78141cc406Sopenharmony_ci{
79141cc406Sopenharmony_ci    std::size_t depth = get_pixel_format_depth(format) * get_pixel_channels(format);
80141cc406Sopenharmony_ci    std::size_t total_bits = depth * width;
81141cc406Sopenharmony_ci    return total_bits / 8 + ((total_bits % 8 > 0) ? 1 : 0);
82141cc406Sopenharmony_ci}
83141cc406Sopenharmony_ci
84141cc406Sopenharmony_cistd::size_t get_pixels_from_row_bytes(PixelFormat format, std::size_t row_bytes)
85141cc406Sopenharmony_ci{
86141cc406Sopenharmony_ci    std::size_t depth = get_pixel_format_depth(format) * get_pixel_channels(format);
87141cc406Sopenharmony_ci    return (row_bytes * 8) / depth;
88141cc406Sopenharmony_ci}
89141cc406Sopenharmony_ci
90141cc406Sopenharmony_ciPixelFormat create_pixel_format(unsigned depth, unsigned channels, ColorOrder order)
91141cc406Sopenharmony_ci{
92141cc406Sopenharmony_ci    for (const auto& desc : s_known_pixel_formats) {
93141cc406Sopenharmony_ci        if (desc.depth == depth && desc.channels == channels && desc.order == order) {
94141cc406Sopenharmony_ci            return desc.format;
95141cc406Sopenharmony_ci        }
96141cc406Sopenharmony_ci    }
97141cc406Sopenharmony_ci   throw SaneException("Unknown pixel format %d %d %d", depth, channels,
98141cc406Sopenharmony_ci                       static_cast<unsigned>(order));
99141cc406Sopenharmony_ci}
100141cc406Sopenharmony_ci
101141cc406Sopenharmony_cistatic inline unsigned read_bit(const std::uint8_t* data, std::size_t x)
102141cc406Sopenharmony_ci{
103141cc406Sopenharmony_ci    return (data[x / 8] >> (7 - (x % 8))) & 0x1;
104141cc406Sopenharmony_ci}
105141cc406Sopenharmony_ci
106141cc406Sopenharmony_cistatic inline void write_bit(std::uint8_t* data, std::size_t x, unsigned value)
107141cc406Sopenharmony_ci{
108141cc406Sopenharmony_ci    value = (value & 0x1) << (7 - (x % 8));
109141cc406Sopenharmony_ci    std::uint8_t mask = 0x1 << (7 - (x % 8));
110141cc406Sopenharmony_ci
111141cc406Sopenharmony_ci    data[x / 8] = (data[x / 8] & ~mask) | (value & mask);
112141cc406Sopenharmony_ci}
113141cc406Sopenharmony_ci
114141cc406Sopenharmony_ciPixel get_pixel_from_row(const std::uint8_t* data, std::size_t x, PixelFormat format)
115141cc406Sopenharmony_ci{
116141cc406Sopenharmony_ci    switch (format) {
117141cc406Sopenharmony_ci        case PixelFormat::I1: {
118141cc406Sopenharmony_ci            std::uint16_t val = read_bit(data, x) ? 0xffff : 0x0000;
119141cc406Sopenharmony_ci            return Pixel(val, val, val);
120141cc406Sopenharmony_ci        }
121141cc406Sopenharmony_ci        case PixelFormat::RGB111: {
122141cc406Sopenharmony_ci            x *= 3;
123141cc406Sopenharmony_ci            std::uint16_t r = read_bit(data, x) ? 0xffff : 0x0000;
124141cc406Sopenharmony_ci            std::uint16_t g = read_bit(data, x + 1) ? 0xffff : 0x0000;
125141cc406Sopenharmony_ci            std::uint16_t b = read_bit(data, x + 2) ? 0xffff : 0x0000;
126141cc406Sopenharmony_ci            return Pixel(r, g, b);
127141cc406Sopenharmony_ci        }
128141cc406Sopenharmony_ci        case PixelFormat::I8: {
129141cc406Sopenharmony_ci            std::uint16_t val = std::uint16_t(data[x]) | (data[x] << 8);
130141cc406Sopenharmony_ci            return Pixel(val, val, val);
131141cc406Sopenharmony_ci        }
132141cc406Sopenharmony_ci        case PixelFormat::I16: {
133141cc406Sopenharmony_ci            x *= 2;
134141cc406Sopenharmony_ci            std::uint16_t val = std::uint16_t(data[x]) | (data[x + 1] << 8);
135141cc406Sopenharmony_ci            return Pixel(val, val, val);
136141cc406Sopenharmony_ci        }
137141cc406Sopenharmony_ci        case PixelFormat::RGB888: {
138141cc406Sopenharmony_ci            x *= 3;
139141cc406Sopenharmony_ci            std::uint16_t r = std::uint16_t(data[x]) | (data[x] << 8);
140141cc406Sopenharmony_ci            std::uint16_t g = std::uint16_t(data[x + 1]) | (data[x + 1] << 8);
141141cc406Sopenharmony_ci            std::uint16_t b = std::uint16_t(data[x + 2]) | (data[x + 2] << 8);
142141cc406Sopenharmony_ci            return Pixel(r, g, b);
143141cc406Sopenharmony_ci        }
144141cc406Sopenharmony_ci        case PixelFormat::BGR888: {
145141cc406Sopenharmony_ci            x *= 3;
146141cc406Sopenharmony_ci            std::uint16_t b = std::uint16_t(data[x]) | (data[x] << 8);
147141cc406Sopenharmony_ci            std::uint16_t g = std::uint16_t(data[x + 1]) | (data[x + 1] << 8);
148141cc406Sopenharmony_ci            std::uint16_t r = std::uint16_t(data[x + 2]) | (data[x + 2] << 8);
149141cc406Sopenharmony_ci            return Pixel(r, g, b);
150141cc406Sopenharmony_ci        }
151141cc406Sopenharmony_ci        case PixelFormat::RGB161616: {
152141cc406Sopenharmony_ci            x *= 6;
153141cc406Sopenharmony_ci            std::uint16_t r = std::uint16_t(data[x]) | (data[x + 1] << 8);
154141cc406Sopenharmony_ci            std::uint16_t g = std::uint16_t(data[x + 2]) | (data[x + 3] << 8);
155141cc406Sopenharmony_ci            std::uint16_t b = std::uint16_t(data[x + 4]) | (data[x + 5] << 8);
156141cc406Sopenharmony_ci            return Pixel(r, g, b);
157141cc406Sopenharmony_ci        }
158141cc406Sopenharmony_ci        case PixelFormat::BGR161616: {
159141cc406Sopenharmony_ci            x *= 6;
160141cc406Sopenharmony_ci            std::uint16_t b = std::uint16_t(data[x]) | (data[x + 1] << 8);
161141cc406Sopenharmony_ci            std::uint16_t g = std::uint16_t(data[x + 2]) | (data[x + 3] << 8);
162141cc406Sopenharmony_ci            std::uint16_t r = std::uint16_t(data[x + 4]) | (data[x + 5] << 8);
163141cc406Sopenharmony_ci            return Pixel(r, g, b);
164141cc406Sopenharmony_ci        }
165141cc406Sopenharmony_ci        default:
166141cc406Sopenharmony_ci            throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
167141cc406Sopenharmony_ci    }
168141cc406Sopenharmony_ci}
169141cc406Sopenharmony_ci
170141cc406Sopenharmony_civoid set_pixel_to_row(std::uint8_t* data, std::size_t x, Pixel pixel, PixelFormat format)
171141cc406Sopenharmony_ci{
172141cc406Sopenharmony_ci    switch (format) {
173141cc406Sopenharmony_ci        case PixelFormat::I1:
174141cc406Sopenharmony_ci            write_bit(data, x, pixel.r & 0x8000 ? 1 : 0);
175141cc406Sopenharmony_ci            return;
176141cc406Sopenharmony_ci        case PixelFormat::RGB111: {
177141cc406Sopenharmony_ci            x *= 3;
178141cc406Sopenharmony_ci            write_bit(data, x, pixel.r & 0x8000 ? 1 : 0);
179141cc406Sopenharmony_ci            write_bit(data, x + 1,pixel.g & 0x8000 ? 1 : 0);
180141cc406Sopenharmony_ci            write_bit(data, x + 2, pixel.b & 0x8000 ? 1 : 0);
181141cc406Sopenharmony_ci            return;
182141cc406Sopenharmony_ci        }
183141cc406Sopenharmony_ci        case PixelFormat::I8: {
184141cc406Sopenharmony_ci            float val = (pixel.r >> 8) * 0.3f;
185141cc406Sopenharmony_ci            val += (pixel.g >> 8) * 0.59f;
186141cc406Sopenharmony_ci            val += (pixel.b >> 8) * 0.11f;
187141cc406Sopenharmony_ci            data[x] = static_cast<std::uint16_t>(val);
188141cc406Sopenharmony_ci            return;
189141cc406Sopenharmony_ci        }
190141cc406Sopenharmony_ci        case PixelFormat::I16: {
191141cc406Sopenharmony_ci            x *= 2;
192141cc406Sopenharmony_ci            float val = pixel.r * 0.3f;
193141cc406Sopenharmony_ci            val += pixel.g * 0.59f;
194141cc406Sopenharmony_ci            val += pixel.b * 0.11f;
195141cc406Sopenharmony_ci            auto val16 = static_cast<std::uint16_t>(val);
196141cc406Sopenharmony_ci            data[x] = val16 & 0xff;
197141cc406Sopenharmony_ci            data[x + 1] = (val16 >> 8) & 0xff;
198141cc406Sopenharmony_ci            return;
199141cc406Sopenharmony_ci        }
200141cc406Sopenharmony_ci        case PixelFormat::RGB888: {
201141cc406Sopenharmony_ci            x *= 3;
202141cc406Sopenharmony_ci            data[x] = pixel.r >> 8;
203141cc406Sopenharmony_ci            data[x + 1] = pixel.g >> 8;
204141cc406Sopenharmony_ci            data[x + 2] = pixel.b >> 8;
205141cc406Sopenharmony_ci            return;
206141cc406Sopenharmony_ci        }
207141cc406Sopenharmony_ci        case PixelFormat::BGR888: {
208141cc406Sopenharmony_ci            x *= 3;
209141cc406Sopenharmony_ci            data[x] = pixel.b >> 8;
210141cc406Sopenharmony_ci            data[x + 1] = pixel.g >> 8;
211141cc406Sopenharmony_ci            data[x + 2] = pixel.r >> 8;
212141cc406Sopenharmony_ci            return;
213141cc406Sopenharmony_ci        }
214141cc406Sopenharmony_ci        case PixelFormat::RGB161616: {
215141cc406Sopenharmony_ci            x *= 6;
216141cc406Sopenharmony_ci            data[x] = pixel.r & 0xff;
217141cc406Sopenharmony_ci            data[x + 1] = (pixel.r >> 8) & 0xff;
218141cc406Sopenharmony_ci            data[x + 2] = pixel.g & 0xff;
219141cc406Sopenharmony_ci            data[x + 3] = (pixel.g >> 8) & 0xff;
220141cc406Sopenharmony_ci            data[x + 4] = pixel.b & 0xff;
221141cc406Sopenharmony_ci            data[x + 5] = (pixel.b >> 8) & 0xff;
222141cc406Sopenharmony_ci            return;
223141cc406Sopenharmony_ci        }
224141cc406Sopenharmony_ci        case PixelFormat::BGR161616:
225141cc406Sopenharmony_ci            x *= 6;
226141cc406Sopenharmony_ci            data[x] = pixel.b & 0xff;
227141cc406Sopenharmony_ci            data[x + 1] = (pixel.b >> 8) & 0xff;
228141cc406Sopenharmony_ci            data[x + 2] = pixel.g & 0xff;
229141cc406Sopenharmony_ci            data[x + 3] = (pixel.g >> 8) & 0xff;
230141cc406Sopenharmony_ci            data[x + 4] = pixel.r & 0xff;
231141cc406Sopenharmony_ci            data[x + 5] = (pixel.r >> 8) & 0xff;
232141cc406Sopenharmony_ci            return;
233141cc406Sopenharmony_ci        default:
234141cc406Sopenharmony_ci            throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
235141cc406Sopenharmony_ci    }
236141cc406Sopenharmony_ci}
237141cc406Sopenharmony_ci
238141cc406Sopenharmony_ciRawPixel get_raw_pixel_from_row(const std::uint8_t* data, std::size_t x, PixelFormat format)
239141cc406Sopenharmony_ci{
240141cc406Sopenharmony_ci    switch (format) {
241141cc406Sopenharmony_ci        case PixelFormat::I1:
242141cc406Sopenharmony_ci            return RawPixel(read_bit(data, x));
243141cc406Sopenharmony_ci        case PixelFormat::RGB111: {
244141cc406Sopenharmony_ci            x *= 3;
245141cc406Sopenharmony_ci            return RawPixel(read_bit(data, x) << 2 |
246141cc406Sopenharmony_ci                            (read_bit(data, x + 1) << 1) |
247141cc406Sopenharmony_ci                            (read_bit(data, x + 2)));
248141cc406Sopenharmony_ci        }
249141cc406Sopenharmony_ci        case PixelFormat::I8:
250141cc406Sopenharmony_ci            return RawPixel(data[x]);
251141cc406Sopenharmony_ci        case PixelFormat::I16: {
252141cc406Sopenharmony_ci            x *= 2;
253141cc406Sopenharmony_ci            return RawPixel(data[x], data[x + 1]);
254141cc406Sopenharmony_ci        }
255141cc406Sopenharmony_ci        case PixelFormat::RGB888:
256141cc406Sopenharmony_ci        case PixelFormat::BGR888: {
257141cc406Sopenharmony_ci            x *= 3;
258141cc406Sopenharmony_ci            return RawPixel(data[x], data[x + 1], data[x + 2]);
259141cc406Sopenharmony_ci        }
260141cc406Sopenharmony_ci        case PixelFormat::RGB161616:
261141cc406Sopenharmony_ci        case PixelFormat::BGR161616: {
262141cc406Sopenharmony_ci            x *= 6;
263141cc406Sopenharmony_ci            return RawPixel(data[x], data[x + 1], data[x + 2],
264141cc406Sopenharmony_ci                            data[x + 3], data[x + 4], data[x + 5]);
265141cc406Sopenharmony_ci        }
266141cc406Sopenharmony_ci        default:
267141cc406Sopenharmony_ci            throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
268141cc406Sopenharmony_ci    }
269141cc406Sopenharmony_ci}
270141cc406Sopenharmony_ci
271141cc406Sopenharmony_civoid set_raw_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel, PixelFormat format)
272141cc406Sopenharmony_ci{
273141cc406Sopenharmony_ci    switch (format) {
274141cc406Sopenharmony_ci        case PixelFormat::I1:
275141cc406Sopenharmony_ci            write_bit(data, x, pixel.data[0] & 0x1);
276141cc406Sopenharmony_ci            return;
277141cc406Sopenharmony_ci        case PixelFormat::RGB111: {
278141cc406Sopenharmony_ci            x *= 3;
279141cc406Sopenharmony_ci            write_bit(data, x, (pixel.data[0] >> 2) & 0x1);
280141cc406Sopenharmony_ci            write_bit(data, x + 1, (pixel.data[0] >> 1) & 0x1);
281141cc406Sopenharmony_ci            write_bit(data, x + 2, (pixel.data[0]) & 0x1);
282141cc406Sopenharmony_ci            return;
283141cc406Sopenharmony_ci        }
284141cc406Sopenharmony_ci        case PixelFormat::I8:
285141cc406Sopenharmony_ci            data[x] = pixel.data[0];
286141cc406Sopenharmony_ci            return;
287141cc406Sopenharmony_ci        case PixelFormat::I16: {
288141cc406Sopenharmony_ci            x *= 2;
289141cc406Sopenharmony_ci            data[x] = pixel.data[0];
290141cc406Sopenharmony_ci            data[x + 1] = pixel.data[1];
291141cc406Sopenharmony_ci            return;
292141cc406Sopenharmony_ci        }
293141cc406Sopenharmony_ci        case PixelFormat::RGB888:
294141cc406Sopenharmony_ci        case PixelFormat::BGR888: {
295141cc406Sopenharmony_ci            x *= 3;
296141cc406Sopenharmony_ci            data[x] = pixel.data[0];
297141cc406Sopenharmony_ci            data[x + 1] = pixel.data[1];
298141cc406Sopenharmony_ci            data[x + 2] = pixel.data[2];
299141cc406Sopenharmony_ci            return;
300141cc406Sopenharmony_ci        }
301141cc406Sopenharmony_ci        case PixelFormat::RGB161616:
302141cc406Sopenharmony_ci        case PixelFormat::BGR161616: {
303141cc406Sopenharmony_ci            x *= 6;
304141cc406Sopenharmony_ci            data[x] = pixel.data[0];
305141cc406Sopenharmony_ci            data[x + 1] = pixel.data[1];
306141cc406Sopenharmony_ci            data[x + 2] = pixel.data[2];
307141cc406Sopenharmony_ci            data[x + 3] = pixel.data[3];
308141cc406Sopenharmony_ci            data[x + 4] = pixel.data[4];
309141cc406Sopenharmony_ci            data[x + 5] = pixel.data[5];
310141cc406Sopenharmony_ci            return;
311141cc406Sopenharmony_ci        }
312141cc406Sopenharmony_ci        default:
313141cc406Sopenharmony_ci            throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
314141cc406Sopenharmony_ci    }
315141cc406Sopenharmony_ci}
316141cc406Sopenharmony_ci
317141cc406Sopenharmony_cistd::uint16_t get_raw_channel_from_row(const std::uint8_t* data, std::size_t x, unsigned channel,
318141cc406Sopenharmony_ci                                       PixelFormat format)
319141cc406Sopenharmony_ci{
320141cc406Sopenharmony_ci    switch (format) {
321141cc406Sopenharmony_ci        case PixelFormat::I1:
322141cc406Sopenharmony_ci            return read_bit(data, x);
323141cc406Sopenharmony_ci        case PixelFormat::RGB111:
324141cc406Sopenharmony_ci            return read_bit(data, x * 3 + channel);
325141cc406Sopenharmony_ci        case PixelFormat::I8:
326141cc406Sopenharmony_ci            return data[x];
327141cc406Sopenharmony_ci        case PixelFormat::I16: {
328141cc406Sopenharmony_ci            x *= 2;
329141cc406Sopenharmony_ci            return data[x] | (data[x + 1] << 8);
330141cc406Sopenharmony_ci        }
331141cc406Sopenharmony_ci        case PixelFormat::RGB888:
332141cc406Sopenharmony_ci        case PixelFormat::BGR888:
333141cc406Sopenharmony_ci            return data[x * 3 + channel];
334141cc406Sopenharmony_ci        case PixelFormat::RGB161616:
335141cc406Sopenharmony_ci        case PixelFormat::BGR161616:
336141cc406Sopenharmony_ci            return data[x * 6 + channel * 2] | (data[x * 6 + channel * 2 + 1]) << 8;
337141cc406Sopenharmony_ci        default:
338141cc406Sopenharmony_ci            throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
339141cc406Sopenharmony_ci    }
340141cc406Sopenharmony_ci}
341141cc406Sopenharmony_ci
342141cc406Sopenharmony_civoid set_raw_channel_to_row(std::uint8_t* data, std::size_t x, unsigned channel,
343141cc406Sopenharmony_ci                            std::uint16_t pixel, PixelFormat format)
344141cc406Sopenharmony_ci{
345141cc406Sopenharmony_ci    switch (format) {
346141cc406Sopenharmony_ci        case PixelFormat::I1:
347141cc406Sopenharmony_ci            write_bit(data, x, pixel & 0x1);
348141cc406Sopenharmony_ci            return;
349141cc406Sopenharmony_ci        case PixelFormat::RGB111: {
350141cc406Sopenharmony_ci            write_bit(data, x * 3 + channel, pixel & 0x1);
351141cc406Sopenharmony_ci            return;
352141cc406Sopenharmony_ci        }
353141cc406Sopenharmony_ci        case PixelFormat::I8:
354141cc406Sopenharmony_ci            data[x] = pixel;
355141cc406Sopenharmony_ci            return;
356141cc406Sopenharmony_ci        case PixelFormat::I16: {
357141cc406Sopenharmony_ci            x *= 2;
358141cc406Sopenharmony_ci            data[x] = pixel;
359141cc406Sopenharmony_ci            data[x + 1] = pixel >> 8;
360141cc406Sopenharmony_ci            return;
361141cc406Sopenharmony_ci        }
362141cc406Sopenharmony_ci        case PixelFormat::RGB888:
363141cc406Sopenharmony_ci        case PixelFormat::BGR888: {
364141cc406Sopenharmony_ci            x *= 3;
365141cc406Sopenharmony_ci            data[x + channel] = pixel;
366141cc406Sopenharmony_ci            return;
367141cc406Sopenharmony_ci        }
368141cc406Sopenharmony_ci        case PixelFormat::RGB161616:
369141cc406Sopenharmony_ci        case PixelFormat::BGR161616: {
370141cc406Sopenharmony_ci            x *= 6;
371141cc406Sopenharmony_ci            data[x + channel * 2] = pixel;
372141cc406Sopenharmony_ci            data[x + channel * 2 + 1] = pixel >> 8;
373141cc406Sopenharmony_ci            return;
374141cc406Sopenharmony_ci        }
375141cc406Sopenharmony_ci        default:
376141cc406Sopenharmony_ci            throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
377141cc406Sopenharmony_ci    }
378141cc406Sopenharmony_ci}
379141cc406Sopenharmony_ci
380141cc406Sopenharmony_citemplate<PixelFormat Format>
381141cc406Sopenharmony_ciPixel get_pixel_from_row(const std::uint8_t* data, std::size_t x)
382141cc406Sopenharmony_ci{
383141cc406Sopenharmony_ci    return get_pixel_from_row(data, x, Format);
384141cc406Sopenharmony_ci}
385141cc406Sopenharmony_ci
386141cc406Sopenharmony_citemplate<PixelFormat Format>
387141cc406Sopenharmony_civoid set_pixel_to_row(std::uint8_t* data, std::size_t x, Pixel pixel)
388141cc406Sopenharmony_ci{
389141cc406Sopenharmony_ci    set_pixel_to_row(data, x, pixel, Format);
390141cc406Sopenharmony_ci}
391141cc406Sopenharmony_ci
392141cc406Sopenharmony_citemplate<PixelFormat Format>
393141cc406Sopenharmony_ciRawPixel get_raw_pixel_from_row(const std::uint8_t* data, std::size_t x)
394141cc406Sopenharmony_ci{
395141cc406Sopenharmony_ci    return get_raw_pixel_from_row(data, x, Format);
396141cc406Sopenharmony_ci}
397141cc406Sopenharmony_ci
398141cc406Sopenharmony_citemplate<PixelFormat Format>
399141cc406Sopenharmony_civoid set_raw_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel)
400141cc406Sopenharmony_ci{
401141cc406Sopenharmony_ci    set_raw_pixel_to_row(data, x, pixel, Format);
402141cc406Sopenharmony_ci}
403141cc406Sopenharmony_ci
404141cc406Sopenharmony_citemplate<PixelFormat Format>
405141cc406Sopenharmony_cistd::uint16_t get_raw_channel_from_row(const std::uint8_t* data, std::size_t x, unsigned channel)
406141cc406Sopenharmony_ci{
407141cc406Sopenharmony_ci    return get_raw_channel_from_row(data, x, channel, Format);
408141cc406Sopenharmony_ci}
409141cc406Sopenharmony_ci
410141cc406Sopenharmony_citemplate<PixelFormat Format>
411141cc406Sopenharmony_civoid set_raw_channel_to_row(std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel)
412141cc406Sopenharmony_ci{
413141cc406Sopenharmony_ci    set_raw_channel_to_row(data, x, channel, pixel, Format);
414141cc406Sopenharmony_ci}
415141cc406Sopenharmony_ci
416141cc406Sopenharmony_citemplate Pixel get_pixel_from_row<PixelFormat::I1>(const std::uint8_t* data, std::size_t x);
417141cc406Sopenharmony_citemplate Pixel get_pixel_from_row<PixelFormat::RGB111>(const std::uint8_t* data, std::size_t x);
418141cc406Sopenharmony_citemplate Pixel get_pixel_from_row<PixelFormat::I8>(const std::uint8_t* data, std::size_t x);
419141cc406Sopenharmony_citemplate Pixel get_pixel_from_row<PixelFormat::RGB888>(const std::uint8_t* data, std::size_t x);
420141cc406Sopenharmony_citemplate Pixel get_pixel_from_row<PixelFormat::BGR888>(const std::uint8_t* data, std::size_t x);
421141cc406Sopenharmony_citemplate Pixel get_pixel_from_row<PixelFormat::I16>(const std::uint8_t* data, std::size_t x);
422141cc406Sopenharmony_citemplate Pixel get_pixel_from_row<PixelFormat::RGB161616>(const std::uint8_t* data, std::size_t x);
423141cc406Sopenharmony_citemplate Pixel get_pixel_from_row<PixelFormat::BGR161616>(const std::uint8_t* data, std::size_t x);
424141cc406Sopenharmony_ci
425141cc406Sopenharmony_citemplate RawPixel get_raw_pixel_from_row<PixelFormat::I1>(const std::uint8_t* data, std::size_t x);
426141cc406Sopenharmony_citemplate RawPixel get_raw_pixel_from_row<PixelFormat::RGB111>(const std::uint8_t* data, std::size_t x);
427141cc406Sopenharmony_citemplate RawPixel get_raw_pixel_from_row<PixelFormat::I8>(const std::uint8_t* data, std::size_t x);
428141cc406Sopenharmony_citemplate RawPixel get_raw_pixel_from_row<PixelFormat::RGB888>(const std::uint8_t* data, std::size_t x);
429141cc406Sopenharmony_citemplate RawPixel get_raw_pixel_from_row<PixelFormat::BGR888>(const std::uint8_t* data, std::size_t x);
430141cc406Sopenharmony_citemplate RawPixel get_raw_pixel_from_row<PixelFormat::I16>(const std::uint8_t* data, std::size_t x);
431141cc406Sopenharmony_citemplate RawPixel get_raw_pixel_from_row<PixelFormat::RGB161616>(const std::uint8_t* data, std::size_t x);
432141cc406Sopenharmony_citemplate RawPixel get_raw_pixel_from_row<PixelFormat::BGR161616>(const std::uint8_t* data, std::size_t x);
433141cc406Sopenharmony_ci
434141cc406Sopenharmony_citemplate std::uint16_t get_raw_channel_from_row<PixelFormat::I1>(
435141cc406Sopenharmony_ci        const std::uint8_t* data, std::size_t x, unsigned channel);
436141cc406Sopenharmony_citemplate std::uint16_t get_raw_channel_from_row<PixelFormat::RGB111>(
437141cc406Sopenharmony_ci        const std::uint8_t* data, std::size_t x, unsigned channel);
438141cc406Sopenharmony_citemplate std::uint16_t get_raw_channel_from_row<PixelFormat::I8>(
439141cc406Sopenharmony_ci        const std::uint8_t* data, std::size_t x, unsigned channel);
440141cc406Sopenharmony_citemplate std::uint16_t get_raw_channel_from_row<PixelFormat::RGB888>(
441141cc406Sopenharmony_ci        const std::uint8_t* data, std::size_t x, unsigned channel);
442141cc406Sopenharmony_citemplate std::uint16_t get_raw_channel_from_row<PixelFormat::BGR888>(
443141cc406Sopenharmony_ci        const std::uint8_t* data, std::size_t x, unsigned channel);
444141cc406Sopenharmony_citemplate std::uint16_t get_raw_channel_from_row<PixelFormat::I16>(
445141cc406Sopenharmony_ci        const std::uint8_t* data, std::size_t x, unsigned channel);
446141cc406Sopenharmony_citemplate std::uint16_t get_raw_channel_from_row<PixelFormat::RGB161616>(
447141cc406Sopenharmony_ci        const std::uint8_t* data, std::size_t x, unsigned channel);
448141cc406Sopenharmony_citemplate std::uint16_t get_raw_channel_from_row<PixelFormat::BGR161616>
449141cc406Sopenharmony_ci        (const std::uint8_t* data, std::size_t x, unsigned channel);
450141cc406Sopenharmony_ci
451141cc406Sopenharmony_citemplate void set_pixel_to_row<PixelFormat::I1>(std::uint8_t* data, std::size_t x, Pixel pixel);
452141cc406Sopenharmony_citemplate void set_pixel_to_row<PixelFormat::RGB111>(std::uint8_t* data, std::size_t x, Pixel pixel);
453141cc406Sopenharmony_citemplate void set_pixel_to_row<PixelFormat::I8>(std::uint8_t* data, std::size_t x, Pixel pixel);
454141cc406Sopenharmony_citemplate void set_pixel_to_row<PixelFormat::RGB888>(std::uint8_t* data, std::size_t x, Pixel pixel);
455141cc406Sopenharmony_citemplate void set_pixel_to_row<PixelFormat::BGR888>(std::uint8_t* data, std::size_t x, Pixel pixel);
456141cc406Sopenharmony_citemplate void set_pixel_to_row<PixelFormat::I16>(std::uint8_t* data, std::size_t x, Pixel pixel);
457141cc406Sopenharmony_citemplate void set_pixel_to_row<PixelFormat::RGB161616>(std::uint8_t* data, std::size_t x, Pixel pixel);
458141cc406Sopenharmony_citemplate void set_pixel_to_row<PixelFormat::BGR161616>(std::uint8_t* data, std::size_t x, Pixel pixel);
459141cc406Sopenharmony_ci
460141cc406Sopenharmony_citemplate void set_raw_pixel_to_row<PixelFormat::I1>(std::uint8_t* data, std::size_t x, RawPixel pixel);
461141cc406Sopenharmony_citemplate void set_raw_pixel_to_row<PixelFormat::RGB111>(std::uint8_t* data, std::size_t x, RawPixel pixel);
462141cc406Sopenharmony_citemplate void set_raw_pixel_to_row<PixelFormat::I8>(std::uint8_t* data, std::size_t x, RawPixel pixel);
463141cc406Sopenharmony_citemplate void set_raw_pixel_to_row<PixelFormat::RGB888>(std::uint8_t* data, std::size_t x, RawPixel pixel);
464141cc406Sopenharmony_citemplate void set_raw_pixel_to_row<PixelFormat::BGR888>(std::uint8_t* data, std::size_t x, RawPixel pixel);
465141cc406Sopenharmony_citemplate void set_raw_pixel_to_row<PixelFormat::I16>(std::uint8_t* data, std::size_t x, RawPixel pixel);
466141cc406Sopenharmony_citemplate void set_raw_pixel_to_row<PixelFormat::RGB161616>(std::uint8_t* data, std::size_t x, RawPixel pixel);
467141cc406Sopenharmony_citemplate void set_raw_pixel_to_row<PixelFormat::BGR161616>(std::uint8_t* data, std::size_t x, RawPixel pixel);
468141cc406Sopenharmony_ci
469141cc406Sopenharmony_citemplate void set_raw_channel_to_row<PixelFormat::I1>(
470141cc406Sopenharmony_ci        std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
471141cc406Sopenharmony_citemplate void set_raw_channel_to_row<PixelFormat::RGB111>(
472141cc406Sopenharmony_ci        std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
473141cc406Sopenharmony_citemplate void set_raw_channel_to_row<PixelFormat::I8>(
474141cc406Sopenharmony_ci        std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
475141cc406Sopenharmony_citemplate void set_raw_channel_to_row<PixelFormat::RGB888>(
476141cc406Sopenharmony_ci        std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
477141cc406Sopenharmony_citemplate void set_raw_channel_to_row<PixelFormat::BGR888>(
478141cc406Sopenharmony_ci        std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
479141cc406Sopenharmony_citemplate void set_raw_channel_to_row<PixelFormat::I16>(
480141cc406Sopenharmony_ci        std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
481141cc406Sopenharmony_citemplate void set_raw_channel_to_row<PixelFormat::RGB161616>(
482141cc406Sopenharmony_ci        std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
483141cc406Sopenharmony_citemplate void set_raw_channel_to_row<PixelFormat::BGR161616>(
484141cc406Sopenharmony_ci        std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
485141cc406Sopenharmony_ci
486141cc406Sopenharmony_ci} // namespace genesys
487