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
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 void operator()(reader& io) const
00061 {
00062 handle_16(io);
00063 handle_alpha(io, alpha_traits::get_alpha_filler());
00064 handle_palette(io);
00065 handle_rgb(io);
00066 handle_gray(io);
00067
00068 io.set_color_type(traits::get_color_type());
00069 io.set_bit_depth(traits::get_bit_depth());
00070 }
00071
00072 void operator()(writer& io) const;
00073
00074 protected:
00075 static void expand_8_to_16(png_struct*, png_row_info* row_info,
00076 byte* row)
00077 {
00078
00079
00080 for (size_t i = row_info->rowbytes; i-- > 0; )
00081 {
00082
00083 row[i*2 + 0] = row[i];
00084 row[i*2 + 1] = 0;
00085 }
00086
00087
00088 }
00089
00090 static void dump_row(byte const* row, size_t width)
00091 {
00092 printf("{");
00093 for (size_t i = 0; i < width; ++i)
00094 {
00095 printf(" %02x,", row[i]);
00096 }
00097 printf(" }\n");
00098 }
00099
00100 static void handle_16(reader& io)
00101 {
00102 if (io.get_bit_depth() == 16 && traits::get_bit_depth() == 8)
00103 {
00104 #ifdef PNG_READ_16_TO_8_SUPPORTED
00105 io.set_strip_16();
00106 #else
00107 throw error("expected 8-bit data but found 16-bit;"
00108 " recompile with PNG_READ_16_TO_8_SUPPORTED");
00109 #endif
00110 }
00111 if (io.get_bit_depth() != 16 && traits::get_bit_depth() == 16)
00112 {
00113 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
00114 io.set_read_user_transform(expand_8_to_16);
00115 io.set_user_transform_info(NULL, 16,
00116 traits::get_channels());
00117 #else
00118 throw error("expected 16-bit data but found 8-bit;"
00119 " recompile with"
00120 " PNG_READ_USER_TRANSFORM_SUPPORTED");
00121 #endif
00122 }
00123 }
00124
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 static void handle_palette(reader& io)
00160 {
00161 if (io.get_color_type() == color_type_palette)
00162 {
00163 #ifdef PNG_READ_EXPAND_SUPPORTED
00164 io.set_palette_to_rgb();
00165
00166 if (traits::get_color_type() != color_type_palette)
00167 {
00168 io.get_info().drop_palette();
00169 }
00170 #else
00171 throw error("indexed colors unexpected;"
00172 " recompile with PNG_READ_EXPAND_SUPPORTED");
00173 #endif
00174 }
00175 }
00176
00177 static void handle_rgb(reader& io)
00178 {
00179 bool src_rgb =
00180 io.get_color_type() & (color_mask_rgb | color_mask_palette);
00181 bool dst_rgb = traits::get_color_type() & color_mask_rgb;
00182 if (src_rgb && !dst_rgb)
00183 {
00184 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
00185 io.set_rgb_to_gray();
00186 #else
00187 throw error("grayscale data expected;"
00188 " recompile with"
00189 " PNG_READ_RGB_TO_GRAY_SUPPORTED");
00190 #endif
00191 }
00192 if (!src_rgb && dst_rgb)
00193 {
00194 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
00195 io.set_gray_to_rgb();
00196 #else
00197 throw error("expected RGB data;"
00198 " recompile with"
00199 " PNG_READ_GRAY_TO_RGB_SUPPORTED");
00200 #endif
00201 }
00202 }
00203
00204 static void handle_gray(reader& io)
00205 {
00206 if ((io.get_color_type() & ~color_mask_alpha)
00207 == color_type_gray)
00208 {
00209 if (io.get_bit_depth() < 8 && traits::get_bit_depth() >= 8)
00210 {
00211 #ifdef PNG_READ_EXPAND_SUPPORTED
00212 io.set_gray_1_2_4_to_8();
00213 #else
00214 throw error("convert_color_space: expected 8-bit data;"
00215 " recompile with"
00216 " PNG_READ_EXPAND_SUPPORTED");
00217 #endif
00218 }
00219 }
00220 }
00221 };
00222
00223 }
00224
00240 template< typename pixel >
00241 struct convert_color_space
00242 {
00243 };
00244
00249 template<>
00250 struct convert_color_space< rgb_pixel >
00251 : convert_color_space_impl< rgb_pixel >
00252 {
00253 };
00254
00259 template<>
00260 struct convert_color_space< rgb_pixel_16 >
00261 : convert_color_space_impl< rgb_pixel_16 >
00262 {
00263 };
00264
00269 template<>
00270 struct convert_color_space< rgba_pixel >
00271 : convert_color_space_impl< rgba_pixel >
00272 {
00273 };
00274
00279 template<>
00280 struct convert_color_space< rgba_pixel_16 >
00281 : convert_color_space_impl< rgba_pixel_16 >
00282 {
00283 };
00284
00289 template<>
00290 struct convert_color_space< gray_pixel >
00291 : convert_color_space_impl< gray_pixel >
00292 {
00293 };
00294
00299 template<>
00300 struct convert_color_space< gray_pixel_16 >
00301 : convert_color_space_impl< gray_pixel_16 >
00302 {
00303 };
00304
00309 template<>
00310 struct convert_color_space< ga_pixel >
00311 : convert_color_space_impl< ga_pixel >
00312 {
00313 };
00314
00319 template<>
00320 struct convert_color_space< ga_pixel_16 >
00321 : convert_color_space_impl< ga_pixel_16 >
00322 {
00323 };
00324
00325 }
00326
00327 #endif // PNGPP_CONVERT_COLOR_SPACE_HPP_INCLUDED