From 003685ce2bec9dca8e971f67bde9b1751fd50cbb Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Tue, 20 Oct 2015 16:53:32 +1100 Subject: [PATCH] image: templatise on component count --- image.cpp | 122 ++++++++++++++++++++++++--------------------- image.hpp | 16 +++--- image.ipp | 20 ++++---- netpbm.cpp | 8 +-- netpbm.hpp | 6 +-- noise.cpp | 6 +-- noise.hpp | 2 +- noise.ipp | 2 +- noise/midpoint.cpp | 6 +-- noise/midpoint.hpp | 2 +- test/image.cpp | 2 +- tools/noise.cpp | 2 +- 12 files changed, 102 insertions(+), 92 deletions(-) diff --git a/image.cpp b/image.cpp index 387b7be3..1bc9dd56 100644 --- a/image.cpp +++ b/image.cpp @@ -22,21 +22,26 @@ using util::image::buffer; //----------------------------------------------------------------------------- -template -util::image::buffer::buffer (util::extentu<2> _size): +template +buffer::buffer (util::extentu<2> _size): m_size (_size), - m_stride (1, _size.w), - m_data (std::make_unique (_size.area ())) -{ ; } + m_stride (C, _size.w), + m_data (std::make_unique (_size.area () * C)) +{ + std::partial_sum (m_stride.begin (), + m_stride.end (), + m_stride.begin (), + std::multiplies ()); +} //----------------------------------------------------------------------------- -template +template template -util::image::buffer -util::image::buffer::alloc (void) const +buffer +buffer::alloc (void) const { - return buffer (m_size); + return buffer (m_size); } @@ -50,45 +55,46 @@ rescale (T v) //----------------------------------------------------------------------------- -template +template template -util::image::buffer -util::image::buffer::clone (void) const +util::image::buffer +util::image::buffer::clone (void) const { auto out = alloc (); - std::transform (begin (), end (), out.begin (), renormalise); + auto func = renormalise; + std::transform (begin (), end (), out.begin (), func); return out; } /////////////////////////////////////////////////////////////////////////////// -template +template const T& -buffer::operator[] (point<2,size_t> p) const +buffer::operator[] (point<2,size_t> p) const { - CHECK (util::all (p < size ())); + CHECK (util::all (p < extent ())); return begin ()[offset (p)]; } //----------------------------------------------------------------------------- -template +template T& -buffer::operator[] (point<2,size_t> p) +buffer::operator[] (point<2,size_t> p) { - CHECK (util::all (p < size ())); + CHECK (util::all (p < extent ())); return begin ()[offset (p)]; } //----------------------------------------------------------------------------- -template +template const T& -buffer::operator[] (size_t idx) const +buffer::operator[] (size_t idx) const { CHECK_LT (idx, size ()); @@ -97,9 +103,9 @@ buffer::operator[] (size_t idx) const //----------------------------------------------------------------------------- -template +template T& -buffer::operator[] (size_t idx) +buffer::operator[] (size_t idx) { CHECK_LT (idx, size ()); @@ -108,97 +114,101 @@ buffer::operator[] (size_t idx) /////////////////////////////////////////////////////////////////////////////// -template +template T* -buffer::data (void) +buffer::data (void) { return begin (); } //----------------------------------------------------------------------------- -template +template T* -buffer::begin (void) +buffer::begin (void) { return m_data.get (); } //----------------------------------------------------------------------------- -template +template T* -buffer::end (void) +buffer::end (void) { return begin () + m_size.back () * m_stride.back (); } //----------------------------------------------------------------------------- -template +template const T* -buffer::begin (void) const +buffer::begin (void) const { return cbegin (); } //----------------------------------------------------------------------------- -template +template const T* -buffer::end (void) const +buffer::end (void) const { return cend (); } //----------------------------------------------------------------------------- -template +template const T* -buffer::data (void) const +buffer::data (void) const { return begin (); } //----------------------------------------------------------------------------- -template +template const T* -buffer::cbegin (void) const +buffer::cbegin (void) const { return m_data.get (); } //----------------------------------------------------------------------------- -template +template const T* -buffer::cend (void) const +buffer::cend (void) const { return cbegin () + m_size.back () * m_stride.back (); } /////////////////////////////////////////////////////////////////////////////// -template struct util::image::buffer; -template struct util::image::buffer; -template struct util::image::buffer; -template struct util::image::buffer; -template struct util::image::buffer< int32_t>; -template struct util::image::buffer; -template struct util::image::buffer; -template util::image::buffer util::image::buffer::alloc (void) const; +#define INSTANTIATE_C_T_U(C,T,U) \ +template util::image::buffer util::image::buffer::alloc (void) const; \ +template util::image::buffer util::image::buffer::clone (void) const; \ +template util::image::buffer util::image::buffer::cast (void) const; -template util::image::buffer util::image::buffer::alloc (void) const; -template util::image::buffer util::image::buffer::clone (void) const; -template util::image::buffer util::image::buffer::clone (void) const; -template util::image::buffer util::image::buffer::clone (void) const; +#define INSTANTIATE_C_T(C,T) \ +template struct util::image::buffer; \ +INSTANTIATE_C_T_U(C,T,uint8_t) \ +INSTANTIATE_C_T_U(C,T,uint16_t) \ +INSTANTIATE_C_T_U(C,T,uint32_t) \ +INSTANTIATE_C_T_U(C,T,float) \ +INSTANTIATE_C_T_U(C,T,double) -template util::image::buffer util::image::buffer::alloc (void) const; -template util::image::buffer util::image::buffer::alloc (void) const; -template util::image::buffer< int32_t> util::image::buffer::alloc (void) const; -template util::image::buffer util::image::buffer::clone (void) const; +#define INSTANTIATE_C(C) \ +INSTANTIATE_C_T(C,uint8_t) \ +INSTANTIATE_C_T(C,uint16_t) \ +INSTANTIATE_C_T(C,uint32_t) \ +INSTANTIATE_C_T(C,float) \ +INSTANTIATE_C_T(C,double) -template util::image::buffer util::image::buffer::alloc (void) const; +INSTANTIATE_C(1) +INSTANTIATE_C(2) +INSTANTIATE_C(3) +INSTANTIATE_C(4) diff --git a/image.hpp b/image.hpp index a089d30a..d9338780 100644 --- a/image.hpp +++ b/image.hpp @@ -26,7 +26,7 @@ namespace util { namespace image { - template + template struct buffer { typedef T value_type; @@ -34,18 +34,18 @@ namespace util { namespace image { buffer (util::extentu<2>); buffer (util::extentu<2>, std::unique_ptr &&data); - buffer (const buffer&) = delete; - buffer (buffer &&) = default; - buffer& operator= (const buffer&) = default; - buffer& operator= (buffer&&) = default; + buffer (const buffer&) = delete; + buffer (buffer &&) = default; + buffer& operator= (const buffer&) = default; + buffer& operator= (buffer&&) = default; //--------------------------------------------------------------------- /// allocate and return a buffer of the same dimensions. contents are undefined. - template buffer alloc (void) const; + template buffer alloc (void) const; /// allocate and return a buffer with the same contents - template buffer clone (void) const; - template buffer cast (void) const { return clone (); } + template buffer clone (void) const; + template buffer cast (void) const { return clone (); } //--------------------------------------------------------------------- constexpr extent2u extent (void) const; diff --git a/image.ipp b/image.ipp index 3fc32a4f..95bf6758 100644 --- a/image.ipp +++ b/image.ipp @@ -21,45 +21,45 @@ namespace util { namespace image { //------------------------------------------------------------------------- - template + template constexpr extent2u - buffer::extent (void) const + buffer::extent (void) const { return m_size; } //------------------------------------------------------------------------- - template + template constexpr vector2u - buffer::stride (void) const + buffer::stride (void) const { return m_stride; } //------------------------------------------------------------------------- - template + template constexpr size_t - buffer::offset (point<2,size_t> p) const + buffer::offset (point<2,size_t> p) const { return dot (stride (), p); } //------------------------------------------------------------------------- - template + template constexpr size_t - buffer::size (void) const + buffer::size (void) const { return extent ().back () * stride ().back (); } //------------------------------------------------------------------------- - template + template constexpr bool - buffer::is_packed (void) const + buffer::is_packed (void) const { return stride ().back () == extent ().back (); } diff --git a/netpbm.cpp b/netpbm.cpp index b105bcf1..5a44bf4f 100644 --- a/netpbm.cpp +++ b/netpbm.cpp @@ -25,7 +25,7 @@ // HACK: This does not support the full header structure with any robustness. // In particular it will abort when it sees a comment. If you want better // support use waif, or port its implementation. -util::image::buffer +util::image::buffer<1,uint8_t> util::pgm::read (const boost::filesystem::path &path) { util::mapped_file raw (path); @@ -48,7 +48,7 @@ util::pgm::read (const boost::filesystem::path &path) if (expected != remain) throw std::runtime_error ("expected data size mismatch"); - util::image::buffer out ({width, height}); + util::image::buffer<1,uint8_t> out ({width, height}); CHECK (out.is_packed ()); std::copy (raw.begin () + cooked.tellg () - 1, raw.end (), out.begin ()); @@ -85,7 +85,7 @@ write_netpbm (const uint8_t *restrict pixels, //----------------------------------------------------------------------------- void -util::pgm::write (const util::image::buffer &src, +util::pgm::write (const util::image::buffer<1,uint8_t> &src, std::ostream &dst) { write (src.begin (), src.extent ().w, src.extent ().h, src.stride ().y, dst); @@ -94,7 +94,7 @@ util::pgm::write (const util::image::buffer &src, //----------------------------------------------------------------------------- void -util::pgm::write (const util::image::buffer &src, +util::pgm::write (const util::image::buffer<1,uint8_t> &src, const boost::filesystem::path &path) { std::ofstream dst (path.string ()); diff --git a/netpbm.hpp b/netpbm.hpp index 04339c2e..21df7806 100644 --- a/netpbm.hpp +++ b/netpbm.hpp @@ -27,11 +27,11 @@ namespace util { // Portable GrayMap: single component greyscale. struct pgm { - static image::buffer read (const boost::filesystem::path&); + static image::buffer<1,uint8_t> read (const boost::filesystem::path&); - static void write (const image::buffer &src, + static void write (const image::buffer<1,uint8_t> &src, const boost::filesystem::path &dst); - static void write (const image::buffer &src, + static void write (const image::buffer<1,uint8_t> &src, std::ostream &dst); static void write (const uint8_t *restrict pixels, diff --git a/noise.cpp b/noise.cpp index 33b0ed97..fc1d32a7 100644 --- a/noise.cpp +++ b/noise.cpp @@ -26,7 +26,7 @@ //----------------------------------------------------------------------------- template void -util::noise::fill (image::buffer &pixels, +util::noise::fill (image::buffer<1,T> &pixels, const util::noise::fractal &gen) { size_t h = pixels.h, s = pixels.s, w = pixels.w; @@ -37,8 +37,8 @@ util::noise::fill (image::buffer &pixels, data[y * s + x] = gen ({T(x), T(y)}); } -template void util::noise::fill (image::buffer&, const util::noise::fractal&); -template void util::noise::fill (image::buffer&, const util::noise::fractal&); +template void util::noise::fill (image::buffer<1,float>&, const util::noise::fractal&); +template void util::noise::fill (image::buffer<1,double>&, const util::noise::fractal&); //----------------------------------------------------------------------------- diff --git a/noise.hpp b/noise.hpp index 8f234190..efd22cee 100644 --- a/noise.hpp +++ b/noise.hpp @@ -24,7 +24,7 @@ namespace util { namespace noise { template - void fill (image::buffer&, const G&); + void fill (image::buffer<1,T>&, const G&); } } #include "noise.ipp" diff --git a/noise.ipp b/noise.ipp index 3a62bbb8..bc851f36 100644 --- a/noise.ipp +++ b/noise.ipp @@ -23,7 +23,7 @@ namespace util { namespace noise { //------------------------------------------------------------------------- template void - fill (image::buffer &pixels, const G& gen) + fill (image::buffer<1,T> &pixels, const G& gen) { size_t h = pixels.h, s = pixels.s, w = pixels.w; T *data = pixels.data (); diff --git a/noise/midpoint.cpp b/noise/midpoint.cpp index 6f158ccb..40072664 100644 --- a/noise/midpoint.cpp +++ b/noise/midpoint.cpp @@ -25,7 +25,7 @@ // assumes corner points have been assigned their weights template static void -fill (util::image::buffer &img, +fill (util::image::buffer<1,T> &img, uint64_t seed, util::region2u target, float scale, @@ -99,7 +99,7 @@ fill (util::image::buffer &img, /////////////////////////////////////////////////////////////////////////////// template void -util::noise::midpoint (image::buffer &img, uint64_t seed, float persistence, float sides) +util::noise::midpoint (image::buffer<1,T> &img, uint64_t seed, float persistence, float sides) { auto ext = img.extent (); @@ -118,4 +118,4 @@ util::noise::midpoint (image::buffer &img, uint64_t seed, float persistence, //----------------------------------------------------------------------------- -template void util::noise::midpoint (image::buffer&, uint64_t, float, float); +template void util::noise::midpoint (image::buffer<1,float>&, uint64_t, float, float); diff --git a/noise/midpoint.hpp b/noise/midpoint.hpp index 45dcff11..afbad858 100644 --- a/noise/midpoint.hpp +++ b/noise/midpoint.hpp @@ -22,7 +22,7 @@ namespace util { namespace noise { template void - midpoint (image::buffer&, uint64_t seed, float persistence = 0.65f, float sides = 0.25f); + midpoint (image::buffer<1,T>&, uint64_t seed, float persistence = 0.65f, float sides = 0.25f); } } #endif diff --git a/test/image.cpp b/test/image.cpp index 657bd480..e64d039e 100644 --- a/test/image.cpp +++ b/test/image.cpp @@ -10,7 +10,7 @@ main (void) constexpr size_t W = 64; constexpr size_t H = 128; - util::image::buffer img ({W, H}); + util::image::buffer<1,uint16_t> img ({W, H}); if (!img.is_packed ()) tap.skip ("linear position probe requires packed image allocation"); diff --git a/tools/noise.cpp b/tools/noise.cpp index 619d85cf..b8ba9f29 100644 --- a/tools/noise.cpp +++ b/tools/noise.cpp @@ -346,7 +346,7 @@ main (int argc, char **argv) for (auto &p: t.perturb) p.frequency (scale / res.w); - util::image::buffer img (res); + util::image::buffer<1,float> img (res); // XXX: offset slightly to avoid origin artefacts in some basis functions const auto OFFSET = util::vector2f {