- 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