Files
cpp-thirdparty/winx64/include/pngpp/pixel_buffer.hpp
Bassem Girgis 81b4b9e273 Initial commit
2018-12-20 17:34:07 -06:00

498 lines
14 KiB
C++

/*
* Copyright (C) 2007,2008 Alex Shulgin
*
* This file is part of png++ the C++ wrapper for libpng. PNG++ is free
* software; the exact copying conditions are as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PNGPP_PIXEL_BUFFER_HPP_INCLUDED
#define PNGPP_PIXEL_BUFFER_HPP_INCLUDED
#include <cassert>
#include <cstddef>
#include <stdexcept>
#include <vector>
#include "packed_pixel.hpp"
#include "gray_pixel.hpp"
#include "index_pixel.hpp"
namespace png
{
/**
* \brief The pixel row traits class template. Provides a common
* way to get starting address of the row for packed and unpacked
* row types.
*
* Not implemented--see specializations.
*/
template< typename row > class row_traits;
/**
* \brief The basic class template to represent image pixel data.
*/
template< typename pixel,
typename row,
class traits = row_traits< row > >
class basic_pixel_buffer
{
public:
/**
* \brief A row of pixel data.
*/
typedef row row_type;
typedef row_type& row_access;
typedef row_type const& row_const_access;
typedef traits row_traits;
/**
* \brief Constructs an empty 0x0 pixel buffer object.
*/
basic_pixel_buffer()
: m_width(0),
m_height(0)
{
}
/**
* \brief Constructs an empty pixel buffer object.
*/
basic_pixel_buffer(uint_32 width, uint_32 height)
: m_width(0),
m_height(0)
{
resize(width, height);
}
uint_32 get_width() const
{
return m_width;
}
uint_32 get_height() const
{
return m_height;
}
/**
* \brief Resizes the pixel buffer.
*
* If new width or height is greater than the original,
* expanded pixels are filled with value of \a pixel().
*/
void resize(uint_32 width, uint_32 height)
{
m_width = width;
m_height = height;
m_rows.resize(height);
for (typename row_vec::iterator r = m_rows.begin();
r != m_rows.end();
++r)
{
r->resize(width);
}
}
/**
* \brief Returns a reference to the row of image data at
* specified index.
*
* Checks the index before returning a row: an instance of
* std::out_of_range is thrown if \c index is greater than \c
* height.
*/
row_access get_row(size_t index)
{
return m_rows.at(index);
}
/**
* \brief Returns a const reference to the row of image data at
* specified index.
*
* The checking version.
*/
row_const_access get_row(size_t index) const
{
return m_rows.at(index);
}
/**
* \brief The non-checking version of get_row() method.
*/
row_access operator[](size_t index)
{
return m_rows[index];
}
/**
* \brief The non-checking version of get_row() method.
*/
row_const_access operator[](size_t index) const
{
return m_rows[index];
}
/**
* \brief Replaces the row at specified index.
*/
void put_row(size_t index, row_type const& r)
{
assert(r.size() == m_width);
m_rows.at(index) = r;
}
/**
* \brief Returns a pixel at (x,y) position.
*/
pixel get_pixel(size_t x, size_t y) const
{
return get_row(y).at(x);
}
/**
* \brief Replaces a pixel at (x,y) position.
*/
void set_pixel(size_t x, size_t y, pixel p)
{
get_row(y).at(x) = p;
}
protected:
uint_32 m_width;
uint_32 m_height;
typedef std::vector< row_type > row_vec;
row_vec m_rows;
};
/**
* \brief The row_traits specialization for unpacked pixel rows.
*/
template< typename pixel >
class row_traits< std::vector< pixel > >
{
public:
/**
* \brief Returns the starting address of the row.
*/
static pixel* get_data(std::vector< pixel >& vec)
{
assert(vec.size());
return & vec[0];
}
};
/**
* The pixel_buffer specialization for unpacked pixels.
*/
template< typename pixel >
class pixel_buffer
: public basic_pixel_buffer< pixel, std::vector< pixel > >
{
public:
pixel_buffer()
{
}
pixel_buffer(uint_32 width, uint_32 height)
: basic_pixel_buffer< pixel, std::vector< pixel > >(width, height)
{
}
};
namespace detail
{
template< class pixel, typename reference >
class basic_packed_pixel_proxy
{
public:
explicit basic_packed_pixel_proxy(reference ref)
: m_ref(ref),
m_shift(0)
{
}
basic_packed_pixel_proxy(reference ref, size_t index)
: m_ref(ref),
m_shift(get_shift(index))
{
}
operator pixel() const
{
return pixel((m_ref >> m_shift) & pixel::get_bit_mask());
}
protected:
/*
* bits: . . .
* 1: 7 6 5 4 3 2 1 0
* 2: 6 4 2 0
* 4: 4 0
*/
static size_t get_shift(size_t index)
{
int const bits = pixel::get_bit_depth();
return (8 - bits) - (index % get_pixels_per_byte()) * bits;
}
static size_t get_pixels_per_byte()
{
return 8 / pixel::get_bit_depth();
}
reference m_ref;
size_t m_shift;
};
template< class pixel >
class const_packed_pixel_proxy
: public basic_packed_pixel_proxy< pixel, byte const& >
{
public:
const_packed_pixel_proxy(byte const& ref, size_t index)
: basic_packed_pixel_proxy< pixel, byte const& >(ref, index)
{
}
};
template< class pixel >
class packed_pixel_proxy
: public basic_packed_pixel_proxy< pixel, byte& >
{
public:
typedef basic_packed_pixel_proxy< pixel, byte& > basic_proxy;
packed_pixel_proxy(byte& ref, size_t index)
: basic_proxy(ref, index)
{
}
packed_pixel_proxy(packed_pixel_proxy const& other)
: basic_proxy(other.m_ref)
{
this->m_shift = other.m_shift;
}
packed_pixel_proxy& operator=(packed_pixel_proxy const& other)
{
return *this = static_cast< pixel >(other);
}
template< typename reference >
packed_pixel_proxy&
operator=(basic_packed_pixel_proxy< pixel, reference > const& other)
{
return *this = static_cast< pixel >(other);
}
packed_pixel_proxy& operator=(pixel p)
{
this->m_ref = (this->m_ref
& ~(pixel::get_bit_mask() << this->m_shift))
| (p << this->m_shift);
return *this;
}
};
} // namespace detail
/**
* \brief The packed pixel row class template.
*
* Stores the pixel row as a std::vector of byte-s, providing
* access to individual packed pixels via proxy objects.
*/
template< class pixel >
class packed_pixel_row
{
public:
/**
* \brief Constructs a pixel row object for \c size packed pixels.
*/
explicit packed_pixel_row(size_t size = 0)
{
resize(size);
}
size_t size() const
{
return m_size;
}
/**
* \brief Resizes the pixel row to hold up to \c size packed pixels.
*/
void resize(size_t size)
{
m_vec.resize(size / get_pixels_per_byte()
+ (size % get_pixels_per_byte() ? 1 : 0));
m_size = size;
}
/**
* \brief The immutable packed pixel proxy type.
*/
typedef detail::const_packed_pixel_proxy< pixel > const_pixel_proxy;
/**
* \brief The mutable packed pixel proxy type.
*/
typedef detail::packed_pixel_proxy< pixel > pixel_proxy;
/**
* \brief Returns an immutable proxy the to the pixel at \c
* index.
*/
const_pixel_proxy at(size_t index) const
{
return const_pixel_proxy(m_vec.at(index / get_pixels_per_byte()),
index);
}
/**
* \brief Returns a mutable proxy the to the pixel at \c
* index.
*/
pixel_proxy at(size_t index)
{
return pixel_proxy(m_vec.at(index / get_pixels_per_byte()),
index);
}
/**
* \brief Returns an immutable proxy the to the pixel at \c
* index. The non-checking version.
*/
const_pixel_proxy operator[](size_t index) const
{
return const_pixel_proxy(m_vec[index / get_pixels_per_byte()],
index);
}
/**
* \brief Returns n mutable proxy the to the pixel at \c
* index. The non-checking version.
*/
pixel_proxy operator[](size_t index)
{
return pixel_proxy(m_vec[index / get_pixels_per_byte()],
index);
}
/**
* \brief Returns the starting address of the row.
*/
byte* get_data()
{
assert(m_vec.size());
return & m_vec[0];
}
private:
static size_t get_pixels_per_byte()
{
return 8 / pixel::get_bit_depth();
}
std::vector< byte > m_vec;
size_t m_size;
};
/**
* \brief The row_traits class template specialization for packed
* pixel row type.
*/
template< typename pixel >
class row_traits< packed_pixel_row< pixel > >
{
public:
/**
* \brief Returns the starting address of the row.
*/
static byte* get_data(packed_pixel_row< pixel >& row)
{
return row.get_data();
}
};
/**
* \brief The pixel buffer class template specialization for the
* packed_gray_pixel type.
*/
template< int bits >
class pixel_buffer< packed_gray_pixel< bits > >
: public basic_pixel_buffer< packed_gray_pixel< bits >,
packed_pixel_row< packed_gray_pixel
< bits > > >
{
public:
typedef packed_gray_pixel< bits > pixel_type;
typedef packed_pixel_row< pixel_type > pixel_row_type;
pixel_buffer()
{
}
pixel_buffer(uint_32 width, uint_32 height)
: basic_pixel_buffer< pixel_type,
pixel_row_type >(width, height)
{
}
};
/**
* \brief The pixel buffer class template specialization for the
* packed_index_pixel type.
*/
template< int bits >
class pixel_buffer< packed_index_pixel< bits > >
: public basic_pixel_buffer< packed_index_pixel< bits >,
packed_pixel_row< packed_index_pixel
< bits > > >
{
public:
typedef packed_index_pixel< bits > pixel_type;
typedef packed_pixel_row< pixel_type > pixel_row_type;
pixel_buffer()
{
}
pixel_buffer(uint_32 width, uint_32 height)
: basic_pixel_buffer< pixel_type,
pixel_row_type >(width, height)
{
}
};
} // namespace png
#endif // PNGPP_PIXEL_BUFFER_HPP_INCLUDED