png++: convert_color_space.hpp Source File

png++ 0.2.10

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 >
54 struct convert_color_space_impl
55 {
56 typedef pixel_traits< pixel > traits;
57 typedef typename traits::component_type component_type;
58 typedef basic_alpha_pixel_traits< component_type > alpha_traits;
59
60 template< class reader >
61 void operator()(reader& io) const
62 {
63 handle_16(io);
64 handle_alpha(io, alpha_traits::get_alpha_filler());
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 (uint_32 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, uint_32 width)
96 {
97 printf("{");
98 for (uint_32 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
120 io.set_read_user_transform(expand_8_to_16);
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 =
164 io.get_color_type() == color_type_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 =
200 io.get_color_type() & (color_mask_rgb | color_mask_palette);
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 >
256 struct convert_color_space
257 {
258 };
259
264 template<>
265 struct convert_color_space< rgb_pixel >
266 : detail::convert_color_space_impl< rgb_pixel >
267 {
268 };
269
274 template<>
275 struct convert_color_space< rgb_pixel_16 >
276 : detail::convert_color_space_impl< rgb_pixel_16 >
277 {
278 };
279
284 template<>
285 struct convert_color_space< rgba_pixel >
286 : detail::convert_color_space_impl< rgba_pixel >
287 {
288 };
289
294 template<>
295 struct convert_color_space< rgba_pixel_16 >
296 : detail::convert_color_space_impl< rgba_pixel_16 >
297 {
298 };
299
304 template<>
305 struct convert_color_space< gray_pixel >
306 : detail::convert_color_space_impl< gray_pixel >
307 {
308 };
309
314 template<>
315 struct convert_color_space< gray_pixel_16 >
316 : detail::convert_color_space_impl< gray_pixel_16 >
317 {
318 };
319
324 template<>
325 struct convert_color_space< ga_pixel >
326 : detail::convert_color_space_impl< ga_pixel >
327 {
328 };
329
334 template<>
335 struct convert_color_space< ga_pixel_16 >
336 : detail::convert_color_space_impl< ga_pixel_16 >
337 {
338 };
339
344 template<>
345 struct convert_color_space< index_pixel >
346 : detail::convert_color_space_impl< index_pixel >
347 {
348 };
349
350 } // namespace png
351
352 #endif // PNGPP_CONVERT_COLOR_SPACE_HPP_INCLUDED
png::io_base::set_read_user_transform
void set_read_user_transform(png_user_transform_ptr transform_fn)
Definition: io_base.hpp:400
png::detail::convert_color_space_impl::handle_gray
static void handle_gray(reader &io)
Definition: convert_color_space.hpp:221
png::io_base::set_strip_16
void set_strip_16() const
Definition: io_base.hpp:392
png::io_base::get_info
info & get_info()
Definition: io_base.hpp:87
png::gray_pixel_16
uint_16 gray_pixel_16
The 16-bit Grayscale pixel type.
Definition: gray_pixel.hpp:49
reader.hpp
png::color_type_palette
@ color_type_palette
Definition: types.hpp:50
png::basic_ga_pixel
Basic Gray+Alpha pixel type.
Definition: ga_pixel.hpp:47
png::detail::convert_color_space_impl::traits
pixel_traits< pixel > traits
Definition: convert_color_space.hpp:56
png::io_base::set_tRNS_to_alpha
void set_tRNS_to_alpha() const
Definition: io_base.hpp:212
png::color_mask_rgb
@ color_mask_rgb
Definition: types.hpp:62
png::detail::convert_color_space_impl::expand_8_to_16
static void expand_8_to_16(png_struct *, png_row_info *row_info, byte *row)
Definition: convert_color_space.hpp:74
png::color_mask_alpha
@ color_mask_alpha
Definition: types.hpp:63
writer.hpp
png::uint_32
png_uint_32 uint_32
Definition: types.hpp:41
png::io_base::get_color_type
color_type get_color_type() const
Definition: io_base.hpp:140
png::io_base::set_bit_depth
void set_bit_depth(int bit_depth)
Definition: io_base.hpp:155
png::chunk_tRNS
@ chunk_tRNS
Definition: types.hpp:104
png::detail::convert_color_space_impl::component_type
traits::component_type component_type
Definition: convert_color_space.hpp:57
png::color_type_gray
@ color_type_gray
Definition: types.hpp:49
png::io_base::get_bit_depth
int get_bit_depth() const
Definition: io_base.hpp:150
png::detail::convert_color_space_impl::dump_row
static void dump_row(byte const *row, uint_32 width)
Definition: convert_color_space.hpp:95
png::io_base::set_rgb_to_gray
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
png::detail::convert_color_space_impl
IO transformation class template. Converts image color space.
Definition: convert_color_space.hpp:55
png::detail::convert_color_space_impl::handle_alpha
static void handle_alpha(reader &io, uint_32 filler)
Definition: convert_color_space.hpp:130
png::io_base::set_user_transform_info
void set_user_transform_info(void *info, int bit_depth, int channels)
Definition: io_base.hpp:409
rgb_pixel.hpp
png::basic_alpha_pixel_traits
Basic pixel traits class template for pixels with alpha channel.
Definition: pixel_traits.hpp:90
png::index_pixel
The 8-bit Indexed (colormap) pixel type.
Definition: index_pixel.hpp:45
png::io_base::set_packing
void set_packing() const
Definition: io_base.hpp:320
png::reader
The PNG reader class template. This is the low-level reading interface–use image class or consumer cl...
Definition: reader.hpp:67
rgba_pixel.hpp
png::detail::convert_color_space_impl::handle_palette
static void handle_palette(reader &io)
Definition: convert_color_space.hpp:161
png::image_info::drop_palette
void drop_palette()
Removes all entries from the palette.
Definition: image_info.hpp:155
png::convert_color_space
IO transformation class template. Converts image color space.
Definition: convert_color_space.hpp:257
png::io_base::set_add_alpha
void set_add_alpha(uint_32 filler, filler_type type) const
Definition: io_base.hpp:301
png::io_base::set_color_type
void set_color_type(color_type color_space)
Definition: io_base.hpp:145
png::error
Exception class to represent runtime errors related to png++ operation.
Definition: error.hpp:59
png::io_base::set_strip_alpha
void set_strip_alpha() const
Definition: io_base.hpp:266
png::io_base::has_chunk
bool has_chunk(chunk id)
Definition: io_base.hpp:192
png::basic_rgb_pixel
RGB pixel type.
Definition: rgb_pixel.hpp:45
png::detail::convert_color_space_impl::handle_rgb
static void handle_rgb(reader &io)
Definition: convert_color_space.hpp:197
png::pixel_traits
Pixel traits class template.
Definition: pixel_traits.hpp:48
png::basic_alpha_pixel_traits::get_alpha_filler
static component get_alpha_filler()
Returns the default alpha channel filler for full opacity.
Definition: pixel_traits.hpp:95
png::color_mask_palette
@ color_mask_palette
Definition: types.hpp:60
png::detail::convert_color_space_impl::operator()
void operator()(reader &io) const
Definition: convert_color_space.hpp:61
png::filler_after
@ filler_after
Definition: types.hpp:69
png::io_base::set_palette_to_rgb
void set_palette_to_rgb() const
Definition: io_base.hpp:206
index_pixel.hpp
png::detail::convert_color_space_impl::handle_16
static void handle_16(reader &io)
Definition: convert_color_space.hpp:107
png::basic_rgba_pixel
RGBA pixel type.
Definition: rgba_pixel.hpp:45
gray_pixel.hpp
png::io_base::set_gray_1_2_4_to_8
void set_gray_1_2_4_to_8() const
Definition: io_base.hpp:200
ga_pixel.hpp
png
Definition: color.hpp:37
png::gray_pixel
byte gray_pixel
The 8-bit Grayscale pixel type.
Definition: gray_pixel.hpp:44
png::io_base::set_gray_to_rgb
void set_gray_to_rgb() const
Definition: io_base.hpp:228
png::detail::convert_color_space_impl::alpha_traits
basic_alpha_pixel_traits< component_type > alpha_traits
Definition: convert_color_space.hpp:58
error.hpp