genesys: Swap 16-bit pixel endian on big endian machines

merge-requests/183/head
Povilas Kanapickas 2019-09-13 17:04:00 +03:00
rodzic cae3015b66
commit 0b1bfa3f12
5 zmienionych plików z 111 dodań i 21 usunięć

Wyświetl plik

@ -45,25 +45,6 @@
* Conversion filters for genesys backend
*/
#if defined(DOUBLE_BYTE) && defined(WORDS_BIGENDIAN)
static void FUNC_NAME(genesys_reorder_components_endian) (uint8_t* src_data, uint8_t* dst_data,
unsigned int lines, unsigned int pixels,
unsigned int channels)
{
DBG_HELPER(dbg);
unsigned int c;
uint8_t *src = src_data;
uint8_t *dst = dst_data;
for(c = 0; c < lines * pixels * channels; c++) {
*dst++ = src[1];
*dst++ = src[0];
src += 2;
}
}
#endif /*defined(DOUBLE_BYTE) && defined(WORDS_BIGENDIAN)*/
static void FUNC_NAME(genesys_reverse_ccd) (uint8_t* src_data, uint8_t* dst_data,
unsigned int lines, unsigned int components_per_line,
unsigned int *ccd_shift, unsigned int component_count)

Wyświetl plik

@ -210,6 +210,29 @@ ImagePipelineNodeDeinterleaveLines::ImagePipelineNodeDeinterleaveLines(
interleaved_lines, pixels_per_chunk)
{}
ImagePipelineNodeSwap16BitEndian::ImagePipelineNodeSwap16BitEndian(ImagePipelineNode& source) :
source_(source),
needs_swapping_{false}
{
if (get_pixel_format_depth(source_.get_format()) == 16) {
needs_swapping_ = true;
} else {
DBG(DBG_info, "%s: this pipeline node does nothing for non 16-bit formats", __func__);
}
}
void ImagePipelineNodeSwap16BitEndian::get_next_row_data(std::uint8_t* out_data)
{
source_.get_next_row_data(out_data);
if (needs_swapping_) {
std::size_t pixels = get_row_bytes() / 2;
for (std::size_t i = 0; i < pixels; ++i) {
std::swap(*out_data, *(out_data + 1));
out_data += 2;
}
}
}
ImagePipelineNodeMergeMonoLines::ImagePipelineNodeMergeMonoLines(ImagePipelineNode& source,
ColorOrder color_order) :
source_(source),

Wyświetl plik

@ -248,6 +248,23 @@ public:
std::size_t pixels_per_chunk);
};
// A pipeline that swaps bytes in 16-bit components on big-endian systems
class ImagePipelineNodeSwap16BitEndian : public ImagePipelineNode
{
public:
ImagePipelineNodeSwap16BitEndian(ImagePipelineNode& source);
std::size_t get_width() const override { return source_.get_width(); }
std::size_t get_height() const override { return source_.get_height(); }
PixelFormat get_format() const override { return source_.get_format(); }
void get_next_row_data(std::uint8_t* out_data) override;
private:
ImagePipelineNode& source_;
bool needs_swapping_ = false;
};
// A pipeline node that merges 3 mono lines into a color channel
class ImagePipelineNodeMergeMonoLines : public ImagePipelineNode
{

Wyświetl plik

@ -1501,6 +1501,12 @@ void build_image_pipeline(Genesys_Device* dev, const ScanSession& session)
get_fake_usb_buffer_model(session), read_data_from_usb);
}
#ifdef WORDS_BIGENDIAN
if (get_pixel_format_depth(format) == 16) {
dev->pipeline.push_node<ImagePipelineNodeSwap16BitEndian>();
}
#endif
if (dev->model->is_cis && session.params.channels == 3) {
dev->pipeline.push_node<ImagePipelineNodeMergeMonoLines>(dev->model->line_mode_color_order);
}

Wyświetl plik

@ -175,7 +175,7 @@ void test_node_desegment_1_line()
ASSERT_EQ(out_data, expected_data);
}
void test_node_deinterleave_lines()
void test_node_deinterleave_lines_i8()
{
using Data = std::vector<std::uint8_t>;
@ -203,6 +203,67 @@ void test_node_deinterleave_lines()
ASSERT_EQ(out_data, expected_data);
}
void test_node_deinterleave_lines_rgb888()
{
using Data = std::vector<std::uint8_t>;
Data in_data = {
1, 2, 3, 7, 8, 9, 13, 14, 15, 19, 20, 21,
4, 5, 6, 10, 11, 12, 16, 17, 18, 22, 23, 24,
};
ImagePipelineStack stack;
stack.push_first_node<ImagePipelineNodeArraySource>(4, 2, PixelFormat::RGB888,
std::move(in_data));
stack.push_node<ImagePipelineNodeDeinterleaveLines>(2, 1);
ASSERT_EQ(stack.get_output_width(), 8u);
ASSERT_EQ(stack.get_output_height(), 1u);
ASSERT_EQ(stack.get_output_row_bytes(), 24u);
ASSERT_EQ(stack.get_output_format(), PixelFormat::RGB888);
auto out_data = stack.get_all_data();
Data expected_data;
expected_data.resize(24, 0);
std::iota(expected_data.begin(), expected_data.end(), 1); // will fill with 1, 2, 3, ..., 20
ASSERT_EQ(out_data, expected_data);
}
void test_node_swap_16bit_endian()
{
using Data = std::vector<std::uint8_t>;
Data in_data = {
0x10, 0x20, 0x30, 0x11, 0x21, 0x31,
0x12, 0x22, 0x32, 0x13, 0x23, 0x33,
0x14, 0x24, 0x34, 0x15, 0x25, 0x35,
0x16, 0x26, 0x36, 0x17, 0x27, 0x37,
};
ImagePipelineStack stack;
stack.push_first_node<ImagePipelineNodeArraySource>(4, 1, PixelFormat::RGB161616,
std::move(in_data));
stack.push_node<ImagePipelineNodeSwap16BitEndian>();
ASSERT_EQ(stack.get_output_width(), 4u);
ASSERT_EQ(stack.get_output_height(), 1u);
ASSERT_EQ(stack.get_output_row_bytes(), 24u);
ASSERT_EQ(stack.get_output_format(), PixelFormat::RGB161616);
auto out_data = stack.get_all_data();
Data expected_data = {
0x20, 0x10, 0x11, 0x30, 0x31, 0x21,
0x22, 0x12, 0x13, 0x32, 0x33, 0x23,
0x24, 0x14, 0x15, 0x34, 0x35, 0x25,
0x26, 0x16, 0x17, 0x36, 0x37, 0x27,
};
ASSERT_EQ(out_data, expected_data);
}
void test_node_merge_mono_lines()
{
using Data = std::vector<std::uint8_t>;
@ -335,7 +396,9 @@ void test_image_pipeline()
test_node_buffered_callable_source();
test_node_format_convert();
test_node_desegment_1_line();
test_node_deinterleave_lines();
test_node_deinterleave_lines_i8();
test_node_deinterleave_lines_rgb888();
test_node_swap_16bit_endian();
test_node_merge_mono_lines();
test_node_split_mono_lines();
test_node_component_shift_lines();