Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef PNGPP_CONVERT_COLOR_SPACE_HPP_INCLUDED
00032 #define PNGPP_CONVERT_COLOR_SPACE_HPP_INCLUDED
00033
00034 #include "error.hpp"
00035 #include "rgb_pixel.hpp"
00036 #include "rgba_pixel.hpp"
00037 #include "gray_pixel.hpp"
00038 #include "ga_pixel.hpp"
00039 #include "index_pixel.hpp"
00040 #include "reader.hpp"
00041 #include "writer.hpp"
00042
00043 namespace png
00044 {
00045
00046 namespace detail
00047 {
00048
00053 template< typename pixel >
00054 struct convert_color_space_impl
00055 {
00056 typedef pixel_traits< pixel > traits;
00057 typedef typename traits::component_type component_type;
00058 typedef basic_alpha_pixel_traits< component_type > alpha_traits;
00059
00060 template< class reader >
00061 void operator()(reader& io) const
00062 {
00063 handle_16(io);
00064 handle_alpha(io, alpha_traits::get_alpha_filler());
00065 handle_palette(io);
00066 handle_rgb(io);
00067 handle_gray(io);
00068
00069 io.set_color_type(traits::get_color_type());
00070 io.set_bit_depth(traits::get_bit_depth());
00071 }
00072
00073 protected:
00074 static void expand_8_to_16(png_struct*, png_row_info* row_info,
00075 byte* row)
00076 {
00077 #ifdef DEBUG_EXPAND_8_16
00078 printf("row: width=%d, bytes=%d, channels=%d\n",
00079 row_info->width, row_info->rowbytes, row_info->channels);
00080 printf("<= ");
00081 dump_row(row, row_info->rowbytes);
00082 #endif
00083 for (size_t i = row_info->rowbytes; i-- > 0; )
00084 {
00085 row[2*i + 1] = row[i];
00086 row[2*i + 0] = 0;
00087 }
00088 #ifdef DEBUG_EXPAND_8_16
00089 printf("=> ");
00090 dump_row(row, 2*row_info->rowbytes);
00091 #endif
00092 }
00093
00094 #ifdef DEBUG_EXPAND_8_16
00095 static void dump_row(byte const* row, size_t width)
00096 {
00097 printf("{");
00098 for (size_t i = 0; i < width; ++i)
00099 {
00100 printf(" %02x,", row[i]);
00101 }
00102 printf(" }\n");
00103 }
00104 #endif
00105
00106 template< class reader >
00107 static void handle_16(reader& io)
00108 {
00109 if (io.get_bit_depth() == 16 && traits::get_bit_depth() == 8)
00110 {
00111 #ifdef PNG_READ_16_TO_8_SUPPORTED
00112 io.set_strip_16();
00113 #else
00114 throw error("expected 8-bit data but found 16-bit;"
00115 " recompile with PNG_READ_16_TO_8_SUPPORTED");
00116 #endif
00117 }
00118 if (io.get_bit_depth() != 16 && traits::get_bit_depth() == 16)
00119 {
00120 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
00121 io.set_read_user_transform(expand_8_to_16);
00122 io.set_user_transform_info(NULL, 16,
00123 traits::get_channels());
00124 #else
00125 throw error("expected 16-bit data but found 8-bit;"
00126 " recompile with"
00127 " PNG_READ_USER_TRANSFORM_SUPPORTED");
00128 #endif
00129 }
00130 }
00131
00132 template< class reader >
00133 static void handle_alpha(reader& io, uint_32 filler)
00134 {
00135 bool src_alpha = (io.get_color_type() & color_mask_alpha);
00136 bool src_tRNS = io.has_chunk(chunk_tRNS);
00137 bool dst_alpha = traits::get_color_type() & color_mask_alpha;
00138 if ((src_alpha || src_tRNS) && !dst_alpha)
00139 {
00140 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
00141 io.set_strip_alpha();
00142 #else
00143 throw error("alpha channel unexpected;"
00144 " recompile with"
00145 " PNG_READ_STRIP_ALPHA_SUPPORTED");
00146 #endif
00147 }
00148 if (!src_alpha && dst_alpha)
00149 {
00150 #if defined(PNG_tRNS_SUPPORTED) && defined(PNG_READ_EXPAND_SUPPORTED)
00151 if (src_tRNS)
00152 {
00153 io.set_tRNS_to_alpha();
00154 return;
00155 }
00156 #endif
00157 #if defined(PNG_READ_FILLER_SUPPORTED) && !defined(PNG_1_0_X)
00158 io.set_add_alpha(filler, filler_after);
00159 #else
00160 throw error("expected alpha channel but none found;"
00161 " recompile with PNG_READ_FILLER_SUPPORTED"
00162 " and be sure to use libpng > 1.0.x");
00163 #endif
00164 }
00165 }
00166
00167 template< class reader >
00168 static void handle_palette(reader& io)
00169 {
00170 if (io.get_color_type() == color_type_palette)
00171 {
00172 #ifdef PNG_READ_EXPAND_SUPPORTED
00173 io.set_palette_to_rgb();
00174
00175 if (traits::get_color_type() != color_type_palette)
00176 {
00177 io.get_info().drop_palette();
00178 }
00179 #else
00180 throw error("indexed colors unexpected;"
00181 " recompile with PNG_READ_EXPAND_SUPPORTED");
00182 #endif
00183 }
00184 }
00185
00186 template< class reader >
00187 static void handle_rgb(reader& io)
00188 {
00189 bool src_rgb =
00190 io.get_color_type() & (color_mask_rgb | color_mask_palette);
00191 bool dst_rgb = traits::get_color_type() & color_mask_rgb;
00192 if (src_rgb && !dst_rgb)
00193 {
00194 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
00195 io.set_rgb_to_gray();
00196 #else
00197 throw error("grayscale data expected;"
00198 " recompile with"
00199 " PNG_READ_RGB_TO_GRAY_SUPPORTED");
00200 #endif
00201 }
00202 if (!src_rgb && dst_rgb)
00203 {
00204 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
00205 io.set_gray_to_rgb();
00206 #else
00207 throw error("expected RGB data;"
00208 " recompile with"
00209 " PNG_READ_GRAY_TO_RGB_SUPPORTED");
00210 #endif
00211 }
00212 }
00213
00214 template< class reader >
00215 static void handle_gray(reader& io)
00216 {
00217 if ((io.get_color_type() & ~color_mask_alpha)
00218 == color_type_gray)
00219 {
00220 if (io.get_bit_depth() < 8 && traits::get_bit_depth() >= 8)
00221 {
00222 #ifdef PNG_READ_EXPAND_SUPPORTED
00223 io.set_gray_1_2_4_to_8();
00224 #else
00225 throw error("convert_color_space: expected 8-bit data;"
00226 " recompile with"
00227 " PNG_READ_EXPAND_SUPPORTED");
00228 #endif
00229 }
00230 }
00231 }
00232 };
00233
00234 }
00235
00251 template< typename pixel >
00252 struct convert_color_space
00253 {
00254 };
00255
00260 template<>
00261 struct convert_color_space< rgb_pixel >
00262 : detail::convert_color_space_impl< rgb_pixel >
00263 {
00264 };
00265
00270 template<>
00271 struct convert_color_space< rgb_pixel_16 >
00272 : detail::convert_color_space_impl< rgb_pixel_16 >
00273 {
00274 };
00275
00280 template<>
00281 struct convert_color_space< rgba_pixel >
00282 : detail::convert_color_space_impl< rgba_pixel >
00283 {
00284 };
00285
00290 template<>
00291 struct convert_color_space< rgba_pixel_16 >
00292 : detail::convert_color_space_impl< rgba_pixel_16 >
00293 {
00294 };
00295
00300 template<>
00301 struct convert_color_space< gray_pixel >
00302 : detail::convert_color_space_impl< gray_pixel >
00303 {
00304 };
00305
00310 template<>
00311 struct convert_color_space< gray_pixel_16 >
00312 : detail::convert_color_space_impl< gray_pixel_16 >
00313 {
00314 };
00315
00320 template<>
00321 struct convert_color_space< ga_pixel >
00322 : detail::convert_color_space_impl< ga_pixel >
00323 {
00324 };
00325
00330 template<>
00331 struct convert_color_space< ga_pixel_16 >
00332 : detail::convert_color_space_impl< ga_pixel_16 >
00333 {
00334 };
00335
00336 }
00337
00338 #endif // PNGPP_CONVERT_COLOR_SPACE_HPP_INCLUDED