$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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 );
 }