From f9d36d1a1b5150866d2a714380c7e7579e4e1189 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Thu, 17 Oct 2019 22:07:00 +0300 Subject: [PATCH] genesys: Add utility to compute percentille of columns in image --- backend/Makefile.am | 3 +- backend/genesys/utilities.h | 88 ++++++++++++++ testsuite/backend/genesys/Makefile.am | 3 +- testsuite/backend/genesys/tests.cpp | 1 + testsuite/backend/genesys/tests.h | 1 + testsuite/backend/genesys/tests_utilities.cpp | 110 ++++++++++++++++++ 6 files changed, 204 insertions(+), 2 deletions(-) create mode 100644 backend/genesys/utilities.h create mode 100644 testsuite/backend/genesys/tests_utilities.cpp diff --git a/backend/Makefile.am b/backend/Makefile.am index a2a73323b..c9dac45a9 100644 --- a/backend/Makefile.am +++ b/backend/Makefile.am @@ -516,7 +516,8 @@ libgenesys_la_SOURCES = genesys/genesys.cpp genesys/genesys.h \ genesys/tables_motor.cpp \ genesys/tables_motor_profile.cpp \ genesys/tables_sensor.cpp \ - genesys/low.cpp genesys/low.h + genesys/low.cpp genesys/low.h \ + genesys/utilities.h libgenesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys diff --git a/backend/genesys/utilities.h b/backend/genesys/utilities.h new file mode 100644 index 000000000..b0eb9318b --- /dev/null +++ b/backend/genesys/utilities.h @@ -0,0 +1,88 @@ +/* sane - Scanner Access Now Easy. + + Copyright (C) 2019 Povilas Kanapickas + + 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_UTILITIES_H +#define BACKEND_GENESYS_UTILITIES_H + +#include "error.h" +#include +#include + +namespace genesys { + +template +void compute_array_percentile_approx(T* result, const T* data, + std::size_t line_count, std::size_t elements_per_line, + float percentile) +{ + if (line_count == 0) { + throw SaneException("invalid line count"); + } + + if (line_count == 1) { + std::copy(data, data + elements_per_line, result); + return; + } + + std::vector column_elems; + column_elems.resize(line_count, 0); + + std::size_t select_elem = std::min(static_cast(line_count * percentile), + line_count - 1); + + auto select_it = column_elems.begin() + select_elem; + + for (std::size_t ix = 0; ix < elements_per_line; ++ix) { + for (std::size_t iy = 0; iy < line_count; ++iy) { + column_elems[iy] = data[iy * elements_per_line + ix]; + } + + std::nth_element(column_elems.begin(), select_it, column_elems.end()); + + *result++ = *select_it; + } +} + +} // namespace genesys + +#endif // BACKEND_GENESYS_UTILITIES_H diff --git a/testsuite/backend/genesys/Makefile.am b/testsuite/backend/genesys/Makefile.am index 4381cc001..c07d54979 100644 --- a/testsuite/backend/genesys/Makefile.am +++ b/testsuite/backend/genesys/Makefile.am @@ -24,6 +24,7 @@ genesys_tests_SOURCES = tests.cpp tests.h \ tests_calibration.cpp \ tests_image.cpp \ tests_image_pipeline.cpp \ - tests_row_buffer.cpp + tests_row_buffer.cpp \ + tests_utilities.cpp genesys_tests_LDADD = $(TEST_LDADD) diff --git a/testsuite/backend/genesys/tests.cpp b/testsuite/backend/genesys/tests.cpp index 6968a667a..4c172ddea 100644 --- a/testsuite/backend/genesys/tests.cpp +++ b/testsuite/backend/genesys/tests.cpp @@ -31,5 +31,6 @@ int main() genesys::test_image(); genesys::test_image_pipeline(); genesys::test_row_buffer(); + genesys::test_utilities(); return finish_tests(); } diff --git a/testsuite/backend/genesys/tests.h b/testsuite/backend/genesys/tests.h index b8cc7492c..3459c2b02 100644 --- a/testsuite/backend/genesys/tests.h +++ b/testsuite/backend/genesys/tests.h @@ -29,6 +29,7 @@ void test_calibration_parsing(); void test_image(); void test_image_pipeline(); void test_row_buffer(); +void test_utilities(); } // namespace genesys diff --git a/testsuite/backend/genesys/tests_utilities.cpp b/testsuite/backend/genesys/tests_utilities.cpp new file mode 100644 index 000000000..49b9abebb --- /dev/null +++ b/testsuite/backend/genesys/tests_utilities.cpp @@ -0,0 +1,110 @@ +/* sane - Scanner Access Now Easy. + + Copyright (C) 2019 Povilas Kanapickas + + 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. +*/ + +#define DEBUG_DECLARE_ONLY + +#include "tests.h" +#include "minigtest.h" +#include "tests_printers.h" + +#include "../../../backend/genesys/utilities.h" + +namespace genesys { + +void test_utilities_compute_array_percentile_approx_empty() +{ + std::vector data; + data.resize(1, 0); + + ASSERT_RAISES(compute_array_percentile_approx(data.data(), data.data(), 0, 0, 0.0f), + SaneException); +} + +void test_utilities_compute_array_percentile_approx_single_line() +{ + std::vector data = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + }; + std::vector expected = data; + std::vector result; + result.resize(data.size(), 0); + + compute_array_percentile_approx(result.data(), data.data(), 1, data.size(), 0.5f); + ASSERT_EQ(result, expected); +} + +void test_utilities_compute_array_percentile_approx_multiple_lines() +{ + std::vector data = { + 5, 17, 4, 14, 3, 9, 9, 5, 10, 1, + 6, 1, 0, 18, 8, 5, 11, 11, 15, 12, + 6, 8, 7, 3, 2, 15, 5, 12, 3, 3, + 6, 12, 17, 6, 7, 7, 1, 6, 3, 18, + 10, 5, 8, 0, 14, 3, 3, 7, 10, 5, + 18, 7, 3, 11, 0, 14, 12, 19, 18, 11, + 5, 16, 2, 9, 8, 2, 7, 6, 11, 18, + 16, 5, 2, 2, 14, 18, 19, 13, 16, 1, + 5, 9, 14, 6, 17, 16, 1, 1, 16, 0, + 19, 18, 4, 12, 0, 7, 15, 3, 2, 6, + }; + std::vector result; + result.resize(10, 0); + + std::vector expected = { + 5, 1, 0, 0, 0, 2, 1, 1, 2, 0, + }; + compute_array_percentile_approx(result.data(), data.data(), 10, 10, 0.0f); + ASSERT_EQ(result, expected); + + expected = { + 5, 5, 2, 3, 2, 5, 3, 5, 3, 1, + }; + compute_array_percentile_approx(result.data(), data.data(), 10, 10, 0.25f); + ASSERT_EQ(result, expected); + + expected = { + 6, 9, 4, 9, 8, 9, 9, 7, 11, 6, + }; + compute_array_percentile_approx(result.data(), data.data(), 10, 10, 0.5f); + ASSERT_EQ(result, expected); + + expected = { + 16, 16, 8, 12, 14, 15, 12, 12, 16, 12, + }; + compute_array_percentile_approx(result.data(), data.data(), 10, 10, 0.75f); + ASSERT_EQ(result, expected); + + expected = { + 19, 18, 17, 18, 17, 18, 19, 19, 18, 18, + }; + compute_array_percentile_approx(result.data(), data.data(), 10, 10, 1.0f); + ASSERT_EQ(result, expected); +} + +void test_utilities() +{ + test_utilities_compute_array_percentile_approx_empty(); + test_utilities_compute_array_percentile_approx_single_line(); + test_utilities_compute_array_percentile_approx_multiple_lines(); +} + +} // namespace genesys