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
00078
00079 for (size_t i = row_info->rowbytes; i-- > 0; )
00080 {
00081 row[i*2 + 1] = row[i];
00082 row[i*2 + 0] = 0;
00083 }
00084
00085
00086 }
00087
00088 static void dump_row(byte const* row, size_t width)
00089 {
00090 printf("{");
00091 for (size_t i = 0; i < width; ++i)
00092 {
00093 printf(" %02x,", row[i]);
00094 }
00095 printf(" }\n");
00096 }
00097
00098 template< class reader >
00099 static void handle_16(reader& io)
00100 {
00101 if (io.get_bit_depth() == 16 && traits::get_bit_depth() == 8)
00102 {
00103 #ifdef PNG_READ_16_TO_8_SUPPORTED
00104 io.set_strip_16();
00105 #else
00106 throw error("expected 8-bit data but found 16-bit;"
00107 " recompile with PNG_READ_16_TO_8_SUPPORTED");
00108 #endif
00109 }
00110 if (io.get_bit_depth() != 16 && traits::get_bit_depth() == 16)
00111 {
00112 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
00113 io.set_read_user_transform(expand_8_to_16);
00114 io.set_user_transform_info(NULL, 16,
00115 traits::get_channels());
00116 #else
00117 throw error("expected 16-bit data but found 8-bit;"
00118 " recompile with"
00119 " PNG_READ_USER_TRANSFORM_SUPPORTED");
00120 #endif
00121 }
00122 }
00123
00124 template< class reader >
00125 static void handle_alpha(reader& io, uint_32 filler)
00126 {
00127 bool src_alpha = io.get_color_type() & color_mask_alpha;
00128 bool dst_alpha = traits::get_color_type() & color_mask_alpha;
00129 if (src_alpha && !dst_alpha)
00130 {
00131 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
00132 io.set_strip_alpha();
00133 #else
00134 throw error("alpha channel unexpected;"
00135 " recompile with"
00136 " PNG_READ_STRIP_ALPHA_SUPPORTED");
00137 #endif
00138 }
00139 if (!src_alpha && dst_alpha)
00140 {
00141 #if defined(PNG_tRNS_SUPPORTED) && defined(PNG_READ_EXPAND_SUPPORTED)
00142 if ((io.get_color_type() & color_mask_palette)
00143 && io.has_chunk(chunk_tRNS))
00144 {
00145 io.set_tRNS_to_alpha();
00146 return;
00147 }
00148 #endif
00149 #if defined(PNG_READ_FILLER_SUPPORTED) && !defined(PNG_1_0_X)
00150 io.set_add_alpha(filler, filler_after);
00151 #else
00152 throw error("expected alpha channel but none found;"
00153 " recompile with PNG_READ_FILLER_SUPPORTED"
00154 " and be sure to use libpng > 1.0.x");
00155 #endif
00156 }
00157 }
00158
00159 template< class reader >
00160 static void handle_palette(reader& io)
00161 {
00162 if (io.get_color_type() == color_type_palette)
00163 {
00164 #ifdef PNG_READ_EXPAND_SUPPORTED
00165 io.set_palette_to_rgb();
00166
00167 if (traits::get_color_type() != color_type_palette)
00168 {
00169 io.get_info().drop_palette();
00170 }
00171 #else
00172 throw error("indexed colors unexpected;"
00173 " recompile with PNG_READ_EXPAND_SUPPORTED");
00174 #endif
00175 }
00176 }
00177
00178 template< class reader >
00179 static void handle_rgb(reader& io)
00180 {
00181 bool src_rgb =
00182 io.get_color_type() & (color_mask_rgb | color_mask_palette);
00183 bool dst_rgb = traits::get_color_type() & color_mask_rgb;
00184 if (src_rgb && !dst_rgb)
00185 {
00186 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
00187 io.set_rgb_to_gray();
00188 #else
00189 throw error("grayscale data expected;"
00190 " recompile with"
00191 " PNG_READ_RGB_TO_GRAY_SUPPORTED");
00192 #endif
00193 }
00194 if (!src_rgb && dst_rgb)
00195 {
00196 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
00197 io.set_gray_to_rgb();
00198 #else
00199 throw error("expected RGB data;"
00200 " recompile with"
00201 " PNG_READ_GRAY_TO_RGB_SUPPORTED");
00202 #endif
00203 }
00204 }
00205
00206 template< class reader >
00207 static void handle_gray(reader& io)
00208 {
00209 if ((io.get_color_type() & ~color_mask_alpha)
00210 == color_type_gray)
00211 {
00212 if (io.get_bit_depth() < 8 && traits::get_bit_depth() >= 8)
00213 {
00214 #ifdef PNG_READ_EXPAND_SUPPORTED
00215 io.set_gray_1_2_4_to_8();
00216 #else
00217 throw error("convert_color_space: expected 8-bit data;"
00218 " recompile with"
00219 " PNG_READ_EXPAND_SUPPORTED");
00220 #endif
00221 }
00222 }
00223 }
00224 };
00225
00226 }
00227
00243 template< typename pixel >
00244 struct convert_color_space
00245 {
00246 };
00247
00252 template<>
00253 struct convert_color_space< rgb_pixel >
00254 : detail::convert_color_space_impl< rgb_pixel >
00255 {
00256 };
00257
00262 template<>
00263 struct convert_color_space< rgb_pixel_16 >
00264 : detail::convert_color_space_impl< rgb_pixel_16 >
00265 {
00266 };
00267
00272 template<>
00273 struct convert_color_space< rgba_pixel >
00274 : detail::convert_color_space_impl< rgba_pixel >
00275 {
00276 };
00277
00282 template<>
00283 struct convert_color_space< rgba_pixel_16 >
00284 : detail::convert_color_space_impl< rgba_pixel_16 >
00285 {
00286 };
00287
00292 template<>
00293 struct convert_color_space< gray_pixel >
00294 : detail::convert_color_space_impl< gray_pixel >
00295 {
00296 };
00297
00302 template<>
00303 struct convert_color_space< gray_pixel_16 >
00304 : detail::convert_color_space_impl< gray_pixel_16 >
00305 {
00306 };
00307
00312 template<>
00313 struct convert_color_space< ga_pixel >
00314 : detail::convert_color_space_impl< ga_pixel >
00315 {
00316 };
00317
00322 template<>
00323 struct convert_color_space< ga_pixel_16 >
00324 : detail::convert_color_space_impl< ga_pixel_16 >
00325 {
00326 };
00327
00328 }
00329
00330 #endif // PNGPP_CONVERT_COLOR_SPACE_HPP_INCLUDED