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 
21 #ifndef BACKEND_GENESYS_IMAGE_PIXEL_H
22 #define BACKEND_GENESYS_IMAGE_PIXEL_H
23 
24 #include "enums.h"
25 #include <algorithm>
26 #include <cstdint>
27 #include <cstddef>
28 
29 namespace genesys {
30 
31 // 16-bit values are in host endian
32 enum class PixelFormat
33 {
34     UNKNOWN,
35     I1,
36     RGB111,
37     I8,
38     RGB888,
39     BGR888,
40     I16,
41     RGB161616,
42     BGR161616,
43 };
44 
45 struct Pixel
46 {
47     Pixel() = default;
Pixelgenesys::Pixel48     Pixel(std::uint16_t red, std::uint16_t green, std::uint16_t blue) :
49         r{red}, g{green}, b{blue} {}
50 
51     std::uint16_t r = 0;
52     std::uint16_t g = 0;
53     std::uint16_t b = 0;
54 
operator ==genesys::Pixel55     bool operator==(const Pixel& other) const
56     {
57         return r == other.r && g == other.g && b == other.b;
58     }
59 };
60 
61 struct RawPixel
62 {
63     RawPixel() = default;
RawPixelgenesys::RawPixel64     RawPixel(std::uint8_t d0) : data{d0, 0, 0, 0, 0, 0} {}
RawPixelgenesys::RawPixel65     RawPixel(std::uint8_t d0, std::uint8_t d1) : data{d0, d1, 0, 0, 0, 0} {}
RawPixelgenesys::RawPixel66     RawPixel(std::uint8_t d0, std::uint8_t d1, std::uint8_t d2) : data{d0, d1, d2, 0, 0, 0} {}
RawPixelgenesys::RawPixel67     RawPixel(std::uint8_t d0, std::uint8_t d1, std::uint8_t d2,
68              std::uint8_t d3, std::uint8_t d4, std::uint8_t d5) : data{d0, d1, d2, d3, d4, d5} {}
69     std::uint8_t data[6] = {};
70 
operator ==genesys::RawPixel71     bool operator==(const RawPixel& other) const
72     {
73         return std::equal(std::begin(data), std::end(data),
74                           std::begin(other.data));
75     }
76 };
77 
78 ColorOrder get_pixel_format_color_order(PixelFormat format);
79 unsigned get_pixel_format_depth(PixelFormat format);
80 unsigned get_pixel_channels(PixelFormat format);
81 std::size_t get_pixel_row_bytes(PixelFormat format, std::size_t width);
82 
83 std::size_t get_pixels_from_row_bytes(PixelFormat format, std::size_t row_bytes);
84 
85 PixelFormat create_pixel_format(unsigned depth, unsigned channels, ColorOrder order);
86 
87 // retrieves or sets the logical pixel values in 16-bit range.
88 Pixel get_pixel_from_row(const std::uint8_t* data, std::size_t x, PixelFormat format);
89 void set_pixel_to_row(std::uint8_t* data, std::size_t x, Pixel pixel, PixelFormat format);
90 
91 // retrieves or sets the physical pixel values. The low bytes of the RawPixel are interpreted as
92 // the retrieved values / values to set
93 RawPixel get_raw_pixel_from_row(const std::uint8_t* data, std::size_t x, PixelFormat format);
94 void set_raw_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel, PixelFormat format);
95 
96 // retrieves or sets the physical value of specific channel of the pixel. The channels are numbered
97 // in the same order as the pixel is laid out in memory, that is, whichever channel comes first
98 // has the index 0. E.g. 0-th channel in RGB888 is the red byte, but in BGR888 is the blue byte.
99 std::uint16_t get_raw_channel_from_row(const std::uint8_t* data, std::size_t x, unsigned channel,
100                                        PixelFormat format);
101 void set_raw_channel_to_row(std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel,
102                             PixelFormat format);
103 
104 template<PixelFormat Format>
105 Pixel get_pixel_from_row(const std::uint8_t* data, std::size_t x);
106 template<PixelFormat Format>
107 void set_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel);
108 
109 template<PixelFormat Format>
110 Pixel get_raw_pixel_from_row(const std::uint8_t* data, std::size_t x);
111 template<PixelFormat Format>
112 void set_raw_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel);
113 
114 template<PixelFormat Format>
115 std::uint16_t get_raw_channel_from_row(const std::uint8_t* data, std::size_t x, unsigned channel);
116 template<PixelFormat Format>
117 void set_raw_channel_to_row(std::uint8_t* data, std::size_t x, unsigned channel,
118                             std::uint16_t pixel);
119 
120 } // namespace genesys
121 
122 #endif // BACKEND_GENESYS_IMAGE_PIXEL_H
123