Index: typedefs.hpp =================================================================== --- typedefs.hpp (revision 42242) +++ typedefs.hpp (working copy) @@ -105,6 +105,13 @@ GIL_DEFINE_BASE_TYPEDEFS(32 ,gray) GIL_DEFINE_BASE_TYPEDEFS(32s,gray) GIL_DEFINE_BASE_TYPEDEFS(32f,gray) +GIL_DEFINE_BASE_TYPEDEFS(8, alpha_gray) +GIL_DEFINE_BASE_TYPEDEFS(8s, alpha_gray) +GIL_DEFINE_BASE_TYPEDEFS(16, alpha_gray) +GIL_DEFINE_BASE_TYPEDEFS(16s,alpha_gray) +GIL_DEFINE_BASE_TYPEDEFS(32 ,alpha_gray) +GIL_DEFINE_BASE_TYPEDEFS(32s,alpha_gray) +GIL_DEFINE_BASE_TYPEDEFS(32f,alpha_gray) GIL_DEFINE_BASE_TYPEDEFS(8, bgr) GIL_DEFINE_BASE_TYPEDEFS(8s, bgr) GIL_DEFINE_BASE_TYPEDEFS(16, bgr) @@ -148,6 +155,13 @@ GIL_DEFINE_ALL_TYPEDEFS(32 ,rgba) GIL_DEFINE_ALL_TYPEDEFS(32s,rgba) GIL_DEFINE_ALL_TYPEDEFS(32f,rgba) +GIL_DEFINE_ALL_TYPEDEFS(8, gray_alpha) +GIL_DEFINE_ALL_TYPEDEFS(8s, gray_alpha) +GIL_DEFINE_ALL_TYPEDEFS(16, gray_alpha) +GIL_DEFINE_ALL_TYPEDEFS(16s,gray_alpha) +GIL_DEFINE_ALL_TYPEDEFS(32 ,gray_alpha) +GIL_DEFINE_ALL_TYPEDEFS(32s,gray_alpha) +GIL_DEFINE_ALL_TYPEDEFS(32f,gray_alpha) GIL_DEFINE_ALL_TYPEDEFS(8, cmyk) GIL_DEFINE_ALL_TYPEDEFS(8s, cmyk) GIL_DEFINE_ALL_TYPEDEFS(16, cmyk) Index: gray_alpha.hpp =================================================================== --- gray_alpha.hpp (revision 0) +++ gray_alpha.hpp (revision 0) @@ -0,0 +1,26 @@ + +/* + Copyright 2007 Andreas Pokorny + + Use, modification and distribution are subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +#ifndef GIL_GRAY_ALPHA_H +#define GIL_GRAY_ALPHA_H +#include "gil_config.hpp" +#include +#include "gray.hpp" +#include "rgba.hpp" +namespace boost { namespace gil { + +typedef mpl::vector2 gray_alpha_t; + +typedef layout gray_alpha_layout_t; +typedef layout > alpha_gray_layout_t; +}} + +#endif Property changes on: gray_alpha.hpp ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Id Name: svn:eol-style + native Index: utilities.hpp =================================================================== --- utilities.hpp (revision 42242) +++ utilities.hpp (working copy) @@ -326,6 +326,7 @@ return !little_endian(); } + } } // namespace boost::gil #endif Index: bit_aligned_pixel_iterator.hpp =================================================================== --- bit_aligned_pixel_iterator.hpp (revision 42242) +++ bit_aligned_pixel_iterator.hpp (working copy) @@ -114,6 +114,10 @@ template struct is_planar > : public is_planar {}; // == false +template +struct channel_type > : public channel_type { +}; + ///////////////////////////// // MemoryBasedIteratorConcept ///////////////////////////// Index: color_convert.hpp =================================================================== --- color_convert.hpp (revision 42242) +++ color_convert.hpp (working copy) @@ -29,6 +29,7 @@ #include "channel_algorithm.hpp" #include "pixel.hpp" #include "gray.hpp" +#include "gray_alpha.hpp" #include "rgb.hpp" #include "rgba.hpp" #include "cmyk.hpp" @@ -110,6 +111,53 @@ }; /// \ingroup ColorConvert +/// \brief Gray Alpha to RGBA +template <> +struct default_color_converter_impl { + template + void operator()(const P1& src, P2& dst) const { + get_color(dst,red_t()) = + channel_convert::type>(get_color(src,gray_color_t())); + get_color(dst,green_t())= + channel_convert::type>(get_color(src,gray_color_t())); + get_color(dst,blue_t()) = + channel_convert::type>(get_color(src,gray_color_t())); + get_color(dst,alpha_t()) = + channel_convert::type>(get_color(src,alpha_t())); + } +}; + +template <> +struct default_color_converter_impl { + template + void operator()(const P1& src, P2& dst) const { + get_color(dst,red_t()) = + channel_convert::type>( + channel_multiply(get_color(src,gray_color_t()),get_color(src,alpha_t()) ) + ); + get_color(dst,green_t()) = + channel_convert::type>( + channel_multiply(get_color(src,gray_color_t()),get_color(src,alpha_t()) ) + ); + get_color(dst,blue_t()) = + channel_convert::type>( + channel_multiply(get_color(src,gray_color_t()),get_color(src,alpha_t()) ) + ); + } +}; + +template <> +struct default_color_converter_impl { + template + void operator()(const P1& src, P2& dst) const { + get_color(dst,gray_color_t()) = + channel_convert::type>( + channel_multiply(get_color(src,gray_color_t()),get_color(src,alpha_t()) ) + ); + } +}; + +/// \ingroup ColorConvert /// \brief Gray to CMYK template <> struct default_color_converter_impl { Index: bit_aligned_pixel_reference.hpp =================================================================== --- bit_aligned_pixel_reference.hpp (revision 42242) +++ bit_aligned_pixel_reference.hpp (working copy) @@ -222,6 +222,49 @@ template struct is_pixel > : public mpl::true_{}; +namespace detail { + + template + struct gen_chan_ref + { + typedef packed_dynamic_channel_reference::type::value,M> type; + }; + + template + struct is_homogeneous_impl; + + + template + struct is_homogeneous_impl : mpl::true_{}; + + + template + struct is_homogeneous_impl + : mpl::and_< + is_homogeneous_impl, + is_same::type> + > {}; + +} // boost::gil::detail + +template +struct is_homogeneous; + +template +struct is_homogeneous > + : detail::is_homogeneous_impl::type,1,mpl::size::type::value> +{}; + +template +struct channel_type > + : boost::lazy_enable_if< + is_homogeneous >, + detail::gen_chan_ref + > +{}; + + + ///////////////////////////// // PixelBasedConcept ///////////////////////////// Index: extension/io/png_io_private.hpp =================================================================== --- extension/io/png_io_private.hpp (revision 42242) +++ extension/io/png_io_private.hpp (working copy) @@ -34,15 +34,18 @@ template struct png_color_type {BOOST_STATIC_CONSTANT(int,color_type=0);}; template<> struct png_color_type { BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); }; template<> struct png_color_type { BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB); }; +template<> struct png_color_type { BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GA); }; template<> struct png_color_type { BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA); }; template struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=false);}; template <> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=true);}; +template <> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=true);}; template <> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=true);}; template <> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=true);}; template <> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=true);}; template <> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=true);}; template <> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=true);}; +template <> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=true);}; template struct png_bit_depth {BOOST_STATIC_CONSTANT(int,bit_depth=sizeof(Channel)*8);}; @@ -52,18 +55,45 @@ BOOST_STATIC_CONSTANT(int,bit_depth=0); BOOST_STATIC_CONSTANT(int,color_type=0); }; +template +struct png_read_support_private,gray_t> { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=1); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); +}; +template +struct png_read_support_private,gray_t> { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=2); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); +}; +template +struct png_read_support_private,gray_t> { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=4); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); +}; template <> struct png_read_support_private { BOOST_STATIC_CONSTANT(bool,is_supported=true); BOOST_STATIC_CONSTANT(int,bit_depth=8); BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); }; + template <> +struct png_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=8); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GA); +}; + +template <> struct png_read_support_private { BOOST_STATIC_CONSTANT(bool,is_supported=true); BOOST_STATIC_CONSTANT(int,bit_depth=8); BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB); }; + template <> struct png_read_support_private { BOOST_STATIC_CONSTANT(bool,is_supported=true); @@ -88,6 +118,12 @@ BOOST_STATIC_CONSTANT(int,bit_depth=16); BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA); }; +template <> +struct png_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=16); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GA); +}; template struct png_write_support_private { @@ -95,6 +131,25 @@ BOOST_STATIC_CONSTANT(int,bit_depth=0); BOOST_STATIC_CONSTANT(int,color_type=0); }; +template +struct png_write_support_private,gray_t> { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=1); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); +}; +template +struct png_write_support_private,gray_t> { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=2); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); +}; +template +struct png_write_support_private,gray_t> { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=4); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); +}; + template <> struct png_write_support_private { BOOST_STATIC_CONSTANT(bool,is_supported=true); @@ -108,6 +163,12 @@ BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB); }; template <> +struct png_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=8); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GA); +}; +template <> struct png_write_support_private { BOOST_STATIC_CONSTANT(bool,is_supported=true); BOOST_STATIC_CONSTANT(int,bit_depth=8); @@ -126,6 +187,12 @@ BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB); }; template <> +struct png_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=16); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GA); +}; +template <> struct png_write_support_private { BOOST_STATIC_CONSTANT(bool,is_supported=true); BOOST_STATIC_CONSTANT(int,bit_depth=16); @@ -191,16 +258,67 @@ png_read_support_private::type, typename color_space_type::type>::color_type!=color_type) io_error("png_read_view: input view type is incompatible with the image type"); - - std::vector::type, - layout::type> > > row(width); - for(png_uint_32 y=0;y::type, + typename color_space_type::type>::bit_depth == 16 ) + png_set_swap(_png_ptr); + if( png_read_support_private::type, + typename color_space_type::type>::bit_depth < 8 ) + png_set_packswap(_png_ptr); } + + read_rows(view, + mpl::int_::type, + typename color_space_type::type + >::bit_depth>(), + mpl::int_< + num_channels::value + >() + ); + png_read_end(_png_ptr,NULL); } + template + void read_rows(View const& view, + mpl::int_ const&, + mpl::int_ const&, + typename boost::enable_if_c::type *ptr = 0 ) + { + std::vector::type, + layout::type> > > row(view.width()); + for(int y=0;y + void read_rows(View const& view, + mpl::int_ const& , + mpl::int_ const& ) + { + typedef bit_aligned_pixel_iterator iterator; + int c = ( view.width() * ChannelCount * BitDepth ) / (8); + int r = view.width() * ChannelCount * BitDepth - (8*c); + std::vector row(c + (r!=0)); + for(int y=0;y void read_image(Image& im) { im.recreate(get_dimensions()); @@ -219,75 +337,90 @@ png_reader_color_convert(const char* filename,CC cc_in) : png_reader(filename),_cc(cc_in) {} png_reader_color_convert(const char* filename) : png_reader(filename) {} template - void apply(const View& view) { + void apply(const View& view) + { png_uint_32 width, height; int bit_depth, color_type, interlace_type; png_get_IHDR(_png_ptr, _info_ptr, &width, &height,&bit_depth,&color_type,&interlace_type, int_p_NULL, int_p_NULL); io_error_if(((png_uint_32)view.width()!=width || (png_uint_32)view.height()!= height), - "png_reader_color_convert::apply(): input view size does not match PNG file size"); - switch (color_type) { + "png_reader_color_convert::apply(): input view size does not match PNG file size"); + + if (little_endian() ) + { + if( png_read_support_private::type, + typename color_space_type::type>::bit_depth == 16 ) + png_set_swap(_png_ptr); + if( png_read_support_private::type, + typename color_space_type::type>::bit_depth < 8 ) + png_set_packswap(_png_ptr); + } + + if(color_type == PNG_COLOR_TYPE_PALETTE) + { + color_type = PNG_COLOR_TYPE_RGB; + bit_depth = 8; + png_set_palette_to_rgb(_png_ptr); + } + + if(png_get_valid(_png_ptr, _info_ptr,PNG_INFO_tRNS)) + { + if( color_type == PNG_COLOR_TYPE_RGB ) + color_type = PNG_COLOR_TYPE_RGBA; + else if( color_type == PNG_COLOR_TYPE_GRAY ) + color_type = PNG_COLOR_TYPE_GA; + + png_set_tRNS_to_alpha(_png_ptr); + } + + typedef unsigned char ba_type; // Use for bitaligned raw data + typedef bit_aligned_pixel_reference,gray_layout_t,true> gray_1b; + typedef bit_aligned_pixel_reference,gray_layout_t,true> gray_2b; + typedef bit_aligned_pixel_reference,gray_layout_t,true> gray_4b; + + switch (color_type) + { case PNG_COLOR_TYPE_GRAY: + switch (bit_depth) + { + case 1: read_rows_bitaligned(view); + break; + case 2: read_rows_bitaligned(view); + break; + case 4: read_rows_bitaligned(view); + break; + case 8: read_rows(view); + break; + case 16: read_rows(view); + break; + default: io_error("png_reader_color_convert::apply(): unknown combination of color type and bit depth"); + } + break; + case PNG_COLOR_TYPE_GA: switch (bit_depth) { - case 8: { - std::vector row(width); - for(png_uint_32 y=0;y(_cc)); - } - break; - } - case 16: { - std::vector row(width); - for(png_uint_32 y=0;y(_cc)); - } - break; - } + case 8: read_rows(view); + break; + case 16: read_rows(view); + break; default: io_error("png_reader_color_convert::apply(): unknown combination of color type and bit depth"); } break; case PNG_COLOR_TYPE_RGB: switch (bit_depth) { - case 8: { - std::vector row(width); - for(png_uint_32 y=0;y(_cc)); - } - break; - } - case 16: { - std::vector row(width); - for(png_uint_32 y=0;y(_cc)); - } - break; - } + case 8: read_rows(view); + break; + case 16: read_rows(view); + break; default: io_error("png_reader_color_convert::apply(): unknown combination of color type and bit depth"); } break; case PNG_COLOR_TYPE_RGBA: switch (bit_depth) { - case 8: { - std::vector row(width); - for(png_uint_32 y=0;y(_cc)); - } - break; - } - case 16: { - std::vector row(width); - for(png_uint_32 y=0;y(_cc)); - } - break; - } + case 8: read_rows(view); + break; + case 16: read_rows(view); + break; default: io_error("png_reader_color_convert::apply(): unknown combination of color type and bit depth"); } break; @@ -295,11 +428,47 @@ } png_read_end(_png_ptr,NULL); } + template + void read_rows( View & view ) + { + std::vector row(view.width()); + for(png_uint_32 y=0;y(_cc) + ); + } + } + + template + void read_rows_bitaligned( View & view ) + { + typedef bit_aligned_pixel_iterator iterator; + + int c = ( view.width() * Channels * BitDepth ) / (sizeof(BitFieldT)*8); + int r = view.width() * Channels * BitDepth - (sizeof(BitFieldT)*8*c); + + std::vector row(c + (r!=0)); + for(png_uint_32 y=0;y(_cc) + ); + } + } + template - void read_image(Image& im) { - im.recreate(get_dimensions()); - apply(view(im)); - } + void read_image(Image& im) { + im.recreate(get_dimensions()); + apply(view(im)); + } }; @@ -339,18 +508,63 @@ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT); png_write_info(_png_ptr,_info_ptr); - if (little_endian() && - png_write_support_private::type, - typename color_space_type::type>::bit_depth>8) - png_set_swap(_png_ptr); + if (little_endian() ) + { + if( png_write_support_private::type, + typename color_space_type::type>::bit_depth == 16 ) + png_set_swap(_png_ptr); + if( png_write_support_private::type, + typename color_space_type::type>::bit_depth < 8 ) + png_set_packswap(_png_ptr); + } + + write_rows(view, + mpl::int_::type, + typename color_space_type::type + >::bit_depth>(), + mpl::int_< + num_channels::value + >() + ); + + png_write_end(_png_ptr,_info_ptr); + } + + template + void write_rows(View const& view, + mpl::int_ const&, + mpl::int_ const&, + typename boost::enable_if_c::type *ptr = 0 ) + { std::vector::type, layout::type> > > row(view.width()); for(int y=0;y + void write_rows(View const& view, + mpl::int_ const& , + mpl::int_ const& ) + { + typedef bit_aligned_pixel_iterator iterator; + int c = ( view.width() * ChannelCount * BitDepth ) / (8); + int r = view.width() * ChannelCount * BitDepth - (8*c); + std::vector row(c + (r!=0)); + for(int y=0;y