image_data : re-factor (ref #2491)

* factor out raw image data alloc/dealloc into separate detail::buffer
* remove shallow ctor
* remove no-op dtor from image_data
This commit is contained in:
artemp 2014-11-20 14:36:03 +01:00
parent 5e2a53bac9
commit f7649c27b0

View file

@ -25,74 +25,100 @@
// mapnik // mapnik
#include <mapnik/global.hpp> #include <mapnik/global.hpp>
// stl // stl
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <stdexcept> #include <stdexcept>
namespace mapnik namespace mapnik {
namespace detail {
struct buffer
{ {
explicit buffer(std::size_t size)
: size_(size),
data_(static_cast<unsigned char*>(size_ != 0 ? ::operator new(size_) : nullptr))
{}
buffer(buffer && rhs) noexcept = default;
buffer(buffer const& rhs)
: size_(rhs.size_),
data_(rhs.data_)
{
if (data_) std::copy(rhs.data_, rhs.data_ + rhs.size_, data_);
}
inline bool operator!() const { return (data_ == nullptr)? false : true; }
~buffer()
{
::operator delete(data_);
}
inline unsigned char* data() { return data_; }
inline unsigned char const* data() const { return data_; }
inline std::size_t size() const { return size_; }
std::size_t size_;
unsigned char* data_;
};
}
template <typename T> template <typename T>
class image_data class image_data
{ {
public: public:
using pixel_type = T; using pixel_type = T;
static constexpr std::size_t pixel_size = sizeof(pixel_type);
image_data(std::size_t width, std::size_t height, bool initialize = true) image_data(std::size_t width, std::size_t height, bool initialize = true)
: width_(width), : width_(width),
height_(height), height_(height),
pData_((width!=0 && height!=0) ? static_cast<T*>(::operator new(sizeof(T) * width_ * height_)):0), buffer_(width_ * height_ * pixel_size),
pData_(reinterpret_cast<pixel_type*>(buffer_.data())),
owns_data_(true) owns_data_(true)
{ {
if (pData_ && initialize) std::fill(pData_, pData_ + width_ * height_, 0); if (pData_ && initialize) std::fill(pData_, pData_ + width_ * height_, 0);
} }
image_data(std::size_t width, std::size_t height, T * data) image_data(image_data<pixel_type> const& rhs)
: width_(width),
height_(height),
owns_data_(false),
pData_(data) {}
image_data(image_data<T> const& rhs)
: width_(rhs.width_), : width_(rhs.width_),
height_(rhs.height_), height_(rhs.height_),
pData_((rhs.width_!=0 && rhs.height_!=0) ? buffer_(rhs.buffer_),
static_cast<T*>(::operator new(sizeof(T) * rhs.width_ * rhs.height_)) : 0), pData_(reinterpret_cast<pixel_type*>(buffer_.data())),
owns_data_(true) owns_data_(true) {}
{
if (pData_) std::copy(rhs.pData_, rhs.pData_ + rhs.width_* rhs.height_, pData_);
}
image_data(image_data<T> && rhs) noexcept image_data(image_data<pixel_type> && rhs) noexcept
: width_(rhs.width_), : width_(rhs.width_),
height_(rhs.height_), height_(rhs.height_),
pData_(rhs.pData_) buffer_(std::move(rhs.buffer_)),
pData_(reinterpret_cast<pixel_type*>(buffer_.data()))
{ {
rhs.width_ = 0; rhs.width_ = 0;
rhs.height_ = 0; rhs.height_ = 0;
rhs.pData_ = nullptr; rhs.pData_ = nullptr;
} }
image_data<T>& operator=(image_data<T> rhs) image_data<pixel_type>& operator=(image_data<pixel_type> rhs)
{ {
swap(rhs); swap(rhs);
return *this; return *this;
} }
void swap(image_data<T> & rhs) void swap(image_data<pixel_type> & rhs)
{ {
std::swap(width_, rhs.width_); std::swap(width_, rhs.width_);
std::swap(height_, rhs.height_); std::swap(height_, rhs.height_);
std::swap(pData_, rhs.pData_); std::swap(buffer_, rhs.buffer_);
} }
inline T& operator() (std::size_t i, std::size_t j) inline pixel_type& operator() (std::size_t i, std::size_t j)
{ {
assert(i<width_ && j<height_); assert(i<width_ && j<height_);
return pData_[j * width_ + i]; return pData_[j * width_ + i];
} }
inline const T& operator() (std::size_t i,std::size_t j) const inline const pixel_type& operator() (std::size_t i, std::size_t j) const
{ {
assert(i < width_ && j < height_); assert(i < width_ && j < height_);
return pData_[j * width_ + i]; return pData_[j * width_ + i];
@ -105,64 +131,56 @@ public:
{ {
return height_; return height_;
} }
inline void set(T const& t) inline void set(pixel_type const& t)
{ {
std::fill(pData_, pData_ + width_ * height_, t); std::fill(pData_, pData_ + width_ * height_, t);
} }
inline const T* getData() const inline const pixel_type* getData() const
{ {
return pData_; return pData_;
} }
inline T* getData() inline pixel_type* getData()
{ {
return pData_; return pData_;
} }
inline const unsigned char* getBytes() const inline const unsigned char* getBytes() const
{ {
return reinterpret_cast<unsigned char*>(pData_); return buffer_.data();
} }
inline unsigned char* getBytes() inline unsigned char* getBytes()
{ {
return reinterpret_cast<unsigned char*>(pData_); return buffer_.data();
} }
inline const T* getRow(unsigned row) const inline const pixel_type* getRow(unsigned row) const
{ {
return pData_ + row * width_; return pData_ + row * width_;
} }
inline T* getRow(unsigned row) inline pixel_type* getRow(unsigned row)
{ {
return pData_ + row * width_; return pData_ + row * width_;
} }
inline void setRow(std::size_t row, T const* buf, std::size_t size) inline void setRow(std::size_t row, pixel_type const* buf, std::size_t size)
{ {
assert(row < height_); assert(row < height_);
assert(size <= width_); assert(size <= width_);
std::copy(buf, buf + size, pData_ + row * width_); std::copy(buf, buf + size, pData_ + row * width_);
} }
inline void setRow(std::size_t row, std::size_t x0, std::size_t x1, T const* buf) inline void setRow(std::size_t row, std::size_t x0, std::size_t x1, pixel_type const* buf)
{ {
std::copy(buf, buf + (x1 - x0), pData_ + row * width_); std::copy(buf, buf + (x1 - x0), pData_ + row * width_);
} }
inline ~image_data()
{
if (owns_data_)
{
::operator delete(pData_),pData_=0;
}
}
private: private:
std::size_t width_; std::size_t width_;
std::size_t height_; std::size_t height_;
T *pData_; detail::buffer buffer_;
pixel_type *pData_;
bool owns_data_; bool owns_data_;
}; };