• Main Page
  • Namespaces
  • Classes
  • Files
  • File List

convert_color_space.hpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007,2008   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 #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(/*rgb_to_gray_error*/);
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     } // namespace detal
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 } // namespace png
00337 
00338 #endif // PNGPP_CONVERT_COLOR_SPACE_HPP_INCLUDED

Generated on Thu Dec 16 2010 12:40:02 for png++ by  doxygen 1.7.2