Commit 189856af authored by Manuel Günther's avatar Manuel Günther
Browse files

Added support for RGBA in png

parent dce61228
......@@ -97,10 +97,10 @@ static void im_peek(const std::string& path, bob::io::base::array::typeinfo& inf
info.dtype = (bit_depth <= 8 ? bob::io::base::array::t_uint8 : bob::io::base::array::t_uint16);
if(color_type == PNG_COLOR_TYPE_GRAY)
info.nd = 2;
else if (color_type == PNG_COLOR_TYPE_RGB || PNG_COLOR_TYPE_PALETTE)
else if (color_type == PNG_COLOR_TYPE_RGB || PNG_COLOR_TYPE_RGB_ALPHA || PNG_COLOR_TYPE_PALETTE)
info.nd = 3;
else {// Unsupported color type
throw std::runtime_error("PNG: codec does not support images with color spaces different than GRAY, RGB or Indexed colors (Palette)");
throw std::runtime_error("PNG: codec does not support images with color spaces different than GRAY, RGB, RGBA or Indexed colors (Palette)");
}
if(info.nd == 2)
{
......@@ -145,18 +145,18 @@ void im_load_gray(png_structp png_ptr, bob::io::base::array::interface& b)
}
template <typename T> static
void imbuffer_to_rgb(const size_t size, const T* im, T* r, T* g, T* b)
void imbuffer_to_rgb(const size_t size, const T* im, T* r, T* g, T* b, const size_t number_of_elements)
{
for(size_t k=0; k<size; ++k)
{
r[k] = im[3*k];
g[k] = im[3*k +1];
b[k] = im[3*k +2];
r[k] = im[number_of_elements*k];
g[k] = im[number_of_elements*k +1];
b[k] = im[number_of_elements*k +2];
}
}
template <typename T> static
void im_load_color(png_structp png_ptr, bob::io::base::array::interface& b)
void im_load_color(png_structp png_ptr, bob::io::base::array::interface& b, bool has_alpha)
{
const bob::io::base::array::typeinfo& info = b.type();
const size_t height = info.shape[1];
......@@ -164,8 +164,10 @@ void im_load_color(png_structp png_ptr, bob::io::base::array::interface& b)
const size_t frame_size = height * width;
const size_t row_color_stride = width;
const size_t number_of_elements = has_alpha ? 4 : 3;
// Allocate array to contains a row of RGB-like pixels
boost::shared_array<T> row(new T[3*width]);
boost::shared_array<T> row(new T[number_of_elements*width]);
png_bytep row_pointer = reinterpret_cast<png_bytep>(row.get());
#ifdef PNG_READ_INTERLACING_SUPPORTED
......@@ -189,7 +191,7 @@ void im_load_color(png_structp png_ptr, bob::io::base::array::interface& b)
for(size_t y=0; y<height; ++y)
{
png_read_row(png_ptr, row_pointer, NULL);
imbuffer_to_rgb(row_color_stride, reinterpret_cast<T*>(row_pointer), element_r, element_g, element_b);
imbuffer_to_rgb(row_color_stride, reinterpret_cast<T*>(row_pointer), element_r, element_g, element_b, number_of_elements);
element_r += row_color_stride;
element_g += row_color_stride;
element_b += row_color_stride;
......@@ -251,15 +253,19 @@ static void im_load(const std::string& filename, bob::io::base::array::interface
else if(color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ptr);
// We currently only support grayscale and rgb images
if(color_type != PNG_COLOR_TYPE_GRAY && color_type != PNG_COLOR_TYPE_RGB && color_type != PNG_COLOR_TYPE_PALETTE) {
throw std::runtime_error("PNG: codec does not support images with color spaces different than GRAY, RGB or Indexed colors (Palette)");
if(color_type != PNG_COLOR_TYPE_GRAY &&
color_type != PNG_COLOR_TYPE_RGB &&
color_type != PNG_COLOR_TYPE_PALETTE &&
color_type != PNG_COLOR_TYPE_RGB_ALPHA) {
throw std::runtime_error("PNG: codec does not support images with color spaces different than GRAY, RGB, RGBA or Indexed colors (Palette)");
}
// 7. Read content
const bob::io::base::array::typeinfo& info = b.type();
bool has_alpha = (color_type & PNG_COLOR_MASK_ALPHA) == PNG_COLOR_MASK_ALPHA;
if(info.dtype == bob::io::base::array::t_uint8) {
if(info.nd == 2) im_load_gray<uint8_t>(png_ptr, b);
else if( info.nd == 3) im_load_color<uint8_t>(png_ptr, b);
else if( info.nd == 3) im_load_color<uint8_t>(png_ptr, b, has_alpha);
else {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
boost::format m("the image in file `%s' has a number of dimensions for which this png codec has no support for: %s");
......@@ -269,7 +275,7 @@ static void im_load(const std::string& filename, bob::io::base::array::interface
}
else if(info.dtype == bob::io::base::array::t_uint16) {
if(info.nd == 2) im_load_gray<uint16_t>(png_ptr, b);
else if( info.nd == 3) im_load_color<uint16_t>(png_ptr, b);
else if( info.nd == 3) im_load_color<uint16_t>(png_ptr, b, has_alpha);
else {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
boost::format m("the image in file `%s' has a number of dimensions for which this png codec has no support for: %s");
......
......@@ -14,6 +14,7 @@ from bob.io.base import load, write, test_utils
# These are some global parameters for the test.
PNG_INDEXED_COLOR = test_utils.datafile('img_indexed_color.png', __name__)
PNG_RGBA_COLOR = test_utils.datafile('img_rgba_color.png', __name__)
def test_png_indexed_color():
......@@ -23,6 +24,15 @@ def test_png_indexed_color():
assert img[0,0,0] == 255
assert img[0,17,17] == 117
def test_png_rgba_color():
# Read an indexed color PNG image, and compared with hardcoded values
img = load(PNG_RGBA_COLOR)
assert img.shape == (3,22,32)
assert img[0,0,0] == 255
assert img[0,17,17] == 117
def transcode(filename):
tmpname = test_utils.temporary_filename(suffix=os.path.splitext(filename)[1])
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment