summaryrefslogtreecommitdiff
path: root/backend/genesys/utilities.h
diff options
context:
space:
mode:
Diffstat (limited to 'backend/genesys/utilities.h')
-rw-r--r--backend/genesys/utilities.h138
1 files changed, 138 insertions, 0 deletions
diff --git a/backend/genesys/utilities.h b/backend/genesys/utilities.h
index 1e268b5..fdab770 100644
--- a/backend/genesys/utilities.h
+++ b/backend/genesys/utilities.h
@@ -46,12 +46,81 @@
#include "error.h"
#include <algorithm>
+#include <cstdint>
#include <iostream>
#include <sstream>
#include <vector>
+
namespace genesys {
+// just like SANE_FIX and SANE_UNFIX except that the conversion is done by a function and argument
+// precision is handled correctly
+inline SANE_Word double_to_fixed(double v)
+{
+ return static_cast<SANE_Word>(v * (1 << SANE_FIXED_SCALE_SHIFT));
+}
+
+inline SANE_Word float_to_fixed(float v)
+{
+ return static_cast<SANE_Word>(v * (1 << SANE_FIXED_SCALE_SHIFT));
+}
+
+inline float fixed_to_float(SANE_Word v)
+{
+ return static_cast<float>(v) / (1 << SANE_FIXED_SCALE_SHIFT);
+}
+
+inline double fixed_to_double(SANE_Word v)
+{
+ return static_cast<double>(v) / (1 << SANE_FIXED_SCALE_SHIFT);
+}
+
+template<class T>
+inline T abs_diff(T a, T b)
+{
+ if (a < b) {
+ return b - a;
+ } else {
+ return a - b;
+ }
+}
+
+inline std::uint64_t align_multiple_floor(std::uint64_t x, std::uint64_t multiple)
+{
+ if (multiple == 0) {
+ return x;
+ }
+ return (x / multiple) * multiple;
+}
+
+inline std::uint64_t align_multiple_ceil(std::uint64_t x, std::uint64_t multiple)
+{
+ if (multiple == 0) {
+ return x;
+ }
+ return ((x + multiple - 1) / multiple) * multiple;
+}
+
+inline std::uint64_t multiply_by_depth_ceil(std::uint64_t pixels, std::uint64_t depth)
+{
+ if (depth == 1) {
+ return (pixels / 8) + ((pixels % 8) ? 1 : 0);
+ } else {
+ return pixels * (depth / 8);
+ }
+}
+
+template<class T>
+inline T clamp(const T& value, const T& lo, const T& hi)
+{
+ if (value < lo)
+ return lo;
+ if (value > hi)
+ return hi;
+ return value;
+}
+
template<class T>
void compute_array_percentile_approx(T* result, const T* data,
std::size_t line_count, std::size_t elements_per_line,
@@ -85,6 +154,75 @@ void compute_array_percentile_approx(T* result, const T* data,
}
}
+class Ratio
+{
+public:
+ Ratio() : multiplier_{1}, divisor_{1}
+ {
+ }
+
+ Ratio(unsigned multiplier, unsigned divisor) : multiplier_{multiplier}, divisor_{divisor}
+ {
+ }
+
+ unsigned multiplier() const { return multiplier_; }
+ unsigned divisor() const { return divisor_; }
+
+ unsigned apply(unsigned arg) const
+ {
+ return static_cast<std::uint64_t>(arg) * multiplier_ / divisor_;
+ }
+
+ int apply(int arg) const
+ {
+ return static_cast<std::int64_t>(arg) * multiplier_ / divisor_;
+ }
+
+ float apply(float arg) const
+ {
+ return arg * multiplier_ / divisor_;
+ }
+
+ unsigned apply_inverse(unsigned arg) const
+ {
+ return static_cast<std::uint64_t>(arg) * divisor_ / multiplier_;
+ }
+
+ int apply_inverse(int arg) const
+ {
+ return static_cast<std::int64_t>(arg) * divisor_ / multiplier_;
+ }
+
+ float apply_inverse(float arg) const
+ {
+ return arg * divisor_ / multiplier_;
+ }
+
+ bool operator==(const Ratio& other) const
+ {
+ return multiplier_ == other.multiplier_ && divisor_ == other.divisor_;
+ }
+private:
+ unsigned multiplier_;
+ unsigned divisor_;
+
+ template<class Stream>
+ friend void serialize(Stream& str, Ratio& x);
+};
+
+template<class Stream>
+void serialize(Stream& str, Ratio& x)
+{
+ serialize(str, x.multiplier_);
+ serialize(str, x.divisor_);
+}
+
+inline std::ostream& operator<<(std::ostream& out, const Ratio& ratio)
+{
+ out << ratio.multiplier() << "/" << ratio.divisor();
+ return out;
+}
+
template<class Char, class Traits>
class BasicStreamStateSaver
{