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
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 //            dump_row(row, row_info->rowbytes);
00079 
00080                 for (size_t i = row_info->rowbytes; i-- > 0; )
00081                 {
00082                     // use PNG byte order (big-endian)
00083                     row[i*2 + 0] = row[i];
00084                     row[i*2 + 1] = 0;
00085                 }
00086 
00087 //            dump_row(row, row_info->rowbytes);
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     } // unnamed namespace
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 } // namespace png
00326 
00327 #endif // PNGPP_CONVERT_COLOR_SPACE_HPP_INCLUDED

Generated on Sun Jul 8 19:33:00 2007 for png++ by  doxygen 1.5.2