convert_color_space.hpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007   Alex Shulgin
00003  *
00004  * This file is part of png++ the C++ wrapper for libpng.  Png++ is free
00005  * software; the exact copying conditions are as follows:
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright notice,
00011  * this list of conditions and the following disclaimer.
00012  *
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  * notice, this list of conditions and the following disclaimer in the
00015  * documentation and/or other materials provided with the distribution.
00016  *
00017  * 3. The name of the author may not be used to endorse or promote products
00018  * derived from this software without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00021  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00022  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00023  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00024  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00025  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00026  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00027  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00028  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00029  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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 //                dump_row(row, row_info->rowbytes);
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 //                dump_row(row, 2*row_info->rowbytes);
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(/*rgb_to_gray_error*/);
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     } // namespace detal
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 } // namespace png
00329 
00330 #endif // PNGPP_CONVERT_COLOR_SPACE_HPP_INCLUDED

Generated on Sat Dec 8 13:43:56 2007 for png++ by  doxygen 1.5.3-20071008