png++  0.2.7
convert_color_space.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007,2008 Alex Shulgin
3  *
4  * This file is part of png++ the C++ wrapper for libpng. PNG++ is free
5  * software; the exact copying conditions are as follows:
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * 3. The name of the author may not be used to endorse or promote products
18  * derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
23  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
25  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 #ifndef PNGPP_CONVERT_COLOR_SPACE_HPP_INCLUDED
32 #define PNGPP_CONVERT_COLOR_SPACE_HPP_INCLUDED
33 
34 #include "error.hpp"
35 #include "rgb_pixel.hpp"
36 #include "rgba_pixel.hpp"
37 #include "gray_pixel.hpp"
38 #include "ga_pixel.hpp"
39 #include "index_pixel.hpp"
40 #include "reader.hpp"
41 #include "writer.hpp"
42 
43 namespace png
44 {
45 
46  namespace detail
47  {
48 
53  template< typename pixel >
55  {
57  typedef typename traits::component_type component_type;
59 
60  template< class reader >
61  void operator()(reader& io) const
62  {
63  handle_16(io);
65  handle_palette(io);
66  handle_rgb(io);
67  handle_gray(io);
68 
69  io.set_color_type(traits::get_color_type());
70  io.set_bit_depth(traits::get_bit_depth());
71  }
72 
73  protected:
74  static void expand_8_to_16(png_struct*, png_row_info* row_info,
75  byte* row)
76  {
77 #ifdef DEBUG_EXPAND_8_16
78  printf("row: width=%d, bytes=%d, channels=%d\n",
79  row_info->width, row_info->rowbytes, row_info->channels);
80  printf("<= ");
81  dump_row(row, row_info->rowbytes);
82 #endif
83  for (size_t i = row_info->rowbytes; i-- > 0; )
84  {
85  row[2*i + 1] = row[i];
86  row[2*i + 0] = 0;
87  }
88 #ifdef DEBUG_EXPAND_8_16
89  printf("=> ");
90  dump_row(row, 2*row_info->rowbytes);
91 #endif
92  }
93 
94 #ifdef DEBUG_EXPAND_8_16
95  static void dump_row(byte const* row, size_t width)
96  {
97  printf("{");
98  for (size_t i = 0; i < width; ++i)
99  {
100  printf(" %02x,", row[i]);
101  }
102  printf(" }\n");
103  }
104 #endif
105 
106  template< class reader >
107  static void handle_16(reader& io)
108  {
109  if (io.get_bit_depth() == 16 && traits::get_bit_depth() == 8)
110  {
111 #ifdef PNG_READ_16_TO_8_SUPPORTED
112  io.set_strip_16();
113 #else
114  throw error("expected 8-bit data but found 16-bit; recompile with PNG_READ_16_TO_8_SUPPORTED");
115 #endif
116  }
117  if (io.get_bit_depth() != 16 && traits::get_bit_depth() == 16)
118  {
119 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
121  io.set_user_transform_info(NULL, 16,
122  traits::get_channels());
123 #else
124  throw error("expected 16-bit data but found 8-bit; recompile with PNG_READ_USER_TRANSFORM_SUPPORTED");
125 #endif
126  }
127  }
128 
129  template< class reader >
130  static void handle_alpha(reader& io, uint_32 filler)
131  {
132  bool src_alpha = (io.get_color_type() & color_mask_alpha);
133  bool src_tRNS = io.has_chunk(chunk_tRNS);
134  bool dst_alpha = traits::get_color_type() & color_mask_alpha;
135  if ((src_alpha || src_tRNS) && !dst_alpha)
136  {
137 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
138  io.set_strip_alpha();
139 #else
140  throw error("alpha channel unexpected; recompile with PNG_READ_STRIP_ALPHA_SUPPORTED");
141 #endif
142  }
143  if (!src_alpha && dst_alpha)
144  {
145 #if defined(PNG_tRNS_SUPPORTED) && defined(PNG_READ_EXPAND_SUPPORTED)
146  if (src_tRNS)
147  {
148  io.set_tRNS_to_alpha();
149  return;
150  }
151 #endif
152 #if defined(PNG_READ_FILLER_SUPPORTED) && !defined(PNG_1_0_X)
153  io.set_add_alpha(filler, filler_after);
154 #else
155  throw error("expected alpha channel but none found; recompile with PNG_READ_FILLER_SUPPORTED and be sure to use libpng > 1.0.x");
156 #endif
157  }
158  }
159 
160  template< class reader >
161  static void handle_palette(reader& io)
162  {
163  bool src_palette =
165  bool dst_palette =
166  traits::get_color_type() == color_type_palette;
167  if (src_palette && !dst_palette)
168  {
169 #ifdef PNG_READ_EXPAND_SUPPORTED
170  io.set_palette_to_rgb();
171  io.get_info().drop_palette();
172 #else
173  throw error("indexed colors unexpected; recompile with PNG_READ_EXPAND_SUPPORTED");
174 #endif
175  }
176  else if (!src_palette && dst_palette)
177  {
178  throw error("conversion to indexed colors is unsupported (yet)");
179  }
180  else if (src_palette && dst_palette
181  && io.get_bit_depth() != traits::get_bit_depth())
182  {
183  if (traits::get_bit_depth() == 8)
184  {
185 #ifdef PNG_READ_PACK_SUPPORTED
186  io.set_packing();
187 #endif
188  }
189  else
190  {
191  throw error("cannot convert to indexed colors with bit-depth < 8");
192  }
193  }
194  }
195 
196  template< class reader >
197  static void handle_rgb(reader& io)
198  {
199  bool src_rgb =
201  bool dst_rgb = traits::get_color_type() & color_mask_rgb;
202  if (src_rgb && !dst_rgb)
203  {
204 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
205  io.set_rgb_to_gray(/*rgb_to_gray_error*/);
206 #else
207  throw error("grayscale data expected; recompile with PNG_READ_RGB_TO_GRAY_SUPPORTED");
208 #endif
209  }
210  if (!src_rgb && dst_rgb)
211  {
212 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
213  io.set_gray_to_rgb();
214 #else
215  throw error("expected RGB data; recompile with PNG_READ_GRAY_TO_RGB_SUPPORTED");
216 #endif
217  }
218  }
219 
220  template< class reader >
221  static void handle_gray(reader& io)
222  {
223  if ((io.get_color_type() & ~color_mask_alpha)
224  == color_type_gray)
225  {
226  if (io.get_bit_depth() < 8 && traits::get_bit_depth() >= 8)
227  {
228 #ifdef PNG_READ_EXPAND_SUPPORTED
229  io.set_gray_1_2_4_to_8();
230 #else
231  throw error("convert_color_space: expected 8-bit data; recompile with PNG_READ_EXPAND_SUPPORTED");
232 #endif
233  }
234  }
235  }
236  };
237 
238  } // namespace detal
239 
255  template< typename pixel >
257  {
258  };
259 
264  template<>
266  : detail::convert_color_space_impl< rgb_pixel >
267  {
268  };
269 
274  template<>
276  : detail::convert_color_space_impl< rgb_pixel_16 >
277  {
278  };
279 
284  template<>
286  : detail::convert_color_space_impl< rgba_pixel >
287  {
288  };
289 
294  template<>
296  : detail::convert_color_space_impl< rgba_pixel_16 >
297  {
298  };
299 
304  template<>
306  : detail::convert_color_space_impl< gray_pixel >
307  {
308  };
309 
314  template<>
316  : detail::convert_color_space_impl< gray_pixel_16 >
317  {
318  };
319 
324  template<>
327  {
328  };
329 
334  template<>
336  : detail::convert_color_space_impl< ga_pixel_16 >
337  {
338  };
339 
344  template<>
346  : detail::convert_color_space_impl< index_pixel >
347  {
348  };
349 
350 } // namespace png
351 
352 #endif // PNGPP_CONVERT_COLOR_SPACE_HPP_INCLUDED
static void handle_gray(reader &io)
Definition: convert_color_space.hpp:221
void set_add_alpha(uint_32 filler, filler_type type) const
Definition: io_base.hpp:301
Basic Gray+Alpha pixel type.
Definition: ga_pixel.hpp:46
void set_read_user_transform(png_user_transform_ptr transform_fn)
Definition: io_base.hpp:400
RGB pixel type.
Definition: rgb_pixel.hpp:44
static void handle_alpha(reader &io, uint_32 filler)
Definition: convert_color_space.hpp:130
Definition: types.hpp:104
Definition: types.hpp:62
void set_bit_depth(size_t bit_depth)
Definition: io_base.hpp:155
static void handle_16(reader &io)
Definition: convert_color_space.hpp:107
static void handle_palette(reader &io)
Definition: convert_color_space.hpp:161
The 8-bit Indexed (colormap) pixel type.
Definition: index_pixel.hpp:44
Definition: types.hpp:63
The PNG reader class template. This is the low-level reading interface–use image class or consumer c...
Definition: reader.hpp:65
Pixel traits class template.
Definition: pixel_traits.hpp:48
color_type get_color_type() const
Definition: io_base.hpp:140
void set_strip_16() const
Definition: io_base.hpp:392
size_t get_bit_depth() const
Definition: io_base.hpp:150
IO transformation class template. Converts image color space.
Definition: convert_color_space.hpp:54
uint_16 gray_pixel_16
The 16-bit Grayscale pixel type.
Definition: gray_pixel.hpp:49
bool has_chunk(chunk id)
Definition: io_base.hpp:192
RGBA pixel type.
Definition: rgba_pixel.hpp:44
png_uint_32 uint_32
Definition: types.hpp:41
png_byte byte
Definition: types.hpp:39
void set_gray_to_rgb() const
Definition: io_base.hpp:228
static component get_alpha_filler()
Returns the default alpha channel filler for full opacity.
Definition: pixel_traits.hpp:95
void operator()(reader &io) const
Definition: convert_color_space.hpp:61
void drop_palette()
Removes all entries from the palette.
Definition: image_info.hpp:154
void set_color_type(color_type color_space)
Definition: io_base.hpp:145
info & get_info()
Definition: io_base.hpp:87
Definition: types.hpp:69
static void expand_8_to_16(png_struct *, png_row_info *row_info, byte *row)
Definition: convert_color_space.hpp:74
Definition: types.hpp:60
byte gray_pixel
The 8-bit Grayscale pixel type.
Definition: gray_pixel.hpp:44
Definition: types.hpp:49
void set_packing() const
Definition: io_base.hpp:320
static void handle_rgb(reader &io)
Definition: convert_color_space.hpp:197
pixel_traits< pixel > traits
Definition: convert_color_space.hpp:56
static void dump_row(byte const *row, size_t width)
Definition: convert_color_space.hpp:95
IO transformation class template. Converts image color space.
Definition: convert_color_space.hpp:256
void set_palette_to_rgb() const
Definition: io_base.hpp:206
basic_alpha_pixel_traits< component_type > alpha_traits
Definition: convert_color_space.hpp:58
void set_tRNS_to_alpha() const
Definition: io_base.hpp:212
Definition: color.hpp:36
void set_gray_1_2_4_to_8() const
Definition: io_base.hpp:200
void set_user_transform_info(void *info, int bit_depth, int channels)
Definition: io_base.hpp:409
void set_rgb_to_gray(rgb_to_gray_error_action error_action=rgb_to_gray_silent, double red_weight=-1.0, double green_weight=-1.0) const
Definition: io_base.hpp:236
Definition: types.hpp:50
Exception class to represent runtime errors related to png++ operation.
Definition: error.hpp:47
traits::component_type component_type
Definition: convert_color_space.hpp:57
void set_strip_alpha() const
Definition: io_base.hpp:266
Basic pixel traits class template for pixels with alpha channel.
Definition: pixel_traits.hpp:89