image: templatise on component count
This commit is contained in:
parent
03efa074ab
commit
003685ce2b
122
image.cpp
122
image.cpp
@ -22,21 +22,26 @@ using util::image::buffer;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
util::image::buffer<T>::buffer (util::extentu<2> _size):
|
||||
template <size_t C, typename T>
|
||||
buffer<C,T>::buffer (util::extentu<2> _size):
|
||||
m_size (_size),
|
||||
m_stride (1, _size.w),
|
||||
m_data (std::make_unique<T[]> (_size.area ()))
|
||||
{ ; }
|
||||
m_stride (C, _size.w),
|
||||
m_data (std::make_unique<T[]> (_size.area () * C))
|
||||
{
|
||||
std::partial_sum (m_stride.begin (),
|
||||
m_stride.end (),
|
||||
m_stride.begin (),
|
||||
std::multiplies<T> ());
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
template <typename U>
|
||||
util::image::buffer<U>
|
||||
util::image::buffer<T>::alloc (void) const
|
||||
buffer<C,U>
|
||||
buffer<C,T>::alloc (void) const
|
||||
{
|
||||
return buffer<U> (m_size);
|
||||
return buffer<C,U> (m_size);
|
||||
}
|
||||
|
||||
|
||||
@ -50,45 +55,46 @@ rescale (T v)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
template <typename U>
|
||||
util::image::buffer<U>
|
||||
util::image::buffer<T>::clone (void) const
|
||||
util::image::buffer<C,U>
|
||||
util::image::buffer<C,T>::clone (void) const
|
||||
{
|
||||
auto out = alloc<U> ();
|
||||
|
||||
std::transform (begin (), end (), out.begin (), renormalise<T,U>);
|
||||
auto func = renormalise<T,U>;
|
||||
std::transform (begin (), end (), out.begin (), func);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
const T&
|
||||
buffer<T>::operator[] (point<2,size_t> p) const
|
||||
buffer<C,T>::operator[] (point<2,size_t> p) const
|
||||
{
|
||||
CHECK (util::all (p < size ()));
|
||||
CHECK (util::all (p < extent ()));
|
||||
|
||||
return begin ()[offset (p)];
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
T&
|
||||
buffer<T>::operator[] (point<2,size_t> p)
|
||||
buffer<C,T>::operator[] (point<2,size_t> p)
|
||||
{
|
||||
CHECK (util::all (p < size ()));
|
||||
CHECK (util::all (p < extent ()));
|
||||
|
||||
return begin ()[offset (p)];
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
const T&
|
||||
buffer<T>::operator[] (size_t idx) const
|
||||
buffer<C,T>::operator[] (size_t idx) const
|
||||
{
|
||||
CHECK_LT (idx, size ());
|
||||
|
||||
@ -97,9 +103,9 @@ buffer<T>::operator[] (size_t idx) const
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
T&
|
||||
buffer<T>::operator[] (size_t idx)
|
||||
buffer<C,T>::operator[] (size_t idx)
|
||||
{
|
||||
CHECK_LT (idx, size ());
|
||||
|
||||
@ -108,97 +114,101 @@ buffer<T>::operator[] (size_t idx)
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
T*
|
||||
buffer<T>::data (void)
|
||||
buffer<C,T>::data (void)
|
||||
{
|
||||
return begin ();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
T*
|
||||
buffer<T>::begin (void)
|
||||
buffer<C,T>::begin (void)
|
||||
{
|
||||
return m_data.get ();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
T*
|
||||
buffer<T>::end (void)
|
||||
buffer<C,T>::end (void)
|
||||
{
|
||||
return begin () + m_size.back () * m_stride.back ();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
const T*
|
||||
buffer<T>::begin (void) const
|
||||
buffer<C,T>::begin (void) const
|
||||
{
|
||||
return cbegin ();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
const T*
|
||||
buffer<T>::end (void) const
|
||||
buffer<C,T>::end (void) const
|
||||
{
|
||||
return cend ();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
const T*
|
||||
buffer<T>::data (void) const
|
||||
buffer<C,T>::data (void) const
|
||||
{
|
||||
return begin ();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
const T*
|
||||
buffer<T>::cbegin (void) const
|
||||
buffer<C,T>::cbegin (void) const
|
||||
{
|
||||
return m_data.get ();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
const T*
|
||||
buffer<T>::cend (void) const
|
||||
buffer<C,T>::cend (void) const
|
||||
{
|
||||
return cbegin () + m_size.back () * m_stride.back ();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template struct util::image::buffer<char>;
|
||||
template struct util::image::buffer<uint8_t>;
|
||||
template struct util::image::buffer<uint16_t>;
|
||||
template struct util::image::buffer<uint32_t>;
|
||||
template struct util::image::buffer< int32_t>;
|
||||
template struct util::image::buffer<float>;
|
||||
template struct util::image::buffer<double>;
|
||||
|
||||
template util::image::buffer<char> util::image::buffer<char>::alloc (void) const;
|
||||
#define INSTANTIATE_C_T_U(C,T,U) \
|
||||
template util::image::buffer<C,U> util::image::buffer<C,T>::alloc (void) const; \
|
||||
template util::image::buffer<C,U> util::image::buffer<C,T>::clone (void) const; \
|
||||
template util::image::buffer<C,U> util::image::buffer<C,T>::cast (void) const;
|
||||
|
||||
template util::image::buffer<uint8_t> util::image::buffer<uint8_t>::alloc (void) const;
|
||||
template util::image::buffer<uint8_t> util::image::buffer<uint8_t>::clone (void) const;
|
||||
template util::image::buffer<uint8_t> util::image::buffer<float>::clone (void) const;
|
||||
template util::image::buffer<uint8_t> util::image::buffer<double>::clone (void) const;
|
||||
#define INSTANTIATE_C_T(C,T) \
|
||||
template struct util::image::buffer<C,T>; \
|
||||
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<float> util::image::buffer<float>::alloc (void) const;
|
||||
template util::image::buffer<uint32_t> util::image::buffer<float>::alloc (void) const;
|
||||
template util::image::buffer< int32_t> util::image::buffer<float>::alloc (void) const;
|
||||
|
||||
template util::image::buffer<float> util::image::buffer<float>::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<uint32_t> util::image::buffer<uint32_t>::alloc (void) const;
|
||||
INSTANTIATE_C(1)
|
||||
INSTANTIATE_C(2)
|
||||
INSTANTIATE_C(3)
|
||||
INSTANTIATE_C(4)
|
||||
|
16
image.hpp
16
image.hpp
@ -26,7 +26,7 @@
|
||||
|
||||
|
||||
namespace util { namespace image {
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
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<T[]> &&data);
|
||||
|
||||
buffer (const buffer<T>&) = delete;
|
||||
buffer (buffer<T> &&) = default;
|
||||
buffer& operator= (const buffer<T>&) = default;
|
||||
buffer& operator= (buffer<T>&&) = 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 <typename U = T> buffer<U> alloc (void) const;
|
||||
template <typename U = T> buffer<C,U> alloc (void) const;
|
||||
|
||||
/// allocate and return a buffer with the same contents
|
||||
template <typename U = T> buffer<U> clone (void) const;
|
||||
template <typename U> buffer<U> cast (void) const { return clone<U> (); }
|
||||
template <typename U = T> buffer<C,U> clone (void) const;
|
||||
template <typename U> buffer<C,U> cast (void) const { return clone<U> (); }
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
constexpr extent2u extent (void) const;
|
||||
|
20
image.ipp
20
image.ipp
@ -21,45 +21,45 @@
|
||||
|
||||
namespace util { namespace image {
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
constexpr extent2u
|
||||
buffer<T>::extent (void) const
|
||||
buffer<C,T>::extent (void) const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
constexpr vector2u
|
||||
buffer<T>::stride (void) const
|
||||
buffer<C,T>::stride (void) const
|
||||
{
|
||||
return m_stride;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
constexpr size_t
|
||||
buffer<T>::offset (point<2,size_t> p) const
|
||||
buffer<C,T>::offset (point<2,size_t> p) const
|
||||
{
|
||||
return dot (stride (), p);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
constexpr size_t
|
||||
buffer<T>::size (void) const
|
||||
buffer<C,T>::size (void) const
|
||||
{
|
||||
return extent ().back () * stride ().back ();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <size_t C, typename T>
|
||||
constexpr bool
|
||||
buffer<T>::is_packed (void) const
|
||||
buffer<C,T>::is_packed (void) const
|
||||
{
|
||||
return stride ().back () == extent ().back ();
|
||||
}
|
||||
|
@ -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<uint8_t>
|
||||
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<uint8_t> 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<uint8_t> &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<uint8_t> &src,
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
util::pgm::write (const util::image::buffer<uint8_t> &src,
|
||||
util::pgm::write (const util::image::buffer<1,uint8_t> &src,
|
||||
const boost::filesystem::path &path)
|
||||
{
|
||||
std::ofstream dst (path.string ());
|
||||
|
@ -27,11 +27,11 @@
|
||||
namespace util {
|
||||
// Portable GrayMap: single component greyscale.
|
||||
struct pgm {
|
||||
static image::buffer<uint8_t> read (const boost::filesystem::path&);
|
||||
static image::buffer<1,uint8_t> read (const boost::filesystem::path&);
|
||||
|
||||
static void write (const image::buffer<uint8_t> &src,
|
||||
static void write (const image::buffer<1,uint8_t> &src,
|
||||
const boost::filesystem::path &dst);
|
||||
static void write (const image::buffer<uint8_t> &src,
|
||||
static void write (const image::buffer<1,uint8_t> &src,
|
||||
std::ostream &dst);
|
||||
|
||||
static void write (const uint8_t *restrict pixels,
|
||||
|
@ -26,7 +26,7 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
void
|
||||
util::noise::fill (image::buffer<T> &pixels,
|
||||
util::noise::fill (image::buffer<1,T> &pixels,
|
||||
const util::noise::fractal<T> &gen)
|
||||
{
|
||||
size_t h = pixels.h, s = pixels.s, w = pixels.w;
|
||||
@ -37,8 +37,8 @@ util::noise::fill (image::buffer<T> &pixels,
|
||||
data[y * s + x] = gen ({T(x), T(y)});
|
||||
}
|
||||
|
||||
template void util::noise::fill (image::buffer<float>&, const util::noise::fractal<float>&);
|
||||
template void util::noise::fill (image::buffer<double>&, const util::noise::fractal<double>&);
|
||||
template void util::noise::fill (image::buffer<1,float>&, const util::noise::fractal<float>&);
|
||||
template void util::noise::fill (image::buffer<1,double>&, const util::noise::fractal<double>&);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
namespace util { namespace noise {
|
||||
template <typename T, typename G>
|
||||
void fill (image::buffer<T>&, const G&);
|
||||
void fill (image::buffer<1,T>&, const G&);
|
||||
} }
|
||||
|
||||
#include "noise.ipp"
|
||||
|
@ -23,7 +23,7 @@ namespace util { namespace noise {
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T, typename G>
|
||||
void
|
||||
fill (image::buffer<T> &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 ();
|
||||
|
@ -25,7 +25,7 @@
|
||||
// assumes corner points have been assigned their weights
|
||||
template <typename T>
|
||||
static void
|
||||
fill (util::image::buffer<T> &img,
|
||||
fill (util::image::buffer<1,T> &img,
|
||||
uint64_t seed,
|
||||
util::region2u target,
|
||||
float scale,
|
||||
@ -99,7 +99,7 @@ fill (util::image::buffer<T> &img,
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
void
|
||||
util::noise::midpoint (image::buffer<T> &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<T> &img, uint64_t seed, float persistence,
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template void util::noise::midpoint (image::buffer<float>&, uint64_t, float, float);
|
||||
template void util::noise::midpoint (image::buffer<1,float>&, uint64_t, float, float);
|
||||
|
@ -22,7 +22,7 @@
|
||||
namespace util { namespace noise {
|
||||
template <typename T>
|
||||
void
|
||||
midpoint (image::buffer<T>&, 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
|
||||
|
@ -10,7 +10,7 @@ main (void)
|
||||
|
||||
constexpr size_t W = 64;
|
||||
constexpr size_t H = 128;
|
||||
util::image::buffer<uint16_t> 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");
|
||||
|
@ -346,7 +346,7 @@ main (int argc, char **argv)
|
||||
for (auto &p: t.perturb)
|
||||
p.frequency (scale / res.w);
|
||||
|
||||
util::image::buffer<float> 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 {
|
||||
|
Loading…
Reference in New Issue
Block a user