Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r60953 - in sandbox/gil/boost/gil/extension/io2: . detail
From: dsaritz_at_[hidden]
Date: 2010-03-30 12:41:40


Author: psiha
Date: 2010-03-30 12:41:39 EDT (Tue, 30 Mar 2010)
New Revision: 60953
URL: http://svn.boost.org/trac/boost/changeset/60953

Log:
Renamed the gp_*_bitmap classes to gp_*_image classes.

Added a first prototype/skeleton for the formatted_image<> class. Test-used it in the gp_image class.

Added the "gp_supported_pixel_formats" typedef, "roi" class, "desired_alignment" static constant and the current_image_type_id() member function as required by the formatted_image<> class.
Made the gp_image-from-IStream constructor public.
Removed some gp_image member functions that are now provided by the base class.
Renamed the gp_image::get_dimensions() member function to dimensions() to conform to the GIL image/view interface.

Added the first implementation of the view class for the gp_image class/backend.

Added Steven Watanabe's not-yet-official switch_ library to the detail folder as an internal implementation detail.

Removed some no-longer valid/relevant comments.
Added:
   sandbox/gil/boost/gil/extension/io2/detail/
   sandbox/gil/boost/gil/extension/io2/detail/switch.hpp (contents, props changed)
   sandbox/gil/boost/gil/extension/io2/formatted_image.hpp (contents, props changed)
Text files modified:
   sandbox/gil/boost/gil/extension/io2/gp_private_base.hpp | 287 +++++++++++++++++++++++++++++++--------
   sandbox/gil/boost/gil/extension/io2/gp_private_io.hpp | 44 +++---
   2 files changed, 245 insertions(+), 86 deletions(-)

Added: sandbox/gil/boost/gil/extension/io2/detail/switch.hpp
==============================================================================
--- (empty file)
+++ sandbox/gil/boost/gil/extension/io2/detail/switch.hpp 2010-03-30 12:41:39 EDT (Tue, 30 Mar 2010)
@@ -0,0 +1,136 @@
+// switch.hpp
+//
+// Copyright (c) 2006-2007
+// Steven Watanabe
+//
+// Distriuted under 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)
+
+#ifndef BOOST_SWITCH_HPP_INCLUDED
+#define BOOST_SWITCH_HPP_INCLUDED
+
+#include <stdexcept>
+#include <string>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/preprocessor/config/limits.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/iteration/local.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+#ifndef BOOST_SWITCH_LIMIT
+ #define BOOST_SWITCH_LIMIT 50
+#endif
+
+#if BOOST_SWITCH_LIMIT > BOOST_PP_LIMIT_REPEAT
+ #error BOOST_SWITCH_LIMIT exceeds Boost.Preprocessor limit
+#endif
+#if BOOST_SWITCH_LIMIT > BOOST_PP_LIMIT_ITERATION
+ #error BOOST_SWITCH_LIMIT exceeds Boost.Preprocessor limit
+#endif
+
+namespace boost {
+
+class bad_switch : public std::runtime_error {
+public:
+ template<class Int>
+ explicit bad_switch(Int v) :
+ std::runtime_error(
+ "boost::switch_ default case called -- none provided. value is: " +
+ boost::lexical_cast<std::string>(v)) {}
+};
+
+namespace switch_detail {
+
+// Avoid the need to create all the specializations of switch_impl
+// twice. Just pass this to switch_impl<N>::apply(...) when no
+// default is supplied.
+
+template<class R>
+inline R forced_return(typename boost::remove_reference<R>::type* r = 0) {
+ return(*r);
+}
+
+// Thanks to Stjepan Rajko for catching this.
+template<>
+inline void forced_return<void>(void*) {}
+template<>
+inline const void forced_return<const void>(const void*) {}
+template<>
+inline volatile void forced_return<volatile void>(volatile void*) {}
+template<>
+inline const volatile void forced_return<const volatile void>(const volatile void*) {}
+
+template<class R>
+struct throw_exception {
+ template<class Int>
+ R operator()(Int i) const {
+ boost::throw_exception(bad_switch(i));
+ return(switch_detail::forced_return<R>());
+ }
+};
+
+// N is the number of cases not including the default
+template<int N>
+struct switch_impl;
+
+// specialize for 0 separately to avoid warnings
+template<>
+struct switch_impl<0> {
+ template<class V, class Int, class F, class Default>
+ static typename F::result_type
+ apply(Int i, F, Default d BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) {
+ return(d(i));
+ }
+};
+
+#define BOOST_SWITCH_CASE(z, n, data) \
+ case boost::mpl::at_c<data, n>::type::value: { \
+ typename boost::mpl::at_c<data, n>::type arg; \
+ return(f(arg)); \
+ }
+
+#define BOOST_SWITCH_IMPL(z, n, data) \
+ template<> \
+ struct switch_impl<n> { \
+ template<class V, class I, class F, class D> \
+ static typename F::result_type \
+ apply(I i, F f, D d BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) { \
+ switch(i) { \
+ BOOST_PP_REPEAT_##z(n, BOOST_SWITCH_CASE, V) \
+ default: return(d(i)); \
+ } \
+ } \
+ };
+
+#define BOOST_PP_LOCAL_LIMITS (1, BOOST_SWITCH_LIMIT)
+#define BOOST_PP_LOCAL_MACRO(n) BOOST_SWITCH_IMPL(1, n, ~)
+#include BOOST_PP_LOCAL_ITERATE()
+
+#undef BOOST_SWITCH_IMPL
+#undef BOOST_SWITCH_CASE
+
+}
+
+template<class V, class N, class F>
+inline typename F::result_type
+switch_(N n, F f BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) {
+ typedef switch_detail::switch_impl<boost::mpl::size<V>::value> impl;
+ switch_detail::throw_exception<typename F::result_type> default_;
+ return(impl::template apply<V>(n, f, default_));
+}
+
+template<class V, class N, class F, class D>
+inline typename F::result_type
+switch_(N n, F f, D d BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) {
+ typedef switch_detail::switch_impl<boost::mpl::size<V>::value> impl;
+ return(impl::template apply<V>(n, f, d));
+}
+
+}
+
+#endif

Added: sandbox/gil/boost/gil/extension/io2/formatted_image.hpp
==============================================================================
--- (empty file)
+++ sandbox/gil/boost/gil/extension/io2/formatted_image.hpp 2010-03-30 12:41:39 EDT (Tue, 30 Mar 2010)
@@ -0,0 +1,396 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \file formatted_image.hpp
+/// -------------------------
+///
+/// (to be) Base CRTP class for all image implementation classes/backends.
+///
+/// Copyright (c) Domagoj Saric 2010.
+///
+/// Use, modification and distribution is 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)
+///
+/// For more information, see http://www.boost.org
+///
+////////////////////////////////////////////////////////////////////////////////
+//------------------------------------------------------------------------------
+#pragma once
+#ifndef formatted_image_hpp__C34C1FB0_A4F5_42F3_9318_5805B88CFE49
+#define formatted_image_hpp__C34C1FB0_A4F5_42F3_9318_5805B88CFE49
+//------------------------------------------------------------------------------
+#include "../../gil_all.hpp"
+#include "io_error.hpp"
+
+#include "detail/switch.hpp"
+
+#include <boost/gil/extension/dynamic_image/any_image.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/integral_c.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <boost/static_assert.hpp>
+//------------------------------------------------------------------------------
+namespace boost
+{
+//------------------------------------------------------------------------------
+namespace gil
+{
+//------------------------------------------------------------------------------
+
+struct assert_dimensions_match {};
+struct ensure_dimensions_match {};
+struct synchronize_dimensions {};
+
+struct assert_formats_match {};
+struct ensure_formats_match {};
+struct synchronize_formats {};
+
+
+namespace detail
+{
+//------------------------------------------------------------------------------
+
+
+typedef iterator_range<TCHAR const *> string_chunk_t;
+
+
+template <typename Pixel, bool planar>
+struct pixel_format_type : mpl::pair<Pixel, mpl::bool_<planar>> {};
+
+
+struct get_planar_pixel_iterator
+{
+ template <typename PixelFormatType>
+ struct apply
+ {
+ typedef planar_pixel_iterator
+ <
+ typename channel_type <typename PixelFormatType::first>::type,
+ typename color_space_type<typename PixelFormatType::first>::type
+ > type;
+ };
+};
+
+struct get_plain_pixel_iterator
+{
+ template <typename PixelFormatType>
+ struct apply
+ {
+ typedef typename PixelFormatType::first * type;
+ };
+};
+
+
+template <typename PixelFormat>
+struct view_for_pixel_format
+{
+ typedef typename type_from_x_iterator
+ <
+ typename mpl::if_
+ <
+ typename PixelFormat::second,
+ get_planar_pixel_iterator,
+ get_plain_pixel_iterator
+
+ >::type::apply<PixelFormat>::type
+ >::view_t type;
+};
+
+template <typename PixelFormats>
+struct views_for_pixel_formats
+ : public mpl::transform<PixelFormats, view_for_pixel_format<mpl::_1> > {};
+
+
+template <typename PixelFormat>
+struct const_view_for_pixel_format
+ :
+ public view_for_pixel_format<pixel_format_type<typename PixelFormat::first const, PixelFormat::second::value> >
+{};
+
+template <typename PixelFormats>
+struct const_views_for_pixel_formats
+ : public mpl::transform<PixelFormats, const_view_for_pixel_format<mpl::_1> > {};
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class formatted_image_base
+///
+////////////////////////////////////////////////////////////////////////////////
+
+class formatted_image_base
+{
+public:
+ typedef point2<std::ptrdiff_t> dimensions_t;
+
+ typedef unsigned int image_type_id;
+ static image_type_id const unsupported_format = -1;
+
+protected:
+ static bool dimensions_match( dimensions_t const & mine, dimensions_t const & other ) { return mine == other; }
+ template <class View>
+ static bool dimensions_match( dimensions_t const & mine, View const & view ) { return dimensions_match( mine, view.dimensions(); ) }
+
+ static void do_ensure_dimensions_match( dimensions_t const & mine, dimensions_t const & other )
+ {
+ io_error_if( !dimensions_match( mine, other ), "input view size does not match source image size" );
+ }
+ template <class View>
+ static void do_ensure_dimensions_match( dimensions_t const & mine, View const & view )
+ {
+ do_ensure_dimensions_match( mine, view.dimensions() );
+ }
+
+ static void do_ensure_formats_match( bool const formats_match )
+ {
+ io_error_if( !formats_match, "input view format does not match source image format" );
+ }
+
+protected:
+ template <typename Image>
+ void do_synchronize_dimensions( Image & image, dimensions_t const & my_dimensions, unsigned int const alignment = 0 )
+ {
+ image.recreate( my_dimensions, alignment );
+ }
+
+protected:
+ struct assert_type_mismatch
+ {
+ typedef bool result_type;
+ template <typename Index>
+ result_type operator()( Index const & ) const { BOOST_ASSERT( !"input view format does not match source image format" ); return false; }
+ };
+
+ struct throw_type_mismatch
+ {
+ typedef void result_type;
+ result_type operator()() const { do_ensure_formats_match( false ); }
+ };
+
+ template <typename Type, typename SupportedPixelFormats>
+ struct check_type_match
+ {
+ typedef bool result_type;
+ template <typename SupportedFormatIndex>
+ result_type operator()( SupportedFormatIndex const & ) const
+ {
+ return worker<SupportedFormatIndex>( mpl::less<SupportedFormatIndex, mpl::size<SupportedPixelFormats> >() );
+ }
+
+ template <typename Index>
+ bool worker( mpl::true_ /*in-range*/ ) const
+ {
+ return is_same<Type, typename mpl::at<SupportedPixelFormats, Index>::type>::value;
+ }
+ template <typename Index>
+ bool worker( mpl::false_ /*not-in-range*/ ) const
+ {
+ return false;
+ }
+ };
+
+ template <typename Images>
+ class make_dynamic_image
+ {
+ public:
+ make_dynamic_image( any_image<Images> & image ) : image_( image ) {}
+
+ template <class Image>
+ Image & apply()
+ {
+ image_.move_in( Image() );
+ return image_._dynamic_cast<Image>();
+ }
+
+ protected:
+ any_image<Images> & image_;
+ };
+
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class formatted_image
+///
+////////////////////////////////////////////////////////////////////////////////
+
+template <class Impl, class SupportedPixelFormats, class ROI>
+class formatted_image : public formatted_image_base
+{
+public:
+ //typedef typename any_image<typename Impl::supported_pixel_formats> any_image_t;
+ typedef SupportedPixelFormats supported_pixel_formats;
+ typedef ROI roi;
+
+ typedef any_image_view<typename const_views_for_pixel_formats<typename supported_pixel_formats>::type> const_view_t;
+ typedef any_image_view<typename views_for_pixel_formats <typename supported_pixel_formats>::type> view_t;
+
+ BOOST_STATIC_CONSTANT( bool, has_full_roi = (is_same<roi::offset_t, roi::point_t>::value) );
+
+protected:
+ typedef formatted_image base_t;
+
+private:
+ template <typename Images, typename dimensions_policy, typename formats_policy>
+ class read_dynamic_image : make_dynamic_image<Images>
+ {
+ private:
+ typedef make_dynamic_image<Images> base;
+ public:
+ typedef void result_type;
+
+ read_dynamic_image( any_image<Images> & image, Impl & impl )
+ :
+ base ( image ),
+ impl_( impl )
+ {}
+
+ template <class Image>
+ void apply()
+ {
+ impl_.copy_to( base::apply<Image>(), dimensions_policy(), formats_policy() );
+ }
+
+ template <typename SupportedFormatIndex>
+ void operator()( SupportedFormatIndex const & )
+ {
+ apply<typename mpl::at<SupportedFormatIndex>::type>();
+ }
+
+ private:
+ Impl & impl_;
+ };
+
+ template <typename dimensions_policy, typename formats_policy>
+ class write_dynamic_view
+ {
+ public:
+ typedef void result_type;
+
+ write_dynamic_view( Impl & impl ) : impl_( impl ) {}
+
+ template <class View>
+ void apply( View const & view )
+ {
+ impl_.copy_from( view, dimensions_policy(), formats_policy() );
+ }
+
+ private:
+ Impl & impl_;
+ };
+
+ struct write_is_supported
+ {
+ template<typename View>
+ struct apply : public Impl::is_supported<View> {};
+ };
+
+ typedef mpl::range_c<std::size_t, 0, mpl::size<supported_pixel_formats>::value> valid_type_id_range_t;
+
+private:
+ template <typename View>
+ bool formats_match()
+ {
+ Gdiplus::PixelFormat tzt = view_gp_format<View>::value;
+ return switch_<valid_type_id_range_t>
+ (
+ impl().current_image_type_id(),
+ check_type_match
+ <
+ pixel_format_type
+ <
+ typename View::value_type,
+ is_planar<typename View>::value
+ >,
+ supported_pixel_formats
+ >(),
+ assert_type_mismatch()
+ );
+ }
+
+ Impl & impl() { return static_cast<Impl &>( *this ); }
+
+public:
+ template <typename Image, typename DimensionsPolicy, typename FormatsPolicy>
+ void copy_to_image( Image & image, DimensionsPolicy const dimensions_policy, FormatsPolicy const formats_policy )
+ {
+ impl().copy_to( view( image ), dimensions_policy, formats_policy );
+ }
+
+ template <typename Image, typename FormatsPolicy>
+ void copy_to_image( Image & image, synchronize_dimensions, FormatsPolicy const formats_policy )
+ {
+ do_synchronize_dimensions( image, impl().dimensions(), Impl::desired_alignment );
+ impl().copy_to( view( image ), assert_dimensions_match(), formats_policy );
+ }
+
+ template <typename View>
+ void copy_to( View & view, assert_dimensions_match, assert_formats_match )
+ {
+ BOOST_ASSERT( dimensions_match( view.dimensions(), impl().dimensions() ) );
+ BOOST_ASSERT( formats_match<View>() );
+ impl().copy_to_prepared_view( view );
+ }
+
+ template <typename View>
+ void copy_to( View & view, assert_dimensions_match, ensure_formats_match )
+ {
+ do_ensure_formats_match( formats_match<View>() );
+ copy_to( view, assert_dimensions_match(), assert_formats_match() );
+ }
+
+ template <typename View>
+ void copy_to( View & view, ensure_dimensions_match, assert_formats_match )
+ {
+ do_ensure_dimensions_match( formats_match<View>() );
+ copy_to( view, assert_dimensions_match, assert_formats_match );
+ }
+
+ template <typename Images, typename dimensions_policy, typename formats_policy>
+ void copy_to( any_image<Images> & im )
+ {
+ typedef mpl::range_c<std::size_t, 0, typename Impl::supported_pixel_formats> valid_range_t;
+ switch_<valid_range_t>
+ (
+ Impl::current_image_type_id(),
+ read_dynamic_image<Images, dimensions_policy, formats_policy>( im, *this ),
+ throw_type_mismatch()
+ );
+ }
+
+ template <typename Views, typename dimensions_policy, typename formats_policy>
+ void copy_from( any_image_view<Views> const & runtime_view, dimensions_policy, formats_policy )
+ {
+ typedef write_dynamic_view<dimensions_policy, formats_policy> op_t;
+ op_t op( *this );
+ apply_operation
+ (
+ runtime_view,
+ dynamic_io_fnobj<write_is_supported, op_t>( &op )
+ );
+ }
+
+ void save_to( std::string const & path )
+ {
+ impl().save_to( path.c_str() );
+ }
+
+ void save_to( std::wstring const & path )
+ {
+ impl().save_to( path.c_str() );
+ }
+
+};
+
+
+//------------------------------------------------------------------------------
+} // namespace detail
+//------------------------------------------------------------------------------
+} // namespace gil
+//------------------------------------------------------------------------------
+} // namespace boost
+//------------------------------------------------------------------------------
+#endif // formatted_image_hpp

Modified: sandbox/gil/boost/gil/extension/io2/gp_private_base.hpp
==============================================================================
--- sandbox/gil/boost/gil/extension/io2/gp_private_base.hpp (original)
+++ sandbox/gil/boost/gil/extension/io2/gp_private_base.hpp 2010-03-30 12:41:39 EDT (Tue, 30 Mar 2010)
@@ -21,8 +21,9 @@
 //------------------------------------------------------------------------------
 #include "../../gil_all.hpp"
 #include "extern_lib_guard.hpp"
-#include "io_error.hpp"
+#include "formatted_image.hpp"
 #include "gp_private_istreams.hpp"
+#include "io_error.hpp"
 
 #include <boost/array.hpp>
 #include <boost/mpl/eval_if.hpp>
@@ -66,7 +67,6 @@
 typedef bgra_layout_t gp_alpha_layout_t;
 typedef bgr_layout_t gp_layout_t;
 
-// An attempt to support packed pixel formats...still does not work/compile...:
 typedef packed_pixel_type<uint16_t, mpl::vector3_c<unsigned,5,6,5>, gp_layout_t>::type gp_rgb565_pixel_t;
 
 struct unpacked_view_gp_format
@@ -97,6 +97,16 @@
 };
 
 
+typedef mpl::vector5
+<
+ pixel_format_type<pixel<bits8 , gp_layout_t >, false>,
+ pixel_format_type<pixel<bits8 , gp_alpha_layout_t>, false>,
+ pixel_format_type<pixel<bits16, gray_layout_t >, false>,
+ pixel_format_type<gp_rgb565_pixel_t , false>,
+ pixel_format_type<cmyk_t , false>
+> gp_supported_pixel_formats;
+
+
 template <class View>
 struct view_gp_format
     :
@@ -201,20 +211,49 @@
 };
 
 
+class gp_roi : public Gdiplus::Rect
+{
+public:
+ typedef INT value_type;
+ typedef point2<value_type> point_t ;
+
+ typedef point_t offset_t ;
+
+public:
+ gp_roi( value_type const x, value_type const y, value_type const width, value_type const height )
+ : Gdiplus::Rect( x, y, width, height ) {}
+
+ gp_roi( offset_t const offset, value_type const width, value_type const height )
+ : Gdiplus::Rect( Gdiplus::Point( offset.x, offset.y ), Gdiplus::Size( width, height ) ) {}
+
+ gp_roi( offset_t const top_left, offset_t const bottom_right )
+ : Gdiplus::Rect( Gdiplus::Point( top_left.x, top_left.y ), Gdiplus::Size( bottom_right.x - top_left.x, bottom_right.y - top_left.y ) ) {}
+};
+
+
 #if defined(BOOST_MSVC)
 # pragma warning( push )
 # pragma warning( disable : 4127 ) // "conditional expression is constant"
 #endif
 
-class gp_bitmap : gp_guard//, noncopyable
+class gp_image
+ :
+ private gp_guard,
+ public detail::formatted_image<gp_image, gp_supported_pixel_formats, gp_roi>
 {
+public:
+ template <class View>
+ struct is_supported : detail::is_supported<view_gp_format<View>::value> {};
+
+ BOOST_STATIC_CONSTANT( unsigned int, desired_alignment = sizeof( Gdiplus::ARGB ) );
+
 private:
     // - GP wants wide-char paths
     // - we received a narrow-char path
     // - we are using GP that means we are also using Windows
     // - on Windows a narrow-char path can only be up to MAX_PATH in length:
     // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath
- // - it is therefor safe to use a fixed sized/stack buffer...
+ // - it is therefore safe to use a fixed sized/stack buffer...
     class wide_path
     {
     public:
@@ -222,8 +261,8 @@
         {
             BOOST_ASSERT( pFilename );
             BOOST_ASSERT( std::strlen( pFilename ) < wideFileName_.size() );
- char const * pSource ( pFilename );
- WCHAR * pDestination( wideFileName_.begin() );
+ char const * pSource ( pFilename );
+ wchar_t * pDestination( wideFileName_.begin() );
             do
             {
                 *pDestination++ = *pSource;
@@ -237,31 +276,32 @@
         boost::array<wchar_t, MAX_PATH> wideFileName_;
     };
 
-protected:
- // This one is intended only for derived classes because GP uses lazy
- // evaluation of the stream so the stream object must preexist and also
- // outlive the GpBitmap object.
- explicit gp_bitmap( IStream & stream )
+
+public: /// \ingroup Construction
+ explicit gp_image( wchar_t const * const filename )
     {
- ensure_result( Gdiplus::DllExports::GdipCreateBitmapFromStreamICM( &stream, &pBitmap_ ) );
+ ensure_result( Gdiplus::DllExports::GdipCreateBitmapFromFileICM( filename, &pBitmap_ ) );
         BOOST_ASSERT( pBitmap_ );
     }
 
-public:
- explicit gp_bitmap( wchar_t const * const filename )
+ explicit gp_image( char const * const filename )
     {
- ensure_result( Gdiplus::DllExports::GdipCreateBitmapFromFileICM( filename, &pBitmap_ ) );
+ ensure_result( Gdiplus::DllExports::GdipCreateBitmapFromFileICM( wide_path( filename ), &pBitmap_ ) );
         BOOST_ASSERT( pBitmap_ );
     }
 
- explicit gp_bitmap( char const * const filename )
+ // The passed IStream object must outlive the GpBitmap object (GDI+ uses
+ // lazy evaluation).
+ explicit gp_image( IStream & stream )
     {
- ensure_result( Gdiplus::DllExports::GdipCreateBitmapFromFileICM( wide_path( filename ), &pBitmap_ ) );
+ ensure_result( Gdiplus::DllExports::GdipCreateBitmapFromStreamICM( &stream, &pBitmap_ ) );
         BOOST_ASSERT( pBitmap_ );
     }
 
+ // The passed View object must outlive the GpBitmap object (GDI+ uses lazy
+ // evaluation).
     template <class View>
- explicit gp_bitmap( View & view )
+ explicit gp_image( View & view )
     {
         // http://msdn.microsoft.com/en-us/library/ms536315(VS.85).aspx
         // stride has to be a multiple of 4 bytes
@@ -282,13 +322,13 @@
         BOOST_ASSERT( pBitmap_ );
     }
 
- ~gp_bitmap()
+ ~gp_image()
     {
         verify_result( Gdiplus::DllExports::GdipDisposeImage( pBitmap_ ) );
     }
 
 public:
- point2<std::ptrdiff_t> get_dimensions() const
+ point2<std::ptrdiff_t> dimensions() const
     {
         using namespace Gdiplus;
         REAL width, height;
@@ -296,6 +336,15 @@
         return point2<std::ptrdiff_t>( static_cast<std::ptrdiff_t>( width ), static_cast<std::ptrdiff_t>( height ) );
     }
 
+
+ void save_to_png( char const * const pFilename ) const { save_to( pFilename, png_codec() ); }
+ void save_to_png( wchar_t const * const pFilename ) const { save_to( pFilename, png_codec() ); }
+
+
+
+private: // Private formatted_image_base interface.
+ friend base_t;
+
     Gdiplus::PixelFormat get_format() const
     {
         using namespace Gdiplus;
@@ -304,17 +353,57 @@
         return format;
     }
 
+ image_type_id current_image_type_id() const
+ {
+ switch ( get_format() )
+ {
+ case PixelFormat48bppRGB :
+ case PixelFormat24bppRGB :
+ return 0;
+
+ case PixelFormat64bppARGB :
+ case PixelFormat32bppARGB :
+ return 1;
+
+ case PixelFormat16bppGrayScale:
+ return 2;
+
+ case PixelFormat16bppRGB565 :
+ return 3;
+
+ case PixelFormat32bppCMYK :
+ return 4;
+
+ default:
+ BOOST_ASSERT( !"Should not get reached." ); __assume( false );
 
+ case PixelFormat16bppRGB555 :
+
+ case PixelFormat64bppPARGB :
+ case PixelFormat32bppPARGB :
+
+ case PixelFormat16bppARGB1555 :
+
+ case PixelFormat32bppRGB :
+
+ case PixelFormat1bppIndexed :
+ case PixelFormat4bppIndexed :
+ case PixelFormat8bppIndexed :
+ return unsupported_format;
+ }
+ }
+
+public:
     template <typename View>
     void convert_to_prepared_view( View const & view ) const
     {
- BOOST_STATIC_ASSERT( is_supported<view_gp_format<View>::value>::value );
+ BOOST_STATIC_ASSERT( detail::is_supported<view_gp_format<View>::value>::value );
 
         BOOST_ASSERT( !dimensions_mismatch( view ) );
 
         using namespace Gdiplus;
 
- if ( is_supported<view_gp_format<View>::value>::value )
+ if ( detail::is_supported<view_gp_format<View>::value>::value )
         {
             PixelFormat const desired_format( view_gp_format<View>::value );
             pre_palettized_conversion<desired_format>( is_indexed<desired_format>::type() );
@@ -326,13 +415,6 @@
         }
     }
 
- template <typename View>
- void convert_to_view( View const & view ) const
- {
- ensure_dimensions_match();
- convert_to_prepared_view( view )
- }
-
     template <typename View, typename CC>
     void convert_to_prepared_view( View const & view, CC const & converter ) const
     {
@@ -349,7 +431,7 @@
         }
         else
         {
- bool const can_do_in_place( can_do_inplace_transform<typename View::value_type>() );
+ bool const can_do_in_place( can_do_inplace_transform<typename View::value_type>( my_format ) );
             if ( can_do_in_place )
             {
                 bitmapData.PixelFormat = my_format;
@@ -387,30 +469,14 @@
         }
     }
 
- template <typename View, typename CC>
- void convert_to_view( View const & view, CC const & converter ) const
- {
- ensure_dimensions_match( view );
- convert_to_prepared_view( view, converter );
- }
-
- template <typename View>
- void copy_to_view( View const & view ) const
- {
- ensure_dimensions_match( view );
- copy_to_prepared_view( view );
- }
-
     template <typename View>
     void copy_to_prepared_view( View const & view ) const
     {
- ensure_formats_match<View>();
+ BOOST_ASSERT( !dimensions_mismatch( view ) );
+ BOOST_ASSERT( !formats_mismatch<View>() );
         convert_to_prepared_view( view );
     }
 
- void save_to_png( char const * const pFilename ) const { save_to( pFilename, png_codec() ); }
- void save_to_png( wchar_t const * const pFilename ) const { save_to( pFilename, png_codec() ); }
-
 private:
     static CLSID const & png_codec()
     {
@@ -446,7 +512,7 @@
         BOOST_STATIC_ASSERT((!is_planar<View>::value /*&& view_is_basic<View>::value*/));
         BOOST_STATIC_ASSERT((boost::is_pointer<typename View::x_iterator>::value));
 
- BOOST_STATIC_ASSERT( is_supported<view_gp_format<View>::value>::value );
+ BOOST_STATIC_ASSERT( detail::is_supported<view_gp_format<View>::value>::value );
 
         return static_cast<BYTE *>( &gil::at_c<0>( view( 0, 0 ) ) );
     }
@@ -475,9 +541,6 @@
         using namespace Gdiplus;
 
         BitmapData * const pMutableBitmapData( const_cast<BitmapData *>( &bitmapData ) );
- // It actually performs faster if only ImageLockModeUserInputBuf is
- // specified, without ImageLockModeRead. Probably does no locking at all
- // even though this option is not clearly documented.
         GpStatus const load_result
         (
             DllExports::GdipBitmapLockBits
@@ -497,8 +560,8 @@
 
     void copy_to_target( Gdiplus::BitmapData const & bitmapData ) const
     {
- BOOST_ASSERT( bitmapData.Width == static_cast<UINT>( get_dimensions().x ) );
- BOOST_ASSERT( bitmapData.Height == static_cast<UINT>( get_dimensions().y ) );
+ BOOST_ASSERT( bitmapData.Width == static_cast<UINT>( dimensions().x ) );
+ BOOST_ASSERT( bitmapData.Height == static_cast<UINT>( dimensions().y ) );
         //...this need not hold as it can be used to perform GDI+ default
         //internal colour conversion...maybe i'll provide another worker
         //function...
@@ -725,7 +788,7 @@
 
     bool dimensions_mismatch( point2<std::ptrdiff_t> const & other_dimensions ) const
     {
- return other_dimensions != get_dimensions();
+ return other_dimensions != dimensions();
     }
 
 
@@ -744,7 +807,7 @@
     template <typename View>
     void ensure_dimensions_match( View const & view ) const
     {
- ensure_dimensions_match( view.get_dimensions() );
+ ensure_dimensions_match( view.dimensions() );
     }
 
     void ensure_dimensions_match( point2<std::ptrdiff_t> const & other_dimensions ) const
@@ -765,6 +828,8 @@
     }
 
 private:
+ friend class gp_view_base;
+
     Gdiplus::GpBitmap * /*const*/ pBitmap_;
 };
 
@@ -773,33 +838,127 @@
 #endif
 
 
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class gp_view_base
+///
+////////////////////////////////////////////////////////////////////////////////
+
+class gp_view_base : noncopyable
+{
+public:
+ ~gp_view_base()
+ {
+ verify_result( Gdiplus::DllExports::GdipBitmapUnlockBits( &bitmap_, &bitmapData_ ) );
+ }
+
+protected:
+ gp_view_base( gp_image & bitmap, unsigned int const lock_mode, gp_image::roi const * const p_roi = 0 )
+ :
+ bitmap_( *bitmap.pBitmap_ )
+ {
+ std::memset( &bitmapData_, 0, sizeof( bitmapData_ ) );
+
+ ensure_result
+ (
+ Gdiplus::DllExports::GdipBitmapLockBits
+ (
+ &bitmap_,
+ p_roi,
+ lock_mode,
+ bitmap.get_format(),
+ &bitmapData_
+ )
+ );
+ }
+
+ template <typename Pixel>
+ typename type_from_x_iterator<Pixel *>::view_t
+ get_typed_view()
+ {
+ //todo assert correct type...
+ interleaved_view<Pixel *>( bitmapData_.Width, bitmapData_.Height, bitmapData_.Scan0, bitmapData_.Stride );
+ }
+
+private:
+ Gdiplus::GpBitmap & bitmap_ ;
+ Gdiplus::BitmapData bitmapData_;
+};
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class gp_view
+///
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename Pixel>
+class gp_view
+ :
+ private gp_view_base,
+ public type_from_x_iterator<Pixel *>::view_t
+{
+public:
+ gp_view( gp_image & image, gp_image::roi const * const p_roi = 0 )
+ :
+ gp_view_base( image, ImageLockModeRead | ( is_const<Pixel>::value * ImageLockModeWrite ), p_roi ),
+ type_from_x_iterator<Pixel *>::view_t( get_typed_view<Pixel>() )
+ {}
+};
+
+
+//...mhmh...to be seen if necessary...
+//template <typename Pixel>
+//class gp_const_view
+// :
+// private gp_view_base,
+// public type_from_x_iterator<Pixel const *>::view_t
+//{
+//public:
+// gp_const_view( gp_image & image, gp_image::roi const * const p_roi = 0 )
+// :
+// gp_view_base( image, ImageLockModeRead ),
+// type_from_x_iterator<Pixel const *>::view_t( get_typed_view<Pixel const>() )
+// {}
+//};
+
+
+//...mhmh...to be implemented...
+//template <class Impl, class SupportedPixelFormats, class ROI>
+//inline
+//typename formatted_image<Impl, SupportedPixelFormats, ROI>::view_t
+//view( formatted_image<Impl, SupportedPixelFormats, ROI> & img );// { return img._view; }
+
+
 #pragma warning( push )
 #pragma warning( disable : 4355 ) // 'this' used in base member initializer list.
 
-class __declspec( novtable ) gp_memory_bitmap sealed
+class __declspec( novtable ) gp_memory_image sealed
     :
     private MemoryReadStream,
- public gp_bitmap
+ public gp_image
 {
 public:
- gp_memory_bitmap( memory_chunk_t const & in_memory_image )
+ gp_memory_image( memory_chunk_t const & in_memory_image )
         :
         MemoryReadStream( in_memory_image ),
- gp_bitmap ( static_cast<IStream &>( *this ) )
+ gp_image ( static_cast<IStream &>( *this ) )
     {
     }
 };
 
-class __declspec( novtable ) gp_FILE_bitmap sealed
+class __declspec( novtable ) gp_FILE_image sealed
     :
     private FileReadStream,
- public gp_bitmap
+ public gp_image
 {
 public:
- explicit gp_FILE_bitmap( FILE * const pFile )
+ explicit gp_FILE_image( FILE * const pFile )
         :
         FileReadStream( *pFile ),
- gp_bitmap ( static_cast<IStream &>( *this ) )
+ gp_image ( static_cast<IStream &>( *this ) )
     {
     }
 };

Modified: sandbox/gil/boost/gil/extension/io2/gp_private_io.hpp
==============================================================================
--- sandbox/gil/boost/gil/extension/io2/gp_private_io.hpp (original)
+++ sandbox/gil/boost/gil/extension/io2/gp_private_io.hpp 2010-03-30 12:41:39 EDT (Tue, 30 Mar 2010)
@@ -31,112 +31,112 @@
 {
 //------------------------------------------------------------------------------
 
-inline point2<std::ptrdiff_t> read_dimensions( detail::gp_bitmap const & image ) {
- return image.get_dimensions();
+inline point2<std::ptrdiff_t> read_dimensions( detail::gp_image const & image ) {
+ return image.dimensions();
 }
 
 inline point2<std::ptrdiff_t> read_dimensions( char const * const filename ) {
- return read_dimensions( gp_bitmap( filename ) );
+ return read_dimensions( gp_image( filename ) );
 }
 
 
 template <typename View>
-inline void read_view( gp_bitmap const & image, View const & view ) {
+inline void read_view( gp_image const & image, View const & view ) {
     image.copy_to_view( view );
 }
 
 template <typename View>
 inline void read_view( char const * const filename, View const & view ) {
- read_view( gp_bitmap( filename ), view );
+ read_view( gp_image( filename ), view );
 }
 
 
 template <typename Image>
-inline void read_image( gp_bitmap const & gp_image, Image & gil_image ) {
+inline void read_image( gp_image const & gp_image, Image & gil_image ) {
     gil_image.recreate( gp_image.get_dimensions(), sizeof( Gdiplus::ARGB ) );
     gp_image.copy_to_prepared_view( view( gil_image ) );
 }
 
 template <typename Image>
 inline void read_image(const char* filename,Image& im) {
- read_image( gp_bitmap( filename ), im );
+ read_image( gp_image( filename ), im );
 }
 
 template <typename Image>
 inline void read_image( wchar_t const * const filename, Image & im ) {
- read_image( gp_bitmap( filename ), im );
+ read_image( gp_image( filename ), im );
 }
 
 
 template <typename View,typename CC>
-inline void read_and_convert_view( gp_bitmap const & image, View const & view, CC cc ) {
+inline void read_and_convert_view( gp_image const & image, View const & view, CC cc ) {
     image.convert_to_view( view, cc );
 }
 
 template <typename View,typename CC>
 inline void read_and_convert_view( char const * const filename, View const & view, CC cc ) {
- read_and_convert_view( gp_bitmap( filename ), view, cc );
+ read_and_convert_view( gp_image( filename ), view, cc );
 }
 
 
 template <typename View>
-inline void read_and_convert_view( gp_bitmap const & image, View const & view ) {
+inline void read_and_convert_view( gp_image const & image, View const & view ) {
     image.convert_to_view( view );
 }
 
 template <typename View>
 inline void read_and_convert_view( const char* filename, const View& view ) {
- read_and_convert_view( gp_bitmap( filename ), view );
+ read_and_convert_view( gp_image( filename ), view );
 }
 
 
 template <typename Image,typename CC>
-inline void read_and_convert_image( gp_bitmap const & gp_image, Image & gil_image, CC cc ) {
+inline void read_and_convert_image( gp_image const & gp_image, Image & gil_image, CC cc ) {
     gil_image.recreate( gp_image.get_dimensions(), sizeof( Gdiplus::ARGB ) );
     gp_image.convert_to_prepared_view( view( gil_image ), cc );
 }
 
 template <typename Image,typename CC>
 inline void read_and_convert_image(const char* filename,Image& im,CC cc) {
- read_and_convert_image( gp_bitmap( filename ), im, cc );
+ read_and_convert_image( gp_image( filename ), im, cc );
 }
 
 template <typename Image,typename CC>
 inline void read_and_convert_image( wchar_t const * const filename, Image & im, CC const & cc ) {
- read_and_convert_image( gp_bitmap( filename ), im, cc );
+ read_and_convert_image( gp_image( filename ), im, cc );
 }
 
 
 template <typename Image>
-inline void read_and_convert_image( gp_bitmap const & gp_image, Image & gil_image ) {
- gil_image.recreate( gp_image.get_dimensions(), sizeof( Gdiplus::ARGB ) );
+inline void read_and_convert_image( gp_image const & gp_image, Image & gil_image ) {
+ gil_image.recreate( gp_image.dimensions(), sizeof( Gdiplus::ARGB ) );
     gp_image.convert_to_prepared_view( view( gil_image ) );
 }
 
 template <typename Image>
 inline void read_and_convert_image(const char* filename,Image& im) {
- read_and_convert_image( gp_bitmap( filename ), im );
+ read_and_convert_image( gp_image( filename ), im );
 }
 
 template <typename Image>
 inline void read_and_convert_image( wchar_t const * const filename, Image & im ) {
- read_and_convert_image( gp_bitmap( filename ), im );
+ read_and_convert_image( gp_image( filename ), im );
 }
 
 template <typename Image>
 inline void read_and_convert_image( FILE * pFile, Image & im ) {
- read_and_convert_image( gp_FILE_bitmap( pFile ), im );
+ read_and_convert_image( gp_FILE_image( pFile ), im );
 }
 
 template <typename Image>
 inline void read_and_convert_image( memory_chunk_t const & in_memory_image, Image & im ) {
- read_and_convert_image( gp_memory_bitmap( in_memory_image ), im );
+ read_and_convert_image( gp_memory_image( in_memory_image ), im );
 }
 
 
 template <typename View>
 inline void png_write_view(const char* filename,const View& view) {
- detail::gp_bitmap const m( view );
+ detail::gp_image const m( view );
     m.save_to_png( filename );
 }
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk