Merge branch 'genesys-image-full-ownership' into 'master'

genesys: Add class that handles full ownership of image data

See merge request sane-project/backends!188
merge-requests/190/merge
Povilas Kanapickas 2019-09-29 17:25:50 +00:00
commit 32c49e5ec1
11 zmienionych plików z 696 dodań i 527 usunięć

Wyświetl plik

@ -497,6 +497,7 @@ libgenesys_la_SOURCES = genesys.cc genesys.h \
genesys_row_buffer.h \
genesys_image_buffer.h genesys_image_buffer.cc \
genesys_image_pipeline.h genesys_image_pipeline.cc \
genesys_image_pixel.h genesys_image_pixel.cc \
genesys_image.h genesys_image.cc \
genesys_motor.h \
genesys_register.h \

Wyświetl plik

@ -117,19 +117,6 @@ enum class ColorOrder
BGR,
};
enum class PixelFormat
{
UNKNOWN,
I1,
RGB111,
I8,
RGB888,
BGR888,
I16,
RGB161616,
BGR161616,
};
enum Genesys_Model_Type
{
MODEL_UMAX_ASTRA_4500 = 0,

Wyświetl plik

@ -47,463 +47,47 @@
#include <array>
struct PixelFormatDesc
Image::Image() = default;
Image::Image(std::size_t width, std::size_t height, PixelFormat format) :
width_{width},
height_{height},
format_{format},
row_bytes_{get_pixel_row_bytes(format_, width_)}
{
PixelFormat format;
unsigned depth;
unsigned channels;
ColorOrder order;
};
const PixelFormatDesc s_known_pixel_formats[] = {
{ PixelFormat::I1, 1, 1, ColorOrder::RGB },
{ PixelFormat::I8, 8, 1, ColorOrder::RGB },
{ PixelFormat::I16, 16, 1, ColorOrder::RGB },
{ PixelFormat::RGB111, 1, 3, ColorOrder::RGB },
{ PixelFormat::RGB888, 8, 3, ColorOrder::RGB },
{ PixelFormat::RGB161616, 16, 3, ColorOrder::RGB },
{ PixelFormat::BGR888, 8, 3, ColorOrder::BGR },
{ PixelFormat::BGR161616, 16, 3, ColorOrder::BGR },
};
ColorOrder get_pixel_format_color_order(PixelFormat format)
{
for (const auto& desc : s_known_pixel_formats) {
if (desc.format == format)
return desc.order;
}
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
data_.resize(get_row_bytes() * height);
}
unsigned get_pixel_format_depth(PixelFormat format)
std::uint8_t* Image::get_row_ptr(std::size_t y)
{
for (const auto& desc : s_known_pixel_formats) {
if (desc.format == format)
return desc.depth;
}
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
return data_.data() + row_bytes_ * y;
}
unsigned get_pixel_channels(PixelFormat format)
const std::uint8_t* Image::get_row_ptr(std::size_t y) const
{
for (const auto& desc : s_known_pixel_formats) {
if (desc.format == format)
return desc.channels;
}
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
return data_.data() + row_bytes_ * y;
}
std::size_t get_pixel_row_bytes(PixelFormat format, std::size_t width)
Pixel Image::get_pixel(std::size_t x, std::size_t y) const
{
std::size_t depth = get_pixel_format_depth(format) * get_pixel_channels(format);
std::size_t total_bits = depth * width;
return total_bits / 8 + ((total_bits % 8 > 0) ? 1 : 0);
return get_pixel_from_row(get_row_ptr(y), x, format_);
}
std::size_t get_pixels_from_row_bytes(PixelFormat format, std::size_t row_bytes)
void Image::set_pixel(std::size_t x, std::size_t y, const Pixel& pixel)
{
std::size_t depth = get_pixel_format_depth(format) * get_pixel_channels(format);
return (row_bytes * 8) / depth;
set_pixel_to_row(get_row_ptr(y), x, pixel, format_);
}
PixelFormat create_pixel_format(unsigned depth, unsigned channels, ColorOrder order)
RawPixel Image::get_raw_pixel(std::size_t x, std::size_t y) const
{
for (const auto& desc : s_known_pixel_formats) {
if (desc.depth == depth && desc.channels == channels && desc.order == order) {
return desc.format;
}
}
throw SaneException("Unknown pixel format %d %d %d", depth, channels,
static_cast<unsigned>(order));
return get_raw_pixel_from_row(get_row_ptr(y), x, format_);
}
static inline unsigned read_bit(const std::uint8_t* data, std::size_t x)
void Image::set_raw_pixel(std::size_t x, std::size_t y, const RawPixel& pixel)
{
return (data[x / 8] >> (7 - (x % 8))) & 0x1;
set_raw_pixel_to_row(get_row_ptr(y), x, pixel, format_);
}
static inline void write_bit(std::uint8_t* data, std::size_t x, unsigned value)
{
value = (value & 0x1) << (7 - (x % 8));
std::uint8_t mask = 0x1 << (7 - (x % 8));
data[x / 8] = (data[x / 8] & ~mask) | (value & mask);
}
Pixel get_pixel_from_row(const std::uint8_t* data, std::size_t x, PixelFormat format)
{
switch (format) {
case PixelFormat::I1: {
std::uint16_t val = read_bit(data, x) ? 0xffff : 0x0000;
return Pixel(val, val, val);
}
case PixelFormat::RGB111: {
x *= 3;
std::uint16_t r = read_bit(data, x) ? 0xffff : 0x0000;
std::uint16_t g = read_bit(data, x + 1) ? 0xffff : 0x0000;
std::uint16_t b = read_bit(data, x + 2) ? 0xffff : 0x0000;
return Pixel(r, g, b);
}
case PixelFormat::I8: {
std::uint16_t val = std::uint16_t(data[x]) | (data[x] << 8);
return Pixel(val, val, val);
}
case PixelFormat::I16: {
x *= 2;
std::uint16_t val = std::uint16_t(data[x]) | (data[x + 1] << 8);
return Pixel(val, val, val);
}
case PixelFormat::RGB888: {
x *= 3;
std::uint16_t r = std::uint16_t(data[x]) | (data[x] << 8);
std::uint16_t g = std::uint16_t(data[x + 1]) | (data[x + 1] << 8);
std::uint16_t b = std::uint16_t(data[x + 2]) | (data[x + 2] << 8);
return Pixel(r, g, b);
}
case PixelFormat::BGR888: {
x *= 3;
std::uint16_t b = std::uint16_t(data[x]) | (data[x] << 8);
std::uint16_t g = std::uint16_t(data[x + 1]) | (data[x + 1] << 8);
std::uint16_t r = std::uint16_t(data[x + 2]) | (data[x + 2] << 8);
return Pixel(r, g, b);
}
case PixelFormat::RGB161616: {
x *= 6;
std::uint16_t r = std::uint16_t(data[x]) | (data[x + 1] << 8);
std::uint16_t g = std::uint16_t(data[x + 2]) | (data[x + 3] << 8);
std::uint16_t b = std::uint16_t(data[x + 4]) | (data[x + 5] << 8);
return Pixel(r, g, b);
}
case PixelFormat::BGR161616: {
x *= 6;
std::uint16_t b = std::uint16_t(data[x]) | (data[x + 1] << 8);
std::uint16_t g = std::uint16_t(data[x + 2]) | (data[x + 3] << 8);
std::uint16_t r = std::uint16_t(data[x + 4]) | (data[x + 5] << 8);
return Pixel(r, g, b);
}
default:
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
}
}
void set_pixel_to_row(std::uint8_t* data, std::size_t x, Pixel pixel, PixelFormat format)
{
switch (format) {
case PixelFormat::I1:
write_bit(data, x, pixel.r & 0x8000 ? 1 : 0);
return;
case PixelFormat::RGB111: {
x *= 3;
write_bit(data, x, pixel.r & 0x8000 ? 1 : 0);
write_bit(data, x + 1,pixel.g & 0x8000 ? 1 : 0);
write_bit(data, x + 2, pixel.b & 0x8000 ? 1 : 0);
return;
}
case PixelFormat::I8: {
float val = (pixel.r >> 8) * 0.3f;
val += (pixel.g >> 8) * 0.59;
val += (pixel.b >> 8) * 0.11;
data[x] = static_cast<uint16_t>(val);
return;
}
case PixelFormat::I16: {
x *= 2;
float val = pixel.r * 0.3f;
val += pixel.g * 0.59;
val += pixel.b * 0.11;
std::uint16_t val16 = val;
data[x] = val16 & 0xff;
data[x + 1] = (val16 >> 8) & 0xff;
return;
}
case PixelFormat::RGB888: {
x *= 3;
data[x] = pixel.r >> 8;
data[x + 1] = pixel.g >> 8;
data[x + 2] = pixel.b >> 8;
return;
}
case PixelFormat::BGR888: {
x *= 3;
data[x] = pixel.b >> 8;
data[x + 1] = pixel.g >> 8;
data[x + 2] = pixel.r >> 8;
return;
}
case PixelFormat::RGB161616: {
x *= 6;
data[x] = pixel.r & 0xff;
data[x + 1] = (pixel.r >> 8) & 0xff;
data[x + 2] = pixel.g & 0xff;
data[x + 3] = (pixel.g >> 8) & 0xff;
data[x + 4] = pixel.b & 0xff;
data[x + 5] = (pixel.b >> 8) & 0xff;
return;
}
case PixelFormat::BGR161616:
x *= 6;
data[x] = pixel.b & 0xff;
data[x + 1] = (pixel.b >> 8) & 0xff;
data[x + 2] = pixel.g & 0xff;
data[x + 3] = (pixel.g >> 8) & 0xff;
data[x + 4] = pixel.r & 0xff;
data[x + 5] = (pixel.r >> 8) & 0xff;
return;
default:
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
}
}
RawPixel get_raw_pixel_from_row(const std::uint8_t* data, std::size_t x, PixelFormat format)
{
switch (format) {
case PixelFormat::I1:
return RawPixel(read_bit(data, x));
case PixelFormat::RGB111: {
x *= 3;
return RawPixel(read_bit(data, x) << 2 |
(read_bit(data, x + 1) << 1) |
(read_bit(data, x + 2)));
}
case PixelFormat::I8:
return RawPixel(data[x]);
case PixelFormat::I16: {
x *= 2;
return RawPixel(data[x], data[x + 1]);
}
case PixelFormat::RGB888:
case PixelFormat::BGR888: {
x *= 3;
return RawPixel(data[x], data[x + 1], data[x + 2]);
}
case PixelFormat::RGB161616:
case PixelFormat::BGR161616: {
x *= 6;
return RawPixel(data[x], data[x + 1], data[x + 2],
data[x + 3], data[x + 4], data[x + 5]);
}
default:
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
}
}
void set_raw_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel, PixelFormat format)
{
switch (format) {
case PixelFormat::I1:
write_bit(data, x, pixel.data[0] & 0x1);
return;
case PixelFormat::RGB111: {
x *= 3;
write_bit(data, x, (pixel.data[0] >> 2) & 0x1);
write_bit(data, x + 1, (pixel.data[0] >> 1) & 0x1);
write_bit(data, x + 2, (pixel.data[0]) & 0x1);
return;
}
case PixelFormat::I8:
data[x] = pixel.data[0];
return;
case PixelFormat::I16: {
x *= 2;
data[x] = pixel.data[0];
data[x + 1] = pixel.data[1];
return;
}
case PixelFormat::RGB888:
case PixelFormat::BGR888: {
x *= 3;
data[x] = pixel.data[0];
data[x + 1] = pixel.data[1];
data[x + 2] = pixel.data[2];
return;
}
case PixelFormat::RGB161616:
case PixelFormat::BGR161616: {
x *= 6;
data[x] = pixel.data[0];
data[x + 1] = pixel.data[1];
data[x + 2] = pixel.data[2];
data[x + 3] = pixel.data[3];
data[x + 4] = pixel.data[4];
data[x + 5] = pixel.data[5];
return;
}
default:
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
}
}
std::uint16_t get_raw_channel_from_row(const std::uint8_t* data, std::size_t x, unsigned channel,
PixelFormat format)
{
switch (format) {
case PixelFormat::I1:
return read_bit(data, x);
case PixelFormat::RGB111:
return read_bit(data, x * 3 + channel);
case PixelFormat::I8:
return data[x];
case PixelFormat::I16: {
x *= 2;
return data[x] | (data[x + 1] << 8);
}
case PixelFormat::RGB888:
case PixelFormat::BGR888:
return data[x * 3 + channel];
case PixelFormat::RGB161616:
case PixelFormat::BGR161616:
return data[x * 6 + channel * 2] | (data[x * 6 + channel * 2 + 1]) << 8;
default:
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
}
}
void set_raw_channel_to_row(std::uint8_t* data, std::size_t x, unsigned channel,
std::uint16_t pixel, PixelFormat format)
{
switch (format) {
case PixelFormat::I1:
write_bit(data, x, pixel & 0x1);
return;
case PixelFormat::RGB111: {
write_bit(data, x * 3 + channel, pixel & 0x1);
return;
}
case PixelFormat::I8:
data[x] = pixel;
return;
case PixelFormat::I16: {
x *= 2;
data[x] = pixel;
data[x + 1] = pixel >> 8;
return;
}
case PixelFormat::RGB888:
case PixelFormat::BGR888: {
x *= 3;
data[x + channel] = pixel;
return;
}
case PixelFormat::RGB161616:
case PixelFormat::BGR161616: {
x *= 6;
data[x + channel * 2] = pixel;
data[x + channel * 2 + 1] = pixel >> 8;
return;
}
default:
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
}
}
template<PixelFormat Format>
Pixel get_pixel_from_row(const std::uint8_t* data, std::size_t x)
{
return get_pixel_from_row(data, x, Format);
}
template<PixelFormat Format>
void set_pixel_to_row(std::uint8_t* data, std::size_t x, Pixel pixel)
{
set_pixel_to_row(data, x, pixel, Format);
}
template<PixelFormat Format>
RawPixel get_raw_pixel_from_row(const std::uint8_t* data, std::size_t x)
{
return get_raw_pixel_from_row(data, x, Format);
}
template<PixelFormat Format>
void set_raw_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel)
{
set_raw_pixel_to_row(data, x, pixel, Format);
}
template<PixelFormat Format>
std::uint16_t get_raw_channel_from_row(const std::uint8_t* data, std::size_t x, unsigned channel)
{
return get_raw_channel_from_row(data, x, channel, Format);
}
template<PixelFormat Format>
void set_raw_channel_to_row(std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel)
{
set_raw_channel_to_row(data, x, channel, pixel, Format);
}
template Pixel get_pixel_from_row<PixelFormat::I1>(const std::uint8_t* data, std::size_t x);
template Pixel get_pixel_from_row<PixelFormat::RGB111>(const std::uint8_t* data, std::size_t x);
template Pixel get_pixel_from_row<PixelFormat::I8>(const std::uint8_t* data, std::size_t x);
template Pixel get_pixel_from_row<PixelFormat::RGB888>(const std::uint8_t* data, std::size_t x);
template Pixel get_pixel_from_row<PixelFormat::BGR888>(const std::uint8_t* data, std::size_t x);
template Pixel get_pixel_from_row<PixelFormat::I16>(const std::uint8_t* data, std::size_t x);
template Pixel get_pixel_from_row<PixelFormat::RGB161616>(const std::uint8_t* data, std::size_t x);
template Pixel get_pixel_from_row<PixelFormat::BGR161616>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::I1>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::RGB111>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::I8>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::RGB888>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::BGR888>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::I16>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::RGB161616>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::BGR161616>(const std::uint8_t* data, std::size_t x);
template std::uint16_t get_raw_channel_from_row<PixelFormat::I1>(
const std::uint8_t* data, std::size_t x, unsigned channel);
template std::uint16_t get_raw_channel_from_row<PixelFormat::RGB111>(
const std::uint8_t* data, std::size_t x, unsigned channel);
template std::uint16_t get_raw_channel_from_row<PixelFormat::I8>(
const std::uint8_t* data, std::size_t x, unsigned channel);
template std::uint16_t get_raw_channel_from_row<PixelFormat::RGB888>(
const std::uint8_t* data, std::size_t x, unsigned channel);
template std::uint16_t get_raw_channel_from_row<PixelFormat::BGR888>(
const std::uint8_t* data, std::size_t x, unsigned channel);
template std::uint16_t get_raw_channel_from_row<PixelFormat::I16>(
const std::uint8_t* data, std::size_t x, unsigned channel);
template std::uint16_t get_raw_channel_from_row<PixelFormat::RGB161616>(
const std::uint8_t* data, std::size_t x, unsigned channel);
template std::uint16_t get_raw_channel_from_row<PixelFormat::BGR161616>
(const std::uint8_t* data, std::size_t x, unsigned channel);
template void set_pixel_to_row<PixelFormat::I1>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_pixel_to_row<PixelFormat::RGB111>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_pixel_to_row<PixelFormat::I8>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_pixel_to_row<PixelFormat::RGB888>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_pixel_to_row<PixelFormat::BGR888>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_pixel_to_row<PixelFormat::I16>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_pixel_to_row<PixelFormat::RGB161616>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_pixel_to_row<PixelFormat::BGR161616>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_raw_pixel_to_row<PixelFormat::I1>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_pixel_to_row<PixelFormat::RGB111>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_pixel_to_row<PixelFormat::I8>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_pixel_to_row<PixelFormat::RGB888>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_pixel_to_row<PixelFormat::BGR888>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_pixel_to_row<PixelFormat::I16>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_pixel_to_row<PixelFormat::RGB161616>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_pixel_to_row<PixelFormat::BGR161616>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_channel_to_row<PixelFormat::I1>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
template void set_raw_channel_to_row<PixelFormat::RGB111>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
template void set_raw_channel_to_row<PixelFormat::I8>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
template void set_raw_channel_to_row<PixelFormat::RGB888>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
template void set_raw_channel_to_row<PixelFormat::BGR888>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
template void set_raw_channel_to_row<PixelFormat::I16>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
template void set_raw_channel_to_row<PixelFormat::RGB161616>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
template void set_raw_channel_to_row<PixelFormat::BGR161616>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
template<PixelFormat SrcFormat, PixelFormat DstFormat>
void convert_pixel_row_impl2(const std::uint8_t* in_data, std::uint8_t* out_data,
std::size_t count)

Wyświetl plik

@ -44,57 +44,38 @@
#ifndef BACKEND_GENESYS_IMAGE_H
#define BACKEND_GENESYS_IMAGE_H
#include "genesys_enums.h"
#include "genesys_error.h"
#include "genesys_image_buffer.h"
#include "genesys_image_pixel.h"
#include <vector>
#include <algorithm>
#include <memory>
class Image
{
public:
Image();
Image(std::size_t width, std::size_t height, PixelFormat format);
ColorOrder get_pixel_format_color_order(PixelFormat format);
unsigned get_pixel_format_depth(PixelFormat format);
unsigned get_pixel_channels(PixelFormat format);
std::size_t get_pixel_row_bytes(PixelFormat format, std::size_t width);
std::size_t get_width() const { return width_; }
std::size_t get_height() const { return height_; }
PixelFormat get_format() const { return format_; }
std::size_t get_row_bytes() const { return row_bytes_; }
std::size_t get_pixels_from_row_bytes(PixelFormat format, std::size_t row_bytes);
std::uint8_t* get_row_ptr(std::size_t y);
const std::uint8_t* get_row_ptr(std::size_t y) const;
PixelFormat create_pixel_format(unsigned depth, unsigned channels, ColorOrder order);
Pixel get_pixel(std::size_t x, std::size_t y) const;
void set_pixel(std::size_t x, std::size_t y, const Pixel& pixel);
// retrieves or sets the logical pixel values in 16-bit range.
Pixel get_pixel_from_row(const std::uint8_t* data, std::size_t x, PixelFormat format);
void set_pixel_to_row(std::uint8_t* data, std::size_t x, Pixel pixel, PixelFormat format);
RawPixel get_raw_pixel(std::size_t x, std::size_t y) const;
void set_raw_pixel(std::size_t x, std::size_t y, const RawPixel& pixel);
// retrieves or sets the physical pixel values. The low bytes of the RawPixel are interpreted as
// the retrieved values / values to set
RawPixel get_raw_pixel_from_row(const std::uint8_t* data, std::size_t x, PixelFormat format);
void set_raw_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel, PixelFormat format);
// retrieves or sets the physical value of specific channel of the pixel. The channels are numbered
// in the same order as the pixel is laid out in memory, that is, whichever channel comes first
// has the index 0. E.g. 0-th channel in RGB888 is the red byte, but in BGR888 is the blue byte.
std::uint16_t get_raw_channel_from_row(const std::uint8_t* data, std::size_t x, unsigned channel,
PixelFormat format);
void set_raw_channel_to_row(std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel,
PixelFormat format);
private:
std::size_t width_ = 0;
std::size_t height_ = 0;
PixelFormat format_ = PixelFormat::UNKNOWN;
std::size_t row_bytes_ = 0;
std::vector<std::uint8_t> data_;
};
void convert_pixel_row_format(const std::uint8_t* in_data, PixelFormat in_format,
std::uint8_t* out_data, PixelFormat out_format, std::size_t count);
template<PixelFormat Format>
Pixel get_pixel_from_row(const std::uint8_t* data, std::size_t x);
template<PixelFormat Format>
void set_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel);
template<PixelFormat Format>
Pixel get_raw_pixel_from_row(const std::uint8_t* data, std::size_t x);
template<PixelFormat Format>
void set_raw_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel);
template<PixelFormat Format>
std::uint16_t get_raw_channel_from_row(const std::uint8_t* data, std::size_t x, unsigned channel);
template<PixelFormat Format>
void set_raw_channel_to_row(std::uint8_t* data, std::size_t x, unsigned channel,
std::uint16_t pixel);
#endif // ifndef BACKEND_GENESYS_IMAGE_H

Wyświetl plik

@ -49,39 +49,6 @@
#include <algorithm>
#include <functional>
struct Pixel
{
Pixel() = default;
Pixel(std::uint16_t red, std::uint16_t green, std::uint16_t blue) :
r{red}, g{green}, b{blue} {}
std::uint16_t r = 0;
std::uint16_t g = 0;
std::uint16_t b = 0;
bool operator==(const Pixel& other) const
{
return r == other.r && g == other.g && b == other.b;
}
};
struct RawPixel
{
RawPixel() = default;
RawPixel(std::uint8_t d0) : data{d0, 0, 0, 0, 0, 0} {}
RawPixel(std::uint8_t d0, std::uint8_t d1) : data{d0, d1, 0, 0, 0, 0} {}
RawPixel(std::uint8_t d0, std::uint8_t d1, std::uint8_t d2) : data{d0, d1, d2, 0, 0, 0} {}
RawPixel(std::uint8_t d0, std::uint8_t d1, std::uint8_t d2,
std::uint8_t d3, std::uint8_t d4, std::uint8_t d5) : data{d0, d1, d2, d3, d4, d5} {}
std::uint8_t data[6] = {};
bool operator==(const RawPixel& other) const
{
return std::equal(std::begin(data), std::end(data),
std::begin(other.data));
}
};
// This class allows reading from row-based source in smaller or larger chunks of data
class ImageBuffer
{

Wyświetl plik

@ -44,6 +44,7 @@
#define DEBUG_DECLARE_ONLY
#include "genesys_image_pipeline.h"
#include "genesys_image.h"
#include "genesys_low.h"
#include <numeric>

Wyświetl plik

@ -44,7 +44,8 @@
#ifndef BACKEND_GENESYS_IMAGE_PIPELINE_H
#define BACKEND_GENESYS_IMAGE_PIPELINE_H
#include "genesys_image.h"
#include "genesys_image_pixel.h"
#include "genesys_image_buffer.h"
#include <algorithm>
#include <functional>

Wyświetl plik

@ -0,0 +1,505 @@
/* sane - Scanner Access Now Easy.
Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
This file is part of the SANE package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
As a special exception, the authors of SANE give permission for
additional uses of the libraries contained in this release of SANE.
The exception is that, if you link a SANE library with other files
to produce an executable, this does not by itself cause the
resulting executable to be covered by the GNU General Public
License. Your use of that executable is in no way restricted on
account of linking the SANE library code into it.
This exception does not, however, invalidate any other reasons why
the executable file might be covered by the GNU General Public
License.
If you submit changes to SANE to the maintainers to be included in
a subsequent release, you agree by submitting the changes that
those changes may be distributed with this exception intact.
If you write modifications of your own for SANE, it is your choice
whether to permit this exception to apply to your modifications.
If you do not wish that, delete this exception notice.
*/
#define DEBUG_DECLARE_ONLY
#include "genesys_image.h"
#include <array>
struct PixelFormatDesc
{
PixelFormat format;
unsigned depth;
unsigned channels;
ColorOrder order;
};
const PixelFormatDesc s_known_pixel_formats[] = {
{ PixelFormat::I1, 1, 1, ColorOrder::RGB },
{ PixelFormat::I8, 8, 1, ColorOrder::RGB },
{ PixelFormat::I16, 16, 1, ColorOrder::RGB },
{ PixelFormat::RGB111, 1, 3, ColorOrder::RGB },
{ PixelFormat::RGB888, 8, 3, ColorOrder::RGB },
{ PixelFormat::RGB161616, 16, 3, ColorOrder::RGB },
{ PixelFormat::BGR888, 8, 3, ColorOrder::BGR },
{ PixelFormat::BGR161616, 16, 3, ColorOrder::BGR },
};
ColorOrder get_pixel_format_color_order(PixelFormat format)
{
for (const auto& desc : s_known_pixel_formats) {
if (desc.format == format)
return desc.order;
}
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
}
unsigned get_pixel_format_depth(PixelFormat format)
{
for (const auto& desc : s_known_pixel_formats) {
if (desc.format == format)
return desc.depth;
}
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
}
unsigned get_pixel_channels(PixelFormat format)
{
for (const auto& desc : s_known_pixel_formats) {
if (desc.format == format)
return desc.channels;
}
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
}
std::size_t get_pixel_row_bytes(PixelFormat format, std::size_t width)
{
std::size_t depth = get_pixel_format_depth(format) * get_pixel_channels(format);
std::size_t total_bits = depth * width;
return total_bits / 8 + ((total_bits % 8 > 0) ? 1 : 0);
}
std::size_t get_pixels_from_row_bytes(PixelFormat format, std::size_t row_bytes)
{
std::size_t depth = get_pixel_format_depth(format) * get_pixel_channels(format);
return (row_bytes * 8) / depth;
}
PixelFormat create_pixel_format(unsigned depth, unsigned channels, ColorOrder order)
{
for (const auto& desc : s_known_pixel_formats) {
if (desc.depth == depth && desc.channels == channels && desc.order == order) {
return desc.format;
}
}
throw SaneException("Unknown pixel format %d %d %d", depth, channels,
static_cast<unsigned>(order));
}
static inline unsigned read_bit(const std::uint8_t* data, std::size_t x)
{
return (data[x / 8] >> (7 - (x % 8))) & 0x1;
}
static inline void write_bit(std::uint8_t* data, std::size_t x, unsigned value)
{
value = (value & 0x1) << (7 - (x % 8));
std::uint8_t mask = 0x1 << (7 - (x % 8));
data[x / 8] = (data[x / 8] & ~mask) | (value & mask);
}
Pixel get_pixel_from_row(const std::uint8_t* data, std::size_t x, PixelFormat format)
{
switch (format) {
case PixelFormat::I1: {
std::uint16_t val = read_bit(data, x) ? 0xffff : 0x0000;
return Pixel(val, val, val);
}
case PixelFormat::RGB111: {
x *= 3;
std::uint16_t r = read_bit(data, x) ? 0xffff : 0x0000;
std::uint16_t g = read_bit(data, x + 1) ? 0xffff : 0x0000;
std::uint16_t b = read_bit(data, x + 2) ? 0xffff : 0x0000;
return Pixel(r, g, b);
}
case PixelFormat::I8: {
std::uint16_t val = std::uint16_t(data[x]) | (data[x] << 8);
return Pixel(val, val, val);
}
case PixelFormat::I16: {
x *= 2;
std::uint16_t val = std::uint16_t(data[x]) | (data[x + 1] << 8);
return Pixel(val, val, val);
}
case PixelFormat::RGB888: {
x *= 3;
std::uint16_t r = std::uint16_t(data[x]) | (data[x] << 8);
std::uint16_t g = std::uint16_t(data[x + 1]) | (data[x + 1] << 8);
std::uint16_t b = std::uint16_t(data[x + 2]) | (data[x + 2] << 8);
return Pixel(r, g, b);
}
case PixelFormat::BGR888: {
x *= 3;
std::uint16_t b = std::uint16_t(data[x]) | (data[x] << 8);
std::uint16_t g = std::uint16_t(data[x + 1]) | (data[x + 1] << 8);
std::uint16_t r = std::uint16_t(data[x + 2]) | (data[x + 2] << 8);
return Pixel(r, g, b);
}
case PixelFormat::RGB161616: {
x *= 6;
std::uint16_t r = std::uint16_t(data[x]) | (data[x + 1] << 8);
std::uint16_t g = std::uint16_t(data[x + 2]) | (data[x + 3] << 8);
std::uint16_t b = std::uint16_t(data[x + 4]) | (data[x + 5] << 8);
return Pixel(r, g, b);
}
case PixelFormat::BGR161616: {
x *= 6;
std::uint16_t b = std::uint16_t(data[x]) | (data[x + 1] << 8);
std::uint16_t g = std::uint16_t(data[x + 2]) | (data[x + 3] << 8);
std::uint16_t r = std::uint16_t(data[x + 4]) | (data[x + 5] << 8);
return Pixel(r, g, b);
}
default:
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
}
}
void set_pixel_to_row(std::uint8_t* data, std::size_t x, Pixel pixel, PixelFormat format)
{
switch (format) {
case PixelFormat::I1:
write_bit(data, x, pixel.r & 0x8000 ? 1 : 0);
return;
case PixelFormat::RGB111: {
x *= 3;
write_bit(data, x, pixel.r & 0x8000 ? 1 : 0);
write_bit(data, x + 1,pixel.g & 0x8000 ? 1 : 0);
write_bit(data, x + 2, pixel.b & 0x8000 ? 1 : 0);
return;
}
case PixelFormat::I8: {
float val = (pixel.r >> 8) * 0.3f;
val += (pixel.g >> 8) * 0.59;
val += (pixel.b >> 8) * 0.11;
data[x] = static_cast<uint16_t>(val);
return;
}
case PixelFormat::I16: {
x *= 2;
float val = pixel.r * 0.3f;
val += pixel.g * 0.59;
val += pixel.b * 0.11;
std::uint16_t val16 = val;
data[x] = val16 & 0xff;
data[x + 1] = (val16 >> 8) & 0xff;
return;
}
case PixelFormat::RGB888: {
x *= 3;
data[x] = pixel.r >> 8;
data[x + 1] = pixel.g >> 8;
data[x + 2] = pixel.b >> 8;
return;
}
case PixelFormat::BGR888: {
x *= 3;
data[x] = pixel.b >> 8;
data[x + 1] = pixel.g >> 8;
data[x + 2] = pixel.r >> 8;
return;
}
case PixelFormat::RGB161616: {
x *= 6;
data[x] = pixel.r & 0xff;
data[x + 1] = (pixel.r >> 8) & 0xff;
data[x + 2] = pixel.g & 0xff;
data[x + 3] = (pixel.g >> 8) & 0xff;
data[x + 4] = pixel.b & 0xff;
data[x + 5] = (pixel.b >> 8) & 0xff;
return;
}
case PixelFormat::BGR161616:
x *= 6;
data[x] = pixel.b & 0xff;
data[x + 1] = (pixel.b >> 8) & 0xff;
data[x + 2] = pixel.g & 0xff;
data[x + 3] = (pixel.g >> 8) & 0xff;
data[x + 4] = pixel.r & 0xff;
data[x + 5] = (pixel.r >> 8) & 0xff;
return;
default:
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
}
}
RawPixel get_raw_pixel_from_row(const std::uint8_t* data, std::size_t x, PixelFormat format)
{
switch (format) {
case PixelFormat::I1:
return RawPixel(read_bit(data, x));
case PixelFormat::RGB111: {
x *= 3;
return RawPixel(read_bit(data, x) << 2 |
(read_bit(data, x + 1) << 1) |
(read_bit(data, x + 2)));
}
case PixelFormat::I8:
return RawPixel(data[x]);
case PixelFormat::I16: {
x *= 2;
return RawPixel(data[x], data[x + 1]);
}
case PixelFormat::RGB888:
case PixelFormat::BGR888: {
x *= 3;
return RawPixel(data[x], data[x + 1], data[x + 2]);
}
case PixelFormat::RGB161616:
case PixelFormat::BGR161616: {
x *= 6;
return RawPixel(data[x], data[x + 1], data[x + 2],
data[x + 3], data[x + 4], data[x + 5]);
}
default:
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
}
}
void set_raw_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel, PixelFormat format)
{
switch (format) {
case PixelFormat::I1:
write_bit(data, x, pixel.data[0] & 0x1);
return;
case PixelFormat::RGB111: {
x *= 3;
write_bit(data, x, (pixel.data[0] >> 2) & 0x1);
write_bit(data, x + 1, (pixel.data[0] >> 1) & 0x1);
write_bit(data, x + 2, (pixel.data[0]) & 0x1);
return;
}
case PixelFormat::I8:
data[x] = pixel.data[0];
return;
case PixelFormat::I16: {
x *= 2;
data[x] = pixel.data[0];
data[x + 1] = pixel.data[1];
return;
}
case PixelFormat::RGB888:
case PixelFormat::BGR888: {
x *= 3;
data[x] = pixel.data[0];
data[x + 1] = pixel.data[1];
data[x + 2] = pixel.data[2];
return;
}
case PixelFormat::RGB161616:
case PixelFormat::BGR161616: {
x *= 6;
data[x] = pixel.data[0];
data[x + 1] = pixel.data[1];
data[x + 2] = pixel.data[2];
data[x + 3] = pixel.data[3];
data[x + 4] = pixel.data[4];
data[x + 5] = pixel.data[5];
return;
}
default:
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
}
}
std::uint16_t get_raw_channel_from_row(const std::uint8_t* data, std::size_t x, unsigned channel,
PixelFormat format)
{
switch (format) {
case PixelFormat::I1:
return read_bit(data, x);
case PixelFormat::RGB111:
return read_bit(data, x * 3 + channel);
case PixelFormat::I8:
return data[x];
case PixelFormat::I16: {
x *= 2;
return data[x] | (data[x + 1] << 8);
}
case PixelFormat::RGB888:
case PixelFormat::BGR888:
return data[x * 3 + channel];
case PixelFormat::RGB161616:
case PixelFormat::BGR161616:
return data[x * 6 + channel * 2] | (data[x * 6 + channel * 2 + 1]) << 8;
default:
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
}
}
void set_raw_channel_to_row(std::uint8_t* data, std::size_t x, unsigned channel,
std::uint16_t pixel, PixelFormat format)
{
switch (format) {
case PixelFormat::I1:
write_bit(data, x, pixel & 0x1);
return;
case PixelFormat::RGB111: {
write_bit(data, x * 3 + channel, pixel & 0x1);
return;
}
case PixelFormat::I8:
data[x] = pixel;
return;
case PixelFormat::I16: {
x *= 2;
data[x] = pixel;
data[x + 1] = pixel >> 8;
return;
}
case PixelFormat::RGB888:
case PixelFormat::BGR888: {
x *= 3;
data[x + channel] = pixel;
return;
}
case PixelFormat::RGB161616:
case PixelFormat::BGR161616: {
x *= 6;
data[x + channel * 2] = pixel;
data[x + channel * 2 + 1] = pixel >> 8;
return;
}
default:
throw SaneException("Unknown pixel format %d", static_cast<unsigned>(format));
}
}
template<PixelFormat Format>
Pixel get_pixel_from_row(const std::uint8_t* data, std::size_t x)
{
return get_pixel_from_row(data, x, Format);
}
template<PixelFormat Format>
void set_pixel_to_row(std::uint8_t* data, std::size_t x, Pixel pixel)
{
set_pixel_to_row(data, x, pixel, Format);
}
template<PixelFormat Format>
RawPixel get_raw_pixel_from_row(const std::uint8_t* data, std::size_t x)
{
return get_raw_pixel_from_row(data, x, Format);
}
template<PixelFormat Format>
void set_raw_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel)
{
set_raw_pixel_to_row(data, x, pixel, Format);
}
template<PixelFormat Format>
std::uint16_t get_raw_channel_from_row(const std::uint8_t* data, std::size_t x, unsigned channel)
{
return get_raw_channel_from_row(data, x, channel, Format);
}
template<PixelFormat Format>
void set_raw_channel_to_row(std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel)
{
set_raw_channel_to_row(data, x, channel, pixel, Format);
}
template Pixel get_pixel_from_row<PixelFormat::I1>(const std::uint8_t* data, std::size_t x);
template Pixel get_pixel_from_row<PixelFormat::RGB111>(const std::uint8_t* data, std::size_t x);
template Pixel get_pixel_from_row<PixelFormat::I8>(const std::uint8_t* data, std::size_t x);
template Pixel get_pixel_from_row<PixelFormat::RGB888>(const std::uint8_t* data, std::size_t x);
template Pixel get_pixel_from_row<PixelFormat::BGR888>(const std::uint8_t* data, std::size_t x);
template Pixel get_pixel_from_row<PixelFormat::I16>(const std::uint8_t* data, std::size_t x);
template Pixel get_pixel_from_row<PixelFormat::RGB161616>(const std::uint8_t* data, std::size_t x);
template Pixel get_pixel_from_row<PixelFormat::BGR161616>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::I1>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::RGB111>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::I8>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::RGB888>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::BGR888>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::I16>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::RGB161616>(const std::uint8_t* data, std::size_t x);
template RawPixel get_raw_pixel_from_row<PixelFormat::BGR161616>(const std::uint8_t* data, std::size_t x);
template std::uint16_t get_raw_channel_from_row<PixelFormat::I1>(
const std::uint8_t* data, std::size_t x, unsigned channel);
template std::uint16_t get_raw_channel_from_row<PixelFormat::RGB111>(
const std::uint8_t* data, std::size_t x, unsigned channel);
template std::uint16_t get_raw_channel_from_row<PixelFormat::I8>(
const std::uint8_t* data, std::size_t x, unsigned channel);
template std::uint16_t get_raw_channel_from_row<PixelFormat::RGB888>(
const std::uint8_t* data, std::size_t x, unsigned channel);
template std::uint16_t get_raw_channel_from_row<PixelFormat::BGR888>(
const std::uint8_t* data, std::size_t x, unsigned channel);
template std::uint16_t get_raw_channel_from_row<PixelFormat::I16>(
const std::uint8_t* data, std::size_t x, unsigned channel);
template std::uint16_t get_raw_channel_from_row<PixelFormat::RGB161616>(
const std::uint8_t* data, std::size_t x, unsigned channel);
template std::uint16_t get_raw_channel_from_row<PixelFormat::BGR161616>
(const std::uint8_t* data, std::size_t x, unsigned channel);
template void set_pixel_to_row<PixelFormat::I1>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_pixel_to_row<PixelFormat::RGB111>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_pixel_to_row<PixelFormat::I8>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_pixel_to_row<PixelFormat::RGB888>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_pixel_to_row<PixelFormat::BGR888>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_pixel_to_row<PixelFormat::I16>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_pixel_to_row<PixelFormat::RGB161616>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_pixel_to_row<PixelFormat::BGR161616>(std::uint8_t* data, std::size_t x, Pixel pixel);
template void set_raw_pixel_to_row<PixelFormat::I1>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_pixel_to_row<PixelFormat::RGB111>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_pixel_to_row<PixelFormat::I8>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_pixel_to_row<PixelFormat::RGB888>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_pixel_to_row<PixelFormat::BGR888>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_pixel_to_row<PixelFormat::I16>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_pixel_to_row<PixelFormat::RGB161616>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_pixel_to_row<PixelFormat::BGR161616>(std::uint8_t* data, std::size_t x, RawPixel pixel);
template void set_raw_channel_to_row<PixelFormat::I1>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
template void set_raw_channel_to_row<PixelFormat::RGB111>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
template void set_raw_channel_to_row<PixelFormat::I8>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
template void set_raw_channel_to_row<PixelFormat::RGB888>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
template void set_raw_channel_to_row<PixelFormat::BGR888>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
template void set_raw_channel_to_row<PixelFormat::I16>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
template void set_raw_channel_to_row<PixelFormat::RGB161616>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);
template void set_raw_channel_to_row<PixelFormat::BGR161616>(
std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel);

Wyświetl plik

@ -0,0 +1,141 @@
/* sane - Scanner Access Now Easy.
Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
This file is part of the SANE package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
As a special exception, the authors of SANE give permission for
additional uses of the libraries contained in this release of SANE.
The exception is that, if you link a SANE library with other files
to produce an executable, this does not by itself cause the
resulting executable to be covered by the GNU General Public
License. Your use of that executable is in no way restricted on
account of linking the SANE library code into it.
This exception does not, however, invalidate any other reasons why
the executable file might be covered by the GNU General Public
License.
If you submit changes to SANE to the maintainers to be included in
a subsequent release, you agree by submitting the changes that
those changes may be distributed with this exception intact.
If you write modifications of your own for SANE, it is your choice
whether to permit this exception to apply to your modifications.
If you do not wish that, delete this exception notice.
*/
#ifndef BACKEND_GENESYS_IMAGE_PIXEL_H
#define BACKEND_GENESYS_IMAGE_PIXEL_H
#include "genesys_enums.h"
#include <algorithm>
#include <cstdint>
#include <cstddef>
enum class PixelFormat
{
UNKNOWN,
I1,
RGB111,
I8,
RGB888,
BGR888,
I16,
RGB161616,
BGR161616,
};
struct Pixel
{
Pixel() = default;
Pixel(std::uint16_t red, std::uint16_t green, std::uint16_t blue) :
r{red}, g{green}, b{blue} {}
std::uint16_t r = 0;
std::uint16_t g = 0;
std::uint16_t b = 0;
bool operator==(const Pixel& other) const
{
return r == other.r && g == other.g && b == other.b;
}
};
struct RawPixel
{
RawPixel() = default;
RawPixel(std::uint8_t d0) : data{d0, 0, 0, 0, 0, 0} {}
RawPixel(std::uint8_t d0, std::uint8_t d1) : data{d0, d1, 0, 0, 0, 0} {}
RawPixel(std::uint8_t d0, std::uint8_t d1, std::uint8_t d2) : data{d0, d1, d2, 0, 0, 0} {}
RawPixel(std::uint8_t d0, std::uint8_t d1, std::uint8_t d2,
std::uint8_t d3, std::uint8_t d4, std::uint8_t d5) : data{d0, d1, d2, d3, d4, d5} {}
std::uint8_t data[6] = {};
bool operator==(const RawPixel& other) const
{
return std::equal(std::begin(data), std::end(data),
std::begin(other.data));
}
};
ColorOrder get_pixel_format_color_order(PixelFormat format);
unsigned get_pixel_format_depth(PixelFormat format);
unsigned get_pixel_channels(PixelFormat format);
std::size_t get_pixel_row_bytes(PixelFormat format, std::size_t width);
std::size_t get_pixels_from_row_bytes(PixelFormat format, std::size_t row_bytes);
PixelFormat create_pixel_format(unsigned depth, unsigned channels, ColorOrder order);
// retrieves or sets the logical pixel values in 16-bit range.
Pixel get_pixel_from_row(const std::uint8_t* data, std::size_t x, PixelFormat format);
void set_pixel_to_row(std::uint8_t* data, std::size_t x, Pixel pixel, PixelFormat format);
// retrieves or sets the physical pixel values. The low bytes of the RawPixel are interpreted as
// the retrieved values / values to set
RawPixel get_raw_pixel_from_row(const std::uint8_t* data, std::size_t x, PixelFormat format);
void set_raw_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel, PixelFormat format);
// retrieves or sets the physical value of specific channel of the pixel. The channels are numbered
// in the same order as the pixel is laid out in memory, that is, whichever channel comes first
// has the index 0. E.g. 0-th channel in RGB888 is the red byte, but in BGR888 is the blue byte.
std::uint16_t get_raw_channel_from_row(const std::uint8_t* data, std::size_t x, unsigned channel,
PixelFormat format);
void set_raw_channel_to_row(std::uint8_t* data, std::size_t x, unsigned channel, std::uint16_t pixel,
PixelFormat format);
template<PixelFormat Format>
Pixel get_pixel_from_row(const std::uint8_t* data, std::size_t x);
template<PixelFormat Format>
void set_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel);
template<PixelFormat Format>
Pixel get_raw_pixel_from_row(const std::uint8_t* data, std::size_t x);
template<PixelFormat Format>
void set_raw_pixel_to_row(std::uint8_t* data, std::size_t x, RawPixel pixel);
template<PixelFormat Format>
std::uint16_t get_raw_channel_from_row(const std::uint8_t* data, std::size_t x, unsigned channel);
template<PixelFormat Format>
void set_raw_channel_to_row(std::uint8_t* data, std::size_t x, unsigned channel,
std::uint16_t pixel);
#endif // BACKEND_GENESYS_IMAGE_PIXEL_H

Wyświetl plik

@ -26,6 +26,7 @@
#include "minigtest.h"
#include "tests_printers.h"
#include "../../../backend/genesys_image.h"
#include "../../../backend/genesys_image_pipeline.h"
#include <vector>

Wyświetl plik

@ -23,7 +23,7 @@
#ifndef SANE_TESTSUITE_BACKEND_GENESYS_TESTS_PRINTERS_H
#define SANE_TESTSUITE_BACKEND_GENESYS_TESTS_PRINTERS_H
#include "../../../backend/genesys_image_buffer.h"
#include "../../../backend/genesys_image_pixel.h"
#include <iostream>
#include <iomanip>
#include <vector>