diff options
Diffstat (limited to 'backend/genesys/utilities.h')
-rw-r--r-- | backend/genesys/utilities.h | 138 |
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 { |