$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r65454 - in sandbox/gil/boost/gil/extension/io2: . detail
From: dsaritz_at_[hidden]
Date: 2010-09-18 17:27:53
Author: psiha
Date: 2010-09-18 17:27:50 EDT (Sat, 18 Sep 2010)
New Revision: 65454
URL: http://svn.boost.org/trac/boost/changeset/65454
Log:
Fixed/updated the GDI+ backend guard classes to conform to the current design (added the appropriate typedef to the gp_image class, moved the gp_guard class to the gp_extern_lib_guard.hpp header, cleaned up the said header...).
Updated the LibTIFF and GDI+ backends to conform to the current design (moved the X_image classes to the public/gil namespace, renamed the LibTIFF backend header appropriately...).
Added various new utility/guard classes to the libx_shared.hpp and windows_shared.hpp headers.
Moved the 'memory_chunk' typedefs to the shared.hpp header.
Moved the formatted_image_traits<> template to the public/gil namespace, updated all backends accordingly.
Decided on first global design/guidelines for write functionality (added the the formatted_image<>::writer_for<> template class along with various helper wrapper classes). Added write capabilities (writer implementations) to all backends.
Added the utility read() and write() formatted_image<> static member funcitons.
Added the view_data_t typedef to the formatted_image<> template (saved some verbosity in the concrete classes).
Minor other refactoring, optimization and stylistic changes.
Added:
   sandbox/gil/boost/gil/extension/io2/libtiff_image.hpp
      - copied, changed from r65436, /sandbox/gil/boost/gil/extension/io2/libtiff_private_base.hpp
Removed:
   sandbox/gil/boost/gil/extension/io2/libtiff_private_base.hpp
Text files modified: 
   sandbox/gil/boost/gil/extension/io2/detail/gp_extern_lib_guard.hpp     |   156 ++++++++------                          
   sandbox/gil/boost/gil/extension/io2/detail/libx_shared.hpp             |    83 +++++++                                 
   sandbox/gil/boost/gil/extension/io2/detail/shared.hpp                  |     6                                         
   sandbox/gil/boost/gil/extension/io2/detail/windows_shared.hpp          |   100 +++++++++                               
   sandbox/gil/boost/gil/extension/io2/detail/windows_shared_istreams.hpp |     6                                         
   sandbox/gil/boost/gil/extension/io2/formatted_image.hpp                |   131 ++++++++++-                             
   sandbox/gil/boost/gil/extension/io2/gp_image.hpp                       |   286 +++++++++++++++------------             
   sandbox/gil/boost/gil/extension/io2/libjpeg_image.hpp                  |   111 +++++++---                              
   sandbox/gil/boost/gil/extension/io2/libpng_image.hpp                   |   408 +++++++++++++++++++++++++++++---------- 
   sandbox/gil/boost/gil/extension/io2/libtiff_image.hpp                  |   325 +++++++++++++++++++++----------         
   sandbox/gil/boost/gil/extension/io2/wic_image.hpp                      |   257 +++++++++++++++++-------                
   11 files changed, 1310 insertions(+), 559 deletions(-)
Modified: sandbox/gil/boost/gil/extension/io2/detail/gp_extern_lib_guard.hpp
==============================================================================
--- sandbox/gil/boost/gil/extension/io2/detail/gp_extern_lib_guard.hpp	(original)
+++ sandbox/gil/boost/gil/extension/io2/detail/gp_extern_lib_guard.hpp	2010-09-18 17:27:50 EDT (Sat, 18 Sep 2010)
@@ -55,6 +55,7 @@
 
 #else // BOOST_LIB_LINK( BOOST_GIL_EXTERNAL_LIB ) != BOOST_LIB_LINK_LOADTIME_OR_STATIC
 
+//------------------------------------------------------------------------------
 } // namespace gil
 
 /// \todo This 'configurability' needs to be handled better.
@@ -64,12 +65,15 @@
     gil::io_error_if( !lib_handle(), "Boost.GIL failed to load external library." );
 }
 
+//------------------------------------------------------------------------------
 } // namespace boost
 
 namespace Gdiplus
 {
+//------------------------------------------------------------------------------
 namespace DllExports
 {
+//------------------------------------------------------------------------------
 
 #define ALWAYS 1
 
@@ -105,7 +109,8 @@
 #undef GP1_1
 #undef GP_FUNCTION
 
-}
+//------------------------------------------------------------------------------
+} // namespace DllExports
 
 // Implementation note:
 //   GDI+ puts all functions in the DllExports namespace (hides the 'flat API')
@@ -129,104 +134,121 @@
     return DllExports::GdiplusShutdown( token );
 }
 
-}
+//------------------------------------------------------------------------------
+} // namespace GdiPlus
 
 namespace boost
 {
+//------------------------------------------------------------------------------
 namespace gil
 {
+//------------------------------------------------------------------------------
 namespace detail
 {
-    typedef Gdiplus::DllExports::gp_guard_base gp_guard_base;
+//------------------------------------------------------------------------------
+
+typedef Gdiplus::DllExports::gp_guard_base gp_guard_base;
 
-    #if BOOST_LIB_LINK( BOOST_GIL_EXTERNAL_LIB ) == BOOST_LIB_LINK_RUNTIME_ASSUME_LOADED
-        // The user/gil_io_lib_guard loads the lib.
-        typedef
-            BOOST_PP_IF
-            (
-                BOOST_PP_GREATER( BOOST_LIB_LOADING( BOOST_GIL_EXTERNAL_LIB ), BOOST_LIB_LOADING_SINGLE ),
-                win32_reloadable_lib_guard,
-                win32_delayloaded_lib_guard
-            ) gil_io_lib_guard_base_helper;
+#if BOOST_LIB_LINK( BOOST_GIL_EXTERNAL_LIB ) == BOOST_LIB_LINK_RUNTIME_ASSUME_LOADED
+    // The user/gil_io_lib_guard loads the lib.
+    typedef
+        BOOST_PP_IF
+        (
+            BOOST_PP_GREATER( BOOST_LIB_LOADING( BOOST_GIL_EXTERNAL_LIB ), BOOST_LIB_LOADING_SINGLE ),
+            win32_reloadable_lib_guard,
+            win32_delayloaded_lib_guard
+        ) gil_io_lib_guard_base_helper;
 
-        class gil_io_lib_guard_base : gil_io_lib_guard_base_helper
+    class gil_io_lib_guard_base : gil_io_lib_guard_base_helper
+    {
+    public:
+        template <typename Char>
+        gil_io_lib_guard_base( Char const * const lib_name )
+            : gil_io_lib_guard_base_helper( lib_name )
         {
-        public:
-            template <typename Char>
-            gil_io_lib_guard_base( Char const * const lib_name )
-                : gil_io_lib_guard_base_helper( lib_name )
-            {
-                #if BOOST_LIB_INIT( BOOST_GIL_EXTERNAL_LIB ) == BOOST_LIB_INIT_ASSUME
-                // The user/gil_io_lib_guard inits the lib so it also has to
-                // init the function pointers (required for initialization).
-                    gp_guard_base::init_functions( lib_handle() );
-                #endif // BOOST_LIB_INIT_ASSUME
-            }
-        };
-
-    #else // BOOST_LIB_LINK_RUNTIME_AUTO_LOAD
-        // GIL loads the lib automatically every time.
-        typedef dummy_lib_guard gil_io_lib_guard_base;
+            #if BOOST_LIB_INIT( BOOST_GIL_EXTERNAL_LIB ) == BOOST_LIB_INIT_ASSUME
+            // The user/gil_io_lib_guard inits the lib so it also has to
+            // init the function pointers (required for initialization).
+                gp_guard_base::init_functions( lib_handle() );
+            #endif // BOOST_LIB_INIT_ASSUME
+        }
+    };
+
+#else // BOOST_LIB_LINK_RUNTIME_AUTO_LOAD
+    // GIL loads the lib automatically every time.
+    typedef dummy_lib_guard gil_io_lib_guard_base;
 
-    #endif // BOOST_LIB_LINK( BOOST_GIL_EXTERNAL_LIB )
+#endif // BOOST_LIB_LINK( BOOST_GIL_EXTERNAL_LIB )
 
+//------------------------------------------------------------------------------
 } // namespace detail
 
 #endif // BOOST_LIB_LINK( BOOST_GIL_EXTERNAL_LIB ) != BOOST_LIB_LINK_LOADTIME_OR_STATIC
 
 namespace detail
 {
-    class gp_initialize_guard : noncopyable
-    {
-    public:
-        gp_initialize_guard();
-        ~gp_initialize_guard();
-    private:
-        ULONG_PTR gp_token_;
-    };
+//------------------------------------------------------------------------------
+
+class gp_initialize_guard : noncopyable
+{
+public:
+    gp_initialize_guard();
+    ~gp_initialize_guard();
+private:
+    ULONG_PTR gp_token_;
+};
 
-    void ensure_result( Gdiplus::GpStatus );
+void ensure_result( Gdiplus::GpStatus );
 
-    inline gp_initialize_guard::gp_initialize_guard()
-    {
-        using namespace Gdiplus;
+inline gp_initialize_guard::gp_initialize_guard()
+{
+    using namespace Gdiplus;
 
-        #if (GDIPVER >= 0x0110)
-            GdiplusStartupInputEx const gp_startup_input( GdiplusStartupNoSetRound, 0, true, true );
-        #else
-            GdiplusStartupInput   const gp_startup_input(                           0, true, true );
-        #endif //(GDIPVER >= 0x0110)
-        GdiplusStartupOutput gp_startup_output;
-        ensure_result
+    #if (GDIPVER >= 0x0110)
+        GdiplusStartupInputEx const gp_startup_input( GdiplusStartupNoSetRound, 0, true, true );
+    #else
+        GdiplusStartupInput   const gp_startup_input(                           0, true, true );
+    #endif //(GDIPVER >= 0x0110)
+    GdiplusStartupOutput gp_startup_output;
+    ensure_result
+    (
+        GdiplusStartup
         (
-            GdiplusStartup
-            (
-                &gp_token_,
-                &gp_startup_input,
-                &gp_startup_output
-            )
-        );
-    }
+            &gp_token_,
+            &gp_startup_input,
+            &gp_startup_output
+        )
+    );
+}
 
-    inline gp_initialize_guard::~gp_initialize_guard()
-    {
-        Gdiplus::GdiplusShutdown( gp_token_ );
-    }
+inline gp_initialize_guard::~gp_initialize_guard()
+{
+    Gdiplus::GdiplusShutdown( gp_token_ );
+}
 
-} // namespace detail
 
-class gil_io_lib_guard
+class gp_guard
     :
-    detail::gil_io_lib_guard_base
+    gp_guard_base
+    #if BOOST_LIB_INIT( BOOST_GIL_EXTERNAL_LIB ) == BOOST_LIB_INIT_AUTO
+        ,gp_initialize_guard
+    #endif
+{};
+
+
+class gp_user_guard
+    :
+    gil_io_lib_guard_base
     #if BOOST_LIB_INIT( BOOST_GIL_EXTERNAL_LIB ) == BOOST_LIB_INIT_ASSUME
-        ,detail::gp_initialize_guard
+        ,gp_initialize_guard
     #endif // BOOST_LIB_INIT_ASSUME
 {
 public:
-    gil_io_lib_guard() : detail::gil_io_lib_guard_base( L"gdiplus.dll" ) {}
+    gp_user_guard() : gil_io_lib_guard_base( L"gdiplus.dll" ) {}
 };
 
-
+//------------------------------------------------------------------------------
+} // namespace detail
 //------------------------------------------------------------------------------
 } // namespace gil
 //------------------------------------------------------------------------------
Modified: sandbox/gil/boost/gil/extension/io2/detail/libx_shared.hpp
==============================================================================
--- sandbox/gil/boost/gil/extension/io2/detail/libx_shared.hpp	(original)
+++ sandbox/gil/boost/gil/extension/io2/detail/libx_shared.hpp	2010-09-18 17:27:50 EDT (Sat, 18 Sep 2010)
@@ -22,6 +22,7 @@
 #include "../../../utilities.hpp"
 #include "io_error.hpp"
 
+#include "boost/assert.hpp"
 #include "boost/noncopyable.hpp"
 
 #include "crtdefs.h"
@@ -37,7 +38,6 @@
 {
 //------------------------------------------------------------------------------
 
-
 ////////////////////////////////////////////////////////////////////////////////
 ///
 /// \class generic_vertical_roi
@@ -71,7 +71,6 @@
 };
 
 
-
 ////////////////////////////////////////////////////////////////////////////////
 ///
 /// \class c_file_guard
@@ -81,13 +80,13 @@
 class c_file_guard : noncopyable
 {
 public:
-    c_file_guard( char const * const file_name )
+    c_file_guard( char const * const file_name, char const * const mode )
         :
-        p_file_( /*std*/::fopen( file_name, "rb" ) )
+        p_file_( /*std*/::fopen( file_name, mode ) )
     {
-        io_error_if( !p_file_, "File open failure" );
+        io_error_if_not( p_file_, "File open failure" );
     }
-    ~c_file_guard() { /*std*/::fclose( p_file_ ); }
+    ~c_file_guard() { BOOST_VERIFY( /*std*/::fclose( p_file_ ) == 0 ); }
 
     FILE & get() const { return *p_file_; }
 
@@ -98,6 +97,78 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
+/// \class c_file_input_guard
+///
+////////////////////////////////////////////////////////////////////////////////
+
+class c_file_input_guard : public c_file_guard
+{
+public:
+    c_file_input_guard( char const * const file_name ) : c_file_guard( file_name, "rb" ) {}
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class c_file_output_guard
+///
+////////////////////////////////////////////////////////////////////////////////
+
+class c_file_output_guard : public c_file_guard
+{
+public:
+    c_file_output_guard( char const * const file_name ) : c_file_guard( file_name, "wb" ) {}
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class input_c_str_for_c_file_extender
+/// \internal
+/// \brief Helper wrapper for classes that can construct from FILE objects.
+///
+////////////////////////////////////////////////////////////////////////////////
+
+template <class c_file_capable_class>
+class input_c_str_for_c_file_extender
+    :
+    private c_file_input_guard,
+    public  c_file_capable_class
+{
+public:
+    input_c_str_for_c_file_extender( char const * const file_path )
+        :
+        c_file_input_guard  ( file_path           ),
+        c_file_capable_class( c_file_guard::get() )
+    {}
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class output_c_str_for_c_file_extender
+/// \internal
+/// \brief Helper wrapper for classes that can construct from FILE objects.
+///
+////////////////////////////////////////////////////////////////////////////////
+
+template <class c_file_capable_class>
+class output_c_str_for_c_file_extender
+    :
+    private c_file_output_guard,
+    public  c_file_capable_class
+{
+public:
+    output_c_str_for_c_file_extender( char const * const file_path )
+        :
+        c_file_output_guard ( file_path           ),
+        c_file_capable_class( c_file_guard::get() )
+    {}
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
 /// \class cumulative_result
 ///
 ////////////////////////////////////////////////////////////////////////////////
Modified: sandbox/gil/boost/gil/extension/io2/detail/shared.hpp
==============================================================================
--- sandbox/gil/boost/gil/extension/io2/detail/shared.hpp	(original)
+++ sandbox/gil/boost/gil/extension/io2/detail/shared.hpp	2010-09-18 17:27:50 EDT (Sat, 18 Sep 2010)
@@ -19,6 +19,8 @@
 #ifndef shared_hpp__DA4F9174_EBAA_43E8_BEDD_A273BBA88CE7
 #define shared_hpp__DA4F9174_EBAA_43E8_BEDD_A273BBA88CE7
 //------------------------------------------------------------------------------
+#include <boost/range/iterator_range.hpp>
+//------------------------------------------------------------------------------
 namespace boost
 {
 //------------------------------------------------------------------------------
@@ -43,6 +45,10 @@
 
 //------------------------------------------------------------------------------
 } // namespace detail
+
+typedef iterator_range<unsigned char const *> memory_chunk_t;
+typedef iterator_range<unsigned char       *> writable_memory_chunk_t;
+
 //------------------------------------------------------------------------------
 } // namespace gil
 //------------------------------------------------------------------------------
Modified: sandbox/gil/boost/gil/extension/io2/detail/windows_shared.hpp
==============================================================================
--- sandbox/gil/boost/gil/extension/io2/detail/windows_shared.hpp	(original)
+++ sandbox/gil/boost/gil/extension/io2/detail/windows_shared.hpp	2010-09-18 17:27:50 EDT (Sat, 18 Sep 2010)
@@ -1,7 +1,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 ///
 /// \file windows_shared.hpp
-/// ----------------------------
+/// ------------------------
 ///
 ///   Common functionality for MS Windows based backends.
 ///
@@ -18,6 +18,8 @@
 #ifndef windows_shared_hpp__9337A434_D2F6_43F2_93C8_4CE66C07B74D
 #define windows_shared_hpp__9337A434_D2F6_43F2_93C8_4CE66C07B74D
 //------------------------------------------------------------------------------
+#include "shared.hpp"
+
 #include "boost/array.hpp"
 #include "boost/assert.hpp"
 
@@ -71,6 +73,102 @@
 };
 
 
+#pragma warning( push )
+#pragma warning( disable : 4355 ) // 'this' used in base member initializer list.
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class input_FILE_for_IStream_extender
+/// \internal
+/// \brief Helper wrapper for classes that can construct from IStream objects.
+///
+////////////////////////////////////////////////////////////////////////////////
+
+template <class IStream_capable_class>
+class __declspec( novtable ) input_FILE_for_IStream_extender
+    :
+    private FileReadStream,
+    public  IStream_capable_class
+{
+public:
+    input_FILE_for_IStream_extender( FILE & file )
+        :
+        FileReadStream       ( file                            ),
+        IStream_capable_class( static_cast<IStream &>( *this ) )
+    {}
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class output_FILE_for_IStream_extender
+/// \internal
+/// \brief Helper wrapper for classes that can construct from IStream objects.
+///
+////////////////////////////////////////////////////////////////////////////////
+
+template <class IStream_capable_class>
+class __declspec( novtable ) output_FILE_for_IStream_extender
+    :
+    private FileWriteStream,
+    public  IStream_capable_class
+{
+public:
+    output_FILE_for_IStream_extender( FILE & file )
+        :
+        FileWriteStream      ( file                            ),
+        IStream_capable_class( static_cast<IStream &>( *this ) )
+    {}
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class memory_chunk_for_IStream_extender
+/// \internal
+/// \brief Helper wrapper for classes that can construct from IStream objects.
+///
+////////////////////////////////////////////////////////////////////////////////
+
+template <class IStream_capable_class>
+class __declspec( novtable ) memory_chunk_for_IStream_extender
+    :
+    private MemoryReadStream,
+    public  IStream_capable_class
+{
+public:
+    memory_chunk_for_IStream_extender( memory_chunk_t const & in_memory_image )
+        :
+        MemoryReadStream     ( in_memory_image                 ),
+        IStream_capable_class( static_cast<IStream &>( *this ) )
+    {}
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class writable_memory_chunk_for_IStream_extender
+/// \internal
+/// \brief Helper wrapper for classes that can construct from IStream objects.
+///
+////////////////////////////////////////////////////////////////////////////////
+
+template <class IStream_capable_class>
+class __declspec( novtable ) writable_memory_chunk_for_IStream_extender
+    :
+    private MemoryWriteStream,
+    public  IStream_capable_class
+{
+public:
+    writable_memory_chunk_for_IStream_extender( writable_memory_chunk_t const & in_memory_image )
+        :
+        MemoryWriteStream     ( in_memory_image                ),
+        IStream_capable_class( static_cast<IStream &>( *this ) )
+    {}
+};
+
+#pragma warning( pop )
+
 //------------------------------------------------------------------------------
 } // namespace detail
 //------------------------------------------------------------------------------
Modified: sandbox/gil/boost/gil/extension/io2/detail/windows_shared_istreams.hpp
==============================================================================
--- sandbox/gil/boost/gil/extension/io2/detail/windows_shared_istreams.hpp	(original)
+++ sandbox/gil/boost/gil/extension/io2/detail/windows_shared_istreams.hpp	2010-09-18 17:27:50 EDT (Sat, 18 Sep 2010)
@@ -19,7 +19,7 @@
 #ifndef windows_shared_istreams_hpp__A8D022F0_BBFA_4496_8252_8FD1F6A28DF7
 #define windows_shared_istreams_hpp__A8D022F0_BBFA_4496_8252_8FD1F6A28DF7
 //------------------------------------------------------------------------------
-#include <boost/range/iterator_range.hpp>
+#include "shared.hpp"
 
 #include "objbase.h"
 #include "objidl.h"
@@ -246,10 +246,6 @@
 };
 
 
-typedef iterator_range<unsigned char const *> memory_chunk_t;
-typedef iterator_range<unsigned char       *> writable_memory_chunk_t;
-
-
 ////////////////////////////////////////////////////////////////////////////////
 ///
 /// \class MemoryStreamBase
Modified: sandbox/gil/boost/gil/extension/io2/formatted_image.hpp
==============================================================================
--- sandbox/gil/boost/gil/extension/io2/formatted_image.hpp	(original)
+++ sandbox/gil/boost/gil/extension/io2/formatted_image.hpp	2010-09-18 17:27:50 EDT (Sat, 18 Sep 2010)
@@ -42,6 +42,7 @@
 #endif // _DEBUG
 #include <boost/range/iterator_range.hpp>
 #include <boost/static_assert.hpp>
+#include <boost/type_traits/decay.hpp>
 //------------------------------------------------------------------------------
 namespace boost
 {
@@ -196,6 +197,15 @@
 offset_view_t<View, Offset> offset_view( View const & view, Offset const & offset ) { return offset_view_t<View, Offset>( view, offset ); }
 
 
+////////////////////////////////////////////////////////////////////////////////
+/// \class formatted_image_traits
+/// ( forward declaration )
+////////////////////////////////////////////////////////////////////////////////
+
+template <class Impl>
+struct formatted_image_traits;
+
+
 namespace detail
 {
 //------------------------------------------------------------------------------
@@ -240,6 +250,65 @@
 template <typename View, typename Offset>
 struct get_original_view_t<offset_view_t<View, Offset> > { typedef View type; };
 
+// Tag base classes for writer implementations.
+struct configure_on_write_writer {};
+struct open_on_write_writer      {};
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class open_then_configure_writer_wrapper
+/// \internal
+/// \brief Helper wrapper for backends/writers that first need to open the
+/// target/file and then be configured for the desired view.
+///
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename Writer, typename WriterTarget, typename ViewDataHolder>
+class open_then_configure_writer_wrapper : public Writer
+{
+public:
+    template <typename View>
+    open_then_configure_writer_wrapper( WriterTarget const target, View const & view )
+        :
+        Writer    ( target ),
+        view_data_( view   )
+    {}
+
+    void write_default() { Writer::write_default( view_data_ ); }
+    void write        () { Writer::write        ( view_data_ ); }
+
+private:
+    ViewDataHolder const view_data_;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class configure_then_open_writer_wrapper
+/// \internal
+/// \brief Helper wrapper for backends/writers that first need to be configured
+/// for/created from the desired view and then open the target/file.
+///
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename Writer, typename WriterTarget>
+class configure_then_open_writer_wrapper : public Writer
+{
+public:
+    template <typename View>
+    configure_then_open_writer_wrapper( WriterTarget const target, View const & view )
+        :
+        Writer ( view   ),
+        target_( target )
+    {}
+
+    void write_default() { Writer::write_default( target_ ); }
+    void write        () { Writer::write        ( target_ ); }
+
+private:
+    WriterTarget const target_;
+};
+
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
@@ -374,21 +443,9 @@
     protected:
         any_image<Images> & image_;
     };
-
 };
 
 
-
-
-////////////////////////////////////////////////////////////////////////////////
-/// \class formatted_image_traits
-/// ( forward declaration )
-////////////////////////////////////////////////////////////////////////////////
-
-template <class Impl>
-struct formatted_image_traits;
-
-
 ////////////////////////////////////////////////////////////////////////////////
 ///
 /// \class formatted_image
@@ -413,10 +470,32 @@
     struct reader_for
         : public mpl::at<typename formatted_image_traits<Impl>::readers, Source> {};
 
+    template <typename Target>
+    struct writer_for
+    {
+    private:
+        typedef typename mpl::at<typename formatted_image_traits<Impl>::writers, Target>::type writer_t;
+
+    public:
+        typedef typename mpl::if_
+                         <
+                            is_base_of<configure_on_write_writer, writer_t>,
+                            open_then_configure_writer_wrapper<writer_t, Target, typename formatted_image_traits<Impl>::writer_view_data_t>,
+                            typename mpl::if_
+                            <
+                                is_base_of<open_on_write_writer, writer_t>,
+                                configure_then_open_writer_wrapper<writer_t, Target>,
+                                writer_t
+                            >::type
+                         >::type type;
+    };
+
     BOOST_STATIC_CONSTANT( bool, has_full_roi = (is_same<roi::offset_t, roi::point_t>::value) );
 
 protected:
-    typedef formatted_image base_t;
+    typedef          formatted_image                           base_t;
+
+    typedef typename formatted_image_traits<Impl>::view_data_t view_data_t;
 
 private:
     template <typename Images, typename dimensions_policy, typename formats_policy>
@@ -492,8 +571,9 @@
     };
 
 private:
-    Impl       & impl()       { return static_cast<Impl       &>( *this ); }
-    Impl const & impl() const { return static_cast<Impl const &>( *this ); }
+    // ...zzz...MSVC++ 10 generates code to check whether this == 0.txt...investigate...
+    Impl       & impl()       { __assume( this != 0 ); return static_cast<Impl       &>( *this ); }
+    Impl const & impl() const { __assume( this != 0 ); return static_cast<Impl const &>( *this ); }
 
 protected:
     template <typename View>
@@ -521,7 +601,7 @@
 
     bool formats_mismatch( typename formatted_image_traits<Impl>::format_t const other_format ) const
     {
-        return static_cast<bool>( other_format != impl().closest_gil_supported_format() );
+        return ( other_format != impl().closest_gil_supported_format() ) != false;
     }
 
     template <class View>
@@ -560,7 +640,7 @@
         BOOST_ASSERT( !impl().formats_mismatch<View>()    );
         impl().raw_copy_to_prepared_view
         (
-            formatted_image_traits<Impl>::view_data_t
+            view_data_t
             (
                 original_view       ( view ),
                 get_offset<offset_t>( view )
@@ -669,6 +749,19 @@
         );
     }
 
+public: // Utility 'quick-wrappers'...
+    template <class Source, class Image>
+    static void read( Source const & target, Image & image )
+    {
+        typename reader_for<typename decay<Source>::type>::type( target ).copy_to_image( image, synchronize_dimensions(), synchronize_formats() );
+    }
+
+    template <class Target, class View>
+    static void write( Target const & target, View const & view )
+    {
+        typename writer_for<typename decay<Target>::type>::type( target, view ).write_default();
+    }
+
 private:
     template <class View, typename CC>
     class in_place_converter_t
@@ -814,7 +907,7 @@
         unsigned int const current_image_format_id( impl().image_format_id( current_format ) );
         if ( can_do_inplace_transform<View>( current_format ) )
         {
-            typename formatted_image_traits<Impl>::view_data_t view_data( original_view( view ), get_offset<offset_t>( view ) );
+            view_data_t view_data( original_view( view ), get_offset<offset_t>( view ) );
             view_data.set_format( current_format );
             impl().raw_copy_to_prepared_view( view_data );
             in_place_transform( current_image_format_id, original_view( view ), converter );
@@ -836,7 +929,7 @@
     {
         impl().raw_convert_to_prepared_view
         (
-            formatted_image_traits<Impl>::view_data_t
+            view_data_t
             (
                 original_view       ( view ),
                 get_offset<offset_t>( view )
Modified: sandbox/gil/boost/gil/extension/io2/gp_image.hpp
==============================================================================
--- sandbox/gil/boost/gil/extension/io2/gp_image.hpp	(original)
+++ sandbox/gil/boost/gil/extension/io2/gp_image.hpp	2010-09-18 17:27:50 EDT (Sat, 18 Sep 2010)
@@ -153,17 +153,6 @@
 }
 
 
-
-class gp_guard
-    :
-    gp_guard_base
-#if BOOST_LIB_INIT( BOOST_GIL_EXTERNAL_LIB ) == BOOST_LIB_INIT_AUTO
-    ,gp_initialize_guard
-#endif
-{
-};
-
-
 class gp_roi : public Gdiplus::Rect
 {
 public:
@@ -183,6 +172,109 @@
         : Gdiplus::Rect( Gdiplus::Point( top_left.x, top_left.y ), Gdiplus::Size( bottom_right.x - top_left.x, bottom_right.y - top_left.y ) ) {}
 };
 
+
+class gp_writer : public open_on_write_writer
+{
+public:
+    typedef std::pair<Gdiplus::GpBitmap *, Gdiplus::EncoderParameters *> lib_object_t;
+
+    // The passed View object must outlive the GpBitmap object (GDI+ uses lazy
+    // evaluation).
+    template <class View>
+    explicit gp_writer( View & view )
+    {
+        BOOST_STATIC_ASSERT( is_supported<view_gp_format::apply<View>::value>::value );
+
+        // http://msdn.microsoft.com/en-us/library/ms536315(VS.85).aspx
+        // stride has to be a multiple of 4 bytes
+        BOOST_ASSERT( !( view.pixels().row_size() % sizeof( Gdiplus::ARGB ) ) );
+
+        ensure_result
+        (
+            Gdiplus::DllExports::GdipCreateBitmapFromScan0
+            (
+                view.width (),
+                view.height(),
+                view.pixels().row_size(),
+                view_gp_format::apply<View>::value,
+                formatted_image_base::get_raw_data( view ),
+                &lib_object().first
+            )
+        );
+        BOOST_ASSERT( lib_object().first );
+    }
+
+    ~gp_writer()
+    {
+        detail::verify_result( Gdiplus::DllExports::GdipDisposeImage( lib_object().first ) );
+    }
+
+    template <typename Target>
+    void write_default( Target const & target )
+    {
+        BOOST_ASSERT( lib_object().second == NULL );
+        write( target );
+    }
+
+    void write( char    const * const pFilename, CLSID const & encoderID = jpg_codec() ) const
+    {
+        write( detail::wide_path( pFilename ), encoderID );
+    }
+
+    void write( wchar_t const * const pFilename, CLSID const & encoderID = jpg_codec() ) const
+    {
+        save_to( pFilename, encoderID );
+    }
+
+    lib_object_t       & lib_object()       { return lib_instance_; }
+    lib_object_t const & lib_object() const { return lib_instance_; }
+
+private:
+    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() ); }
+
+    void save_to( char    const * const pFilename, CLSID const & encoderID ) const { save_to( detail::wide_path( pFilename ), encoderID ); }
+    void save_to( wchar_t const * const pFilename, CLSID const & encoderID ) const
+    {
+        detail::ensure_result( Gdiplus::DllExports::GdipSaveImageToFile( lib_object().first, pFilename, &encoderID, lib_object().second ) );
+    }
+
+    static CLSID const & png_codec()
+    {
+        static CLSID const clsid = { 0x557cf406, 0x1a04, 0x11d3, 0x9A, 0x73, 0x00, 0x00, 0xF8, 0x1E, 0xF3, 0x2E };
+        return clsid;
+    }
+    static CLSID const & jpg_codec()
+    {
+        static CLSID const clsid = { 0x557CF401, 0x1A04, 0x11D3, 0x9A, 0x73, 0x00, 0x00, 0xF8, 0x1E, 0xF3, 0x2E };
+        return clsid;
+    }
+    static CLSID const & tiff_codec()
+    {
+        static CLSID const clsid = { 0x557CF405, 0x1A04, 0x11D3, 0x9A, 0x73, 0x00, 0x00, 0xF8, 0x1E, 0xF3, 0x2E };
+        return clsid;
+    }
+    static CLSID const & gif_codec()
+    {
+        static CLSID const clsid = { 0x557CF402, 0x1A04, 0x11D3, 0x9A, 0x73, 0x00, 0x00, 0xF8, 0x1E, 0xF3, 0x2E };
+        return clsid;
+    }
+    static CLSID const & bmp_codec()
+    {
+        static CLSID const clsid = { 0x557CF400, 0x1A04, 0x11D3, 0x9A, 0x73, 0x00, 0x00, 0xF8, 0x1E, 0xF3, 0x2E };
+        return clsid;
+    }
+
+private:
+    lib_object_t lib_instance_;
+};
+
+
+class gp_view_base;
+
+//------------------------------------------------------------------------------
+} // namespace detail
+
 class gp_image;
 
 template <>
@@ -190,53 +282,78 @@
 {
     typedef Gdiplus::PixelFormat format_t;
 
-    typedef gp_supported_pixel_formats supported_pixel_formats_t;
+    typedef detail::gp_supported_pixel_formats supported_pixel_formats_t;
 
-    typedef gp_roi roi_t;
+    typedef detail::gp_roi roi_t;
 
-    typedef view_gp_format view_to_native_format;
+    typedef detail::view_gp_format view_to_native_format;
 
     template <class View>
-    struct is_supported : detail::is_supported<view_gp_format::apply<View>::value> {};
+    struct is_supported : detail::is_supported<view_to_native_format::apply<View>::value> {};
 
-    struct view_data_t : public Gdiplus::BitmapData
+    typedef mpl::map5
+        <
+            mpl::pair<char                    const *,                                                    gp_image  >,
+            mpl::pair<wchar_t                 const *,                                                    gp_image  >,
+            mpl::pair<IStream                       &,                                                    gp_image  >,
+            mpl::pair<FILE                          &, detail::input_FILE_for_IStream_extender           <gp_image> >,
+            mpl::pair<writable_memory_chunk_t const &, detail::writable_memory_chunk_for_IStream_extender<gp_image> >
+        > readers;
+
+    typedef mpl::map5
+        <
+            mpl::pair<char           const *, detail::gp_writer>,
+            mpl::pair<wchar_t        const *, detail::gp_writer>,
+            mpl::pair<IStream              &, detail::gp_writer>,
+            mpl::pair<FILE                 &, detail::gp_writer>,
+            mpl::pair<memory_chunk_t const &, detail::gp_writer>
+        > writers;
+
+    class view_data_t : public Gdiplus::BitmapData
     {
+    public:
         template <typename View>
         view_data_t( View const & view ) : p_roi_( 0 ) { set_bitmapdata_for_view( view ); }
 
         template <typename View>
-        view_data_t( View const & view, gp_roi::offset_t const & offset )
+        view_data_t( View const & view, roi_t::offset_t const & offset )
             :
-            p_roi_( static_cast<gp_roi const *>( optional_roi_.address() ) )
+            p_roi_( static_cast<roi_t const *>( optional_roi_.address() ) )
         {
             set_bitmapdata_for_view( view );
-            new ( optional_roi_.address() ) gp_roi( offset, Width, Height );
+            new ( optional_roi_.address() ) roi_t( offset, Width, Height );
         }
 
         void set_format( format_t const format ) { PixelFormat = format; }
 
+    public:
         Gdiplus::Rect const * const p_roi_;
 
     private:
         template <typename View>
         void set_bitmapdata_for_view( View const & view )
         {
+            BOOST_STATIC_ASSERT( is_supported<View>::value );
+
             Width       = view.width();
             Height      = view.height();
             Stride      = view.pixels().row_size();
-            PixelFormat = view_gp_format::apply<View>::value;
-            Scan0       = formatted_image_base::get_raw_data( view );
+            PixelFormat = view_to_native_format::apply<View>::value;
+            Scan0       = detail::formatted_image_base::get_raw_data( view );
             Reserved    = 0;
         }
 
         void operator=( view_data_t const & );
 
     private:
-        aligned_storage<sizeof( gp_roi ), alignment_of<gp_roi>::value>::type optional_roi_;
+        aligned_storage<sizeof( roi_t ), alignment_of<roi_t>::value>::type optional_roi_;
     };
 
+    typedef view_data_t writer_view_data_t;
+
     BOOST_STATIC_CONSTANT( unsigned int, desired_alignment  = sizeof( Gdiplus::ARGB ) );
     BOOST_STATIC_CONSTANT( bool        , builtin_conversion = true                    );
+    BOOST_STATIC_CONSTANT( bool        , writers_need_source_first = true             );
 };
 
 
@@ -247,19 +364,22 @@
 
 class gp_image
     :
-    private gp_guard,
+    private detail::gp_guard,
     public  detail::formatted_image<gp_image>
 {
+public:
+    typedef detail::gp_user_guard guard;
+
 public: /// \ingroup Construction
     explicit gp_image( wchar_t const * const filename )
     {
-        ensure_result( Gdiplus::DllExports::GdipCreateBitmapFromFileICM( filename, &pBitmap_ ) );
+        detail::ensure_result( Gdiplus::DllExports::GdipCreateBitmapFromFileICM( filename, &pBitmap_ ) );
         BOOST_ASSERT( pBitmap_ );
     }
 
     explicit gp_image( char const * const filename )
     {
-        ensure_result( Gdiplus::DllExports::GdipCreateBitmapFromFileICM( wide_path( filename ), &pBitmap_ ) );
+        detail::ensure_result( Gdiplus::DllExports::GdipCreateBitmapFromFileICM( detail::wide_path( filename ), &pBitmap_ ) );
         BOOST_ASSERT( pBitmap_ );
     }
 
@@ -267,37 +387,13 @@
     // lazy evaluation).
     explicit gp_image( IStream & stream )
     {
-        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_image( View & view )
-    {
-        // http://msdn.microsoft.com/en-us/library/ms536315(VS.85).aspx
-        // stride has to be a multiple of 4 bytes
-        BOOST_ASSERT( !( view.pixels().row_size() % sizeof( Gdiplus::ARGB ) ) );
-
-        ensure_result
-        (
-            Gdiplus::DllExports::GdipCreateBitmapFromScan0
-            (
-                view.width(),
-                view.height(),
-                view.pixels().row_size(),
-                view_gp_format::apply<View>::value,
-                get_raw_data( view ),
-                &pBitmap_
-            )
-        );
+        detail::ensure_result( Gdiplus::DllExports::GdipCreateBitmapFromStreamICM( &stream, &pBitmap_ ) );
         BOOST_ASSERT( pBitmap_ );
     }
 
     ~gp_image()
     {
-        verify_result( Gdiplus::DllExports::GdipDisposeImage( pBitmap_ ) );
+        detail::verify_result( Gdiplus::DllExports::GdipDisposeImage( pBitmap_ ) );
     }
 
 public:
@@ -305,7 +401,7 @@
     {
         using namespace Gdiplus;
         REAL width, height;
-        verify_result( DllExports::GdipGetImageDimension( const_cast<GpBitmap *>( pBitmap_ ), &width, &height ) );
+        detail::verify_result( DllExports::GdipGetImageDimension( const_cast<GpBitmap *>( pBitmap_ ), &width, &height ) );
         return point2<std::ptrdiff_t>( static_cast<std::ptrdiff_t>( width ), static_cast<std::ptrdiff_t>( height ) );
     }
 
@@ -314,9 +410,6 @@
         return Gdiplus::GetPixelFormatSize( format );
     }
 
-    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() ); }
-
     ::Gdiplus::GpBitmap       & lib_object()       { return *pBitmap_; }
     ::Gdiplus::GpBitmap const & lib_object() const { return const_cast<gp_image &>( *this ).lib_object(); }
 
@@ -326,7 +419,7 @@
     format_t format() const
     {
         format_t pixel_format;
-        verify_result( Gdiplus::DllExports::GdipGetImagePixelFormat( pBitmap_, &pixel_format ) );
+        detail::verify_result( Gdiplus::DllExports::GdipGetImagePixelFormat( pBitmap_, &pixel_format ) );
         return pixel_format;
     }
 
@@ -432,10 +525,11 @@
         verify_result( DllExports::GdipBitmapUnlockBits( pBitmap_, &bitmapData ) );
     }
 
-    void raw_convert_to_prepared_view( formatted_image_traits<gp_image>::view_data_t const & view_data ) const
+    void raw_convert_to_prepared_view( view_data_t const & view_data ) const
     {
         BOOST_ASSERT( view_data.Scan0 );
 
+        using namespace detail ;
         using namespace Gdiplus;
 
         BitmapData * const pMutableBitmapData( const_cast<BitmapData *>( static_cast<BitmapData const *>( &view_data ) ) );
@@ -456,7 +550,7 @@
     }
 
 
-    void copy_to_target( formatted_image_traits<gp_image>::view_data_t const & view_data ) const
+    void raw_copy_to_prepared_view( view_data_t const & view_data ) const
     {
         BOOST_ASSERT( view_data.Width       == static_cast<UINT>( dimensions().x ) );
         BOOST_ASSERT( view_data.Height      == static_cast<UINT>( dimensions().y ) );
@@ -468,33 +562,6 @@
     }
 
 private:
-    static CLSID const & png_codec()
-    {
-        static CLSID const clsid = { 0x557cf406, 0x1a04, 0x11d3, 0x9A, 0x73, 0x00, 0x00, 0xF8, 0x1E, 0xF3, 0x2E };
-        return clsid;
-    }
-    static CLSID const & jpg_codec()
-    {
-        static CLSID const clsid = { 0x557CF401, 0x1A04, 0x11D3, 0x9A, 0x73, 0x00, 0x00, 0xF8, 0x1E, 0xF3, 0x2E };
-        return clsid;
-    }
-    static CLSID const & tiff_codec()
-    {
-        static CLSID const clsid = { 0x557CF405, 0x1A04, 0x11D3, 0x9A, 0x73, 0x00, 0x00, 0xF8, 0x1E, 0xF3, 0x2E };
-        return clsid;
-    }
-    static CLSID const & gif_codec()
-    {
-        static CLSID const clsid = { 0x557CF402, 0x1A04, 0x11D3, 0x9A, 0x73, 0x00, 0x00, 0xF8, 0x1E, 0xF3, 0x2E };
-        return clsid;
-    }
-    static CLSID const & bmp_codec()
-    {
-        static CLSID const clsid = { 0x557CF400, 0x1A04, 0x11D3, 0x9A, 0x73, 0x00, 0x00, 0xF8, 0x1E, 0xF3, 0x2E };
-        return clsid;
-    }
-
-
     template <Gdiplus::PixelFormat desired_format>
     void pre_palettized_conversion( mpl::true_ /*is_indexed*/ )
     {
@@ -549,14 +616,8 @@
     template <Gdiplus::PixelFormat desired_format>
     void pre_palettized_conversion( mpl::false_ /*not is_indexed*/ ) const {}
 
-    void save_to( char    const * const pFilename, CLSID const & encoderID ) const { save_to( wide_path( pFilename ), encoderID ); }
-    void save_to( wchar_t const * const pFilename, CLSID const & encoderID ) const
-    {
-        ensure_result( Gdiplus::DllExports::GdipSaveImageToFile( pBitmap_, pFilename, &encoderID, NULL ) );
-    }
-
 private:
-    friend class gp_view_base;
+    friend class detail::gp_view_base;
 
     Gdiplus::GpBitmap * /*const*/ pBitmap_;
 };
@@ -565,7 +626,9 @@
 #   pragma warning( pop )
 #endif
 
-
+namespace detail
+{
+//------------------------------------------------------------------------------
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
@@ -588,7 +651,7 @@
     {
         std::memset( &bitmapData_, 0, sizeof( bitmapData_ ) );
 
-        ensure_result
+        detail::ensure_result
         (
             Gdiplus::DllExports::GdipBitmapLockBits
             (
@@ -659,41 +722,6 @@
 //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_image sealed
-    :
-    private MemoryReadStream,
-    public  gp_image
-{
-public:
-    gp_memory_image( memory_chunk_t const & in_memory_image )
-        :
-        MemoryReadStream( in_memory_image                 ),
-        gp_image        ( static_cast<IStream &>( *this ) )
-    {
-    }
-};
-
-class __declspec( novtable ) gp_FILE_image sealed
-    :
-    private FileReadStream,
-    public  gp_image
-{
-public:
-    explicit gp_FILE_image( FILE * const pFile )
-        :
-        FileReadStream( *pFile                          ),
-        gp_image      ( static_cast<IStream &>( *this ) )
-    {
-    }
-};
-
-#pragma warning( pop )
-
-
 //------------------------------------------------------------------------------
 } // namespace detail
 //------------------------------------------------------------------------------
Modified: sandbox/gil/boost/gil/extension/io2/libjpeg_image.hpp
==============================================================================
--- sandbox/gil/boost/gil/extension/io2/libjpeg_image.hpp	(original)
+++ sandbox/gil/boost/gil/extension/io2/libjpeg_image.hpp	2010-09-18 17:27:50 EDT (Sat, 18 Sep 2010)
@@ -178,7 +178,7 @@
         fatal_error_handler( p_cinfo );
     }
 
-    static void __cdecl output_message( j_common_ptr /*p_cinfo*/ ) {}
+    static void __cdecl output_message( j_common_ptr /*p_cinfo*/                    ) {}
     static void __cdecl emit_message  ( j_common_ptr /*p_cinfo*/, int /*msg_level*/ ) {}
     static void __cdecl format_message( j_common_ptr /*p_cinfo*/, char * /*buffer*/ ) {}
 
@@ -198,8 +198,6 @@
 };
 
 
-class libjpeg_image;
-
 struct decompression_setup_data_t
 {
     decompression_setup_data_t( J_COLOR_SPACE const format, JSAMPROW const buffer, libjpeg_roi::offset_t const offset )
@@ -225,7 +223,9 @@
         width_ ( view.width ()            ),
         stride_( view.pixels().row_size() ),
         number_of_channels_( num_channels<View>::value )
-    {}
+    {
+        BOOST_STATIC_ASSERT( view_libjpeg_format::apply<View>::value != JCS_UNKNOWN );
+    }
 
     void set_format( J_COLOR_SPACE const format ) { format_ = format; }
 
@@ -236,7 +236,7 @@
 };
 
 
-class libjpeg_writer : public libjpeg_base
+class libjpeg_writer : private libjpeg_base, public configure_on_write_writer
 {
 public:
     explicit libjpeg_writer( char const * const p_target_file_name )
@@ -246,6 +246,13 @@
         setup_destination( p_target_file_name );
     }
 
+    explicit libjpeg_writer( FILE & file )
+        :
+        libjpeg_base( for_compressor() )
+    {
+        setup_destination( file );
+    }
+
     ~libjpeg_writer()
     {
         jpeg_finish_compress( &compressor() );
@@ -254,41 +261,55 @@
     jpeg_compress_struct       & lib_object()       { return compressor(); }
     jpeg_compress_struct const & lib_object() const { return const_cast<libjpeg_writer &>( *this ).lib_object(); }
 
-    static void write( view_data_t const & view, char const * const p_target_file_name )
+    void write_default( view_data_t const & view ) throw(...)
     {
-        BOOST_ASSERT( view.format_ != JCS_UNKNOWN );
+        setup_compression( view );
+
+        #ifndef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+            if ( setjmp( error_handler_target() ) )
+                throw_jpeg_error();
+        #endif // BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+        jpeg_set_defaults( &compressor() );
+        //jpeg_set_quality( &compressor(), 100, false );
+
+        do_write( view );
+    }
+
+    void write( view_data_t const & view )
+    {
+        setup_compression( view );
+        do_write         ( view );
+    }
 
-        libjpeg_writer writer( p_target_file_name );
+private:
+    void setup_compression( view_data_t const & view )
+    {
+        compressor().image_width      = static_cast<JDIMENSION>( view.width_  );
+        compressor().image_height     = static_cast<JDIMENSION>( view.height_ );
+        compressor().input_components = view.number_of_channels_;
+        compressor().in_color_space   = view.format_;
+    }
+
+    void do_write( view_data_t const & view ) throw(...)
+    {
+        BOOST_ASSERT( view.format_ != JCS_UNKNOWN );
 
         #ifndef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
             if ( setjmp( error_handler_target() ) )
                 throw_jpeg_error();
         #endif // BOOST_GIL_THROW_THROUGH_C_SUPPORTED
         
-        writer.compressor().image_width  = static_cast<JDIMENSION>( view.width_  );
-        writer.compressor().image_height = static_cast<JDIMENSION>( view.height_ );
-        writer.compressor().input_components = view.number_of_channels_;
-        writer.compressor().in_color_space   = view.format_;
-
-        writer.setup_compression();
+        jpeg_start_compress( &compressor(), false );
 
         JSAMPLE *       p_row( view.buffer_ );
         JSAMPLE * const p_end( memunit_advanced( view.buffer_, view.height_ * view.stride_ ) );
         while ( p_row < p_end )
         {
-            writer.write_row( p_row );
+            write_row( p_row );
             memunit_advance( p_row, view.stride_ );
         }
     }
 
-private:
-    void setup_compression() BOOST_GIL_CAN_THROW
-    {
-        jpeg_set_defaults  ( &compressor()             );
-        //jpeg_set_quality   ( &compressor(), 100, false );
-        jpeg_start_compress( &compressor(),      false );
-    }
-
     void write_row( JSAMPLE * p_row ) BOOST_GIL_CAN_THROW
     {
         BOOST_VERIFY( jpeg_write_scanlines( &compressor(), &p_row, 1 ) == 1 );
@@ -381,28 +402,47 @@
     jpeg_destination_mgr       destination_manager_;
     array<unsigned char, 4096> write_buffer_       ;
 };
+//------------------------------------------------------------------------------
+} // namespace detail
 
 
+class libjpeg_image;
+
 template <>
 struct formatted_image_traits<libjpeg_image>
 {
-    typedef J_COLOR_SPACE                   format_t;
-    typedef libjpeg_supported_pixel_formats supported_pixel_formats_t;
-    typedef libjpeg_roi                     roi_t;
-    typedef view_libjpeg_format             view_to_native_format;
-    typedef view_data_t                     view_data_t;
+    typedef       ::J_COLOR_SPACE                   format_t;
+    typedef detail::libjpeg_supported_pixel_formats supported_pixel_formats_t;
+    typedef detail::libjpeg_roi                     roi_t;
+    typedef detail::view_libjpeg_format             view_to_native_format;
+    typedef detail::view_data_t                     view_data_t;
 
     template <class View>
-    struct is_supported : mpl::bool_<view_libjpeg_format::apply<View>::value != JCS_UNKNOWN> {};
+    struct is_supported : mpl::bool_<view_to_native_format::apply<View>::value != JCS_UNKNOWN> {};
+
+    typedef mpl::map2
+            <
+                mpl::pair<FILE       &, libjpeg_image>,
+                mpl::pair<char const *, libjpeg_image>
+            > readers;
+
+    typedef mpl::map2
+            <
+                mpl::pair<FILE       &, detail::libjpeg_writer>,
+                mpl::pair<char const *, detail::libjpeg_writer>
+            > writers;
+
+    typedef view_data_t writer_view_data_t;
 
     BOOST_STATIC_CONSTANT( unsigned int, desired_alignment  = sizeof( void * ) );
     BOOST_STATIC_CONSTANT( bool        , builtin_conversion = true             );
+    BOOST_STATIC_CONSTANT( bool        , writers_need_source_first = false     );
 };
 
 
 class libjpeg_image
     :
-    public  libjpeg_base,
+    public  detail::libjpeg_base,
     public  detail::formatted_image<libjpeg_image>
 {
 public:
@@ -527,7 +567,7 @@
 
 private: // Private formatted_image_base interface.
     friend base_t;
-    void raw_convert_to_prepared_view( view_data_t const & view_data ) const throw(...)
+    void raw_convert_to_prepared_view( detail::view_data_t const & view_data ) const throw(...)
     {
         setup_decompression( view_data );
 
@@ -612,7 +652,7 @@
         }
     }
 
-    void raw_copy_to_prepared_view( view_data_t const & view_data ) const
+    void raw_copy_to_prepared_view( detail::view_data_t const & view_data ) const
     {
         BOOST_ASSERT( view_data.width_  == static_cast<unsigned int>( dimensions().x ) );
         BOOST_ASSERT( view_data.height_ == static_cast<unsigned int>( dimensions().y ) );
@@ -621,7 +661,7 @@
     }
 
 private:
-    void setup_decompression( decompression_setup_data_t const & view_data ) const throw(...)
+    void setup_decompression( detail::decompression_setup_data_t const & view_data ) const throw(...)
     {
         unsigned int const state       ( decompressor().global_state );
         unsigned int       rows_to_skip( view_data.offset_           );
@@ -741,7 +781,7 @@
     {
         BOOST_VERIFY( jpeg_read_header( &decompressor(), true ) == JPEG_HEADER_OK );
 
-        io_error_if( decompressor().data_precision != 8, "Unsupported image file data precision." );
+        detail::io_error_if( decompressor().data_precision != 8, "Unsupported image file data precision." );
     }
 
     // Unextracted "libjpeg_reader" interface.
@@ -913,9 +953,6 @@
 //    {}
 //};
 
-
-//------------------------------------------------------------------------------
-} // namespace detail
 //------------------------------------------------------------------------------
 } // namespace gil
 //------------------------------------------------------------------------------
Modified: sandbox/gil/boost/gil/extension/io2/libpng_image.hpp
==============================================================================
--- sandbox/gil/boost/gil/extension/io2/libpng_image.hpp	(original)
+++ sandbox/gil/boost/gil/extension/io2/libpng_image.hpp	2010-09-18 17:27:50 EDT (Sat, 18 Sep 2010)
@@ -35,10 +35,6 @@
 namespace gil
 {
 //------------------------------------------------------------------------------
-
-class libpng_image;
-class libpng_image_from_char;
-
 namespace detail
 {
 //------------------------------------------------------------------------------
@@ -54,7 +50,6 @@
 template <> struct gil_to_libpng_format<gray16_pixel_t, false> : mpl::integral_c<int, PNG_COLOR_TYPE_GRAY      | ( 16 << 16 )> {};
 
 
-
 struct view_libpng_format
 {
     template <class View>
@@ -62,6 +57,10 @@
 };
 
 
+template <class View>
+struct is_view_supported : mpl::bool_<view_libpng_format::apply<View>::value != -1> {};
+
+
 typedef mpl::vector6
 <
     image<rgb8_pixel_t  , false>,
@@ -78,6 +77,8 @@
 
 struct libpng_view_data_t
 {
+    typedef unsigned int format_t;
+
     template <class View>
     /*explicit*/ libpng_view_data_t( View const & view, libpng_roi::offset_t const offset = 0 )
         :
@@ -88,14 +89,16 @@
         width_ ( view.width ()            ),
         stride_( view.pixels().row_size() ),
         number_of_channels_( num_channels<View>::value )
-    {}
+    {
+        BOOST_STATIC_ASSERT( is_view_supported<View>::value );
+    }
 
     void set_format( unsigned int const format ) { format_ = format; }
 
-    unsigned int          /*const*/ format_;
-    unsigned int          /*const*/ colour_type_;
-    unsigned int bits_per_pixel_;
-    png_byte *              /*const*/ buffer_;
+    format_t             /*const*/ format_;
+    unsigned int         /*const*/ colour_type_;
+    unsigned int         /*const*/ bits_per_pixel_;
+    png_byte *           /*const*/ buffer_;
     libpng_roi::offset_t /*const*/ offset_;
 
     unsigned int /*const*/ height_;
@@ -105,38 +108,26 @@
 };
 
 
-template <>
-struct formatted_image_traits<libpng_image>
+inline void throw_libpng_error()
 {
-    typedef int                            format_t;
-    typedef libpng_supported_pixel_formats supported_pixel_formats_t;
-    typedef libpng_roi                     roi_t;
-    typedef view_libpng_format             view_to_native_format;
-    typedef libpng_view_data_t             view_data_t;
-
-    template <class View>
-    struct is_supported : mpl::bool_<view_libpng_format::apply<View>::value != -1> {};
-
-    typedef mpl::map2
-            <
-                mpl::pair<FILE       &, libpng_image          >,
-                mpl::pair<char const *, libpng_image_from_char>
-            > readers;
-
-    BOOST_STATIC_CONSTANT( unsigned int, desired_alignment  = sizeof( void * ) );
-    BOOST_STATIC_CONSTANT( bool        , builtin_conversion = true             );
-};
-
+    io_error( "LibPNG failure" );
+}
 
 
-inline void throw_libpng_error()
+inline void PNGAPI png_warning_function( png_structp /*png_ptr*/, png_const_charp const message )
 {
-    boost::gil::detail::io_error( "LibPNG failure" );
+    #ifdef _DEBUG
+        std::puts( message );
+    #else
+        ignore_unused_variable_warning( message );
+    #endif // _DEBUG
 }
 
 
-inline void PNGAPI png_error_function( png_structp const png_ptr, png_const_charp const /*error_message*/ )
+inline void PNGAPI png_error_function( png_structp const png_ptr, png_const_charp const error_message )
 {
+    png_warning_function( png_ptr, error_message );
+
     #ifdef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
         throw_libpng_error();
         boost::ignore_unused_variable_warning( png_ptr );
@@ -146,10 +137,6 @@
 }
 
 
-inline void PNGAPI png_warning_function( png_structp, png_const_charp )
-{
-}
-
 //...zzz...this will blow-up at link-time when included in multiple .cpps unless it gets moved into a separate module...
 #ifdef PNG_NO_ERROR_TEXT
     extern "C" void PNGAPI png_error( png_structp const png_ptr, png_const_charp const error_message )
@@ -174,13 +161,266 @@
         png_warning_function( png_ptr, error_message );
     }
 #endif // PNG_NO_WARNINGS
+
+
+class lib_object_t : noncopyable
+{
+public:
+    png_struct & png_object() const
+    {
+        BOOST_ASSERT( p_png_ && "Call this only after ensuring creation success!" );
+        png_struct & png( *p_png_ );
+        __assume( &png != 0 );
+        return png;
+    }
+
+    png_info & info_object() const
+    {
+        BOOST_ASSERT( p_png_ && "Call this only after ensuring creation success!" );
+        png_info & info( *p_info_ );
+        __assume( &info != 0 );
+        return info;
+    }
+
+protected:
+    lib_object_t( png_struct * const p_png, png_info  * const p_info )
+        :
+        p_png_ ( p_png  ),
+        p_info_( p_info )
+    {}
+
+    ~lib_object_t()
+    {
+        BOOST_ASSERT( !p_png_ && !p_info_ && "The concrete class must do the cleanup!" );
+    }
+
+    //...zzz...forced by LibPNG into either duplication or this anti-pattern...
+    bool is_valid() const { return p_png_ && p_info_; }
+
+    png_struct * & png_object_for_destruction () { return p_png_ ; }
+    png_info   * & info_object_for_destruction() { return p_info_; }
+
+private:
+    png_struct * __restrict p_png_ ;
+    png_info   * __restrict p_info_;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class libpng_base
+///
+/// \brief
+///
+////////////////////////////////////////////////////////////////////////////////
+
+class libpng_base : public lib_object_t
+{
+public:
+    typedef lib_object_t lib_object_t;
+
+    lib_object_t & lib_object() { return *this; }
+
+protected:
+    libpng_base( png_struct * const p_png )
+        :
+        lib_object_t( p_png, ::png_create_info_struct( p_png ) )
+    {}
+
+    bool successful_creation() const { return is_valid(); }
+
+    static std::size_t format_bit_depth( libpng_view_data_t::format_t const format )
+    {
+        return ( format >> 16 ) & 0xFF;
+    }
+
+    static std::size_t format_colour_type( libpng_view_data_t::format_t const format )
+    {
+        return format & 0xFF;
+    }
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class libpng_writer
+///
+/// \brief
+///
+////////////////////////////////////////////////////////////////////////////////
+
+class libpng_writer : public libpng_base, public configure_on_write_writer
+{
+public:
+    void write_default( libpng_view_data_t const & view )
+    {
+        ::png_set_IHDR
+        (
+            &png_object ()                    ,
+            &info_object()                    ,
+            view.width_                       ,
+            view.height_                      ,
+            format_bit_depth  ( view.format_ ),
+            format_colour_type( view.format_ ),
+            PNG_INTERLACE_NONE                ,
+            PNG_COMPRESSION_TYPE_DEFAULT      ,
+            PNG_INTRAPIXEL_DIFFERENCING
+        );
+
+        //::png_set_invert_alpha( &png_object() );
+
+        write( view );
+    }
+
+    void write( libpng_view_data_t const & view ) throw(...)
+    {
+        BOOST_ASSERT( view.format_ != JCS_UNKNOWN );
+
+        #ifndef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+            if ( setjmp( error_handler_target() ) )
+                throw_jpeg_error();
+        #endif // BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+
+        if ( little_endian() )
+            ::png_set_swap( &png_object() );
+
+        ::png_write_info( &png_object(), &info_object() );
+        
+        png_byte *       p_row( view.buffer_ );
+        png_byte * const p_end( memunit_advanced( view.buffer_, view.height_ * view.stride_ ) );
+        while ( p_row < p_end )
+        {
+            ::png_write_row( &png_object(), p_row );
+            memunit_advance( p_row, view.stride_ );
+        }
+
+        ::png_write_end( &png_object(), 0 );
+    }
+
+protected:
+    libpng_writer( void * const p_target_object, png_rw_ptr const write_data_fn, png_flush_ptr const output_flush_fn )
+        :
+        libpng_base( ::png_create_write_struct_2( PNG_LIBPNG_VER_STRING, NULL, &detail::png_error_function, &detail::png_warning_function, NULL, NULL, NULL ) )
+    {
+        if ( !successful_creation() )
+            cleanup_and_throw_libpng_error();
+
+        setup_destination( p_target_object, write_data_fn, output_flush_fn );
+    }
+
+    ~libpng_writer()
+    {
+        destroy_write_struct();
+    }
+
+private:
+    void destroy_write_struct() { ::png_destroy_write_struct( &png_object_for_destruction(), &info_object_for_destruction() ); }
+
+    void cleanup_and_throw_libpng_error()
+    {
+        destroy_write_struct();
+        detail::throw_libpng_error();
+    }
+
+    void setup_destination( void * const p_target_object, png_rw_ptr const write_data_fn, png_flush_ptr const output_flush_fn )
+    {
+        ::png_set_write_fn( &png_object(), p_target_object, write_data_fn, output_flush_fn );
+    }
+
+private:
+    jpeg_destination_mgr       destination_manager_;
+    array<unsigned char, 4096> write_buffer_       ;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class libpng_writer_FILE
+///
+/// \brief
+///
+////////////////////////////////////////////////////////////////////////////////
+
+class libpng_writer_FILE : public libpng_writer
+{
+public:
+    libpng_writer_FILE( FILE & file )
+        :
+        libpng_writer( &file, &png_write_data, &png_flush_data )
+    {}
+
+private:
+    static void PNGAPI png_write_data( png_structp const png_ptr, png_bytep const data, png_size_t const length )
+    {
+        BOOST_ASSERT( png_ptr );
+
+        png_size_t const written_size
+        (
+            static_cast<png_size_t>( std::fwrite( data, 1, length, static_cast<FILE *>( png_ptr->io_ptr ) ) )
+        );
+
+        if ( written_size != length )
+            png_error_function( png_ptr, "Write Error" );
+    }
+
+    static void PNGAPI png_flush_data( png_structp const png_ptr )
+    {
+        BOOST_ASSERT( png_ptr );
+
+        std::fflush( static_cast<FILE *>( png_ptr->io_ptr ) );
+    }
+};
+
 //------------------------------------------------------------------------------
 } // namespace detail
 
 
+class libpng_image;
+
+template <>
+struct formatted_image_traits<libpng_image>
+{
+    typedef         int                            format_t;
+    typedef detail::libpng_supported_pixel_formats supported_pixel_formats_t;
+    typedef detail::libpng_roi                     roi_t;
+    typedef detail::view_libpng_format             view_to_native_format;
+    typedef detail::libpng_view_data_t             view_data_t;
+
+    template <class View>
+    struct is_supported : detail::is_view_supported<View> {};
+
+    typedef mpl::map2
+            <
+                mpl::pair<FILE       &,                                   libpng_image  >,
+                mpl::pair<char const *, detail::input_c_str_for_c_file_extender<libpng_image> >
+            > readers;
+
+    typedef mpl::map2
+            <
+                mpl::pair<FILE       &,                                   detail::libpng_writer_FILE  >,
+                mpl::pair<char const *, detail::output_c_str_for_c_file_extender<detail::libpng_writer_FILE> >
+            > writers;
+
+    typedef view_data_t writer_view_data_t;
+
+    BOOST_STATIC_CONSTANT( unsigned int, desired_alignment  = sizeof( void * ) );
+    BOOST_STATIC_CONSTANT( bool        , builtin_conversion = true             );
+    BOOST_STATIC_CONSTANT( bool        , writers_need_source_first = false     );
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class libpng_image
+///
+/// \brief
+///
+////////////////////////////////////////////////////////////////////////////////
+
 class libpng_image
     :
-    public detail::formatted_image<libpng_image>
+    public  detail::formatted_image<libpng_image>,
+    private detail::libpng_base
 {
 public:
     struct guard {};
@@ -227,7 +467,7 @@
 
     std::size_t format_size( format_t const format ) const
     {
-        return number_of_channels() * ( ( format >> 16 ) & 0xFF ) / 8;
+        return number_of_channels() * format_bit_depth( format ) / 8;
     }
 
     std::size_t format_size() const
@@ -235,44 +475,12 @@
         return number_of_channels() * bit_depth() / 8;
     }
 
-private:
-    static void PNGAPI png_read_data( png_structp const png_ptr, png_bytep const data, png_size_t const length )
-    {
-        BOOST_ASSERT( png_ptr );
-
-        png_size_t const read_size
-        (
-            static_cast<png_size_t>( std::fread( data, 1, length, static_cast<FILE *>( png_ptr->io_ptr ) ) )
-        );
-
-        if ( read_size != length )
-            detail::png_error_function( png_ptr, "Read Error" );
-    }
-
-    static void PNGAPI png_write_data( png_structp const png_ptr, png_bytep const data, png_size_t const length )
-    {
-        BOOST_ASSERT( png_ptr );
-
-        png_size_t const written_size
-        (
-            static_cast<png_size_t>( std::fwrite( data, 1, length, static_cast<FILE *>( png_ptr->io_ptr ) ) )
-        );
-
-        if ( written_size != length )
-            detail::png_error_function( png_ptr, "Write Error" );
-    }
-
-    //static void png_flush_data( png_structp const png_ptr);
-
 public: /// \ingroup Construction
     explicit libpng_image( FILE & file )
         :
-        p_png_ ( ::png_create_read_struct_2( PNG_LIBPNG_VER_STRING, NULL, &detail::png_error_function, &detail::png_warning_function, NULL, NULL, NULL ) ),
-        p_info_( ::png_create_info_struct  ( p_png_                                                                                                    ) )
+        libpng_base( ::png_create_read_struct_2( PNG_LIBPNG_VER_STRING, NULL, &detail::png_error_function, &detail::png_warning_function, NULL, NULL, NULL ) )
     {
-        /// \todo Replace this manual logic with proper RAII guards.
-        ///                                   (03.09.2010.) (Domagoj Saric)
-        if ( !p_png_ || !p_info_ )
+        if ( !successful_creation() )
             cleanup_and_throw_libpng_error();
 
         #ifdef PNG_NO_STDIO
@@ -280,15 +488,12 @@
         #else
             ::png_init_io( &png_object(), &file );
         #endif
-        //..zzz...png_set_write_fn(png_structp write_ptr, voidp write_io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn);
 
         init();
     }
 
     ~libpng_image()
     {
-        __assume( p_png_  != 0 );
-        __assume( p_info_ != 0 );
         destroy_read_struct();
     }
 
@@ -346,7 +551,7 @@
         }
     }
 
-    void raw_convert_to_prepared_view( detail::libpng_view_data_t const & view_data ) const throw(...)
+    void raw_convert_to_prepared_view( detail::libpng_view_data_t const & view_data ) const
     {
         BOOST_ASSERT( view_data.width_  == static_cast<unsigned int>( dimensions().x ) );
         BOOST_ASSERT( view_data.height_ == static_cast<unsigned int>( dimensions().y ) );
@@ -412,7 +617,7 @@
 
         while ( number_of_passes-- )
         {
-            png_byte       *       p_row( view_data.buffer_ );
+            png_byte       *       p_row( view_data.buffer_                                 );
             png_byte const * const p_end( p_row + ( view_data.height_ * view_data.stride_ ) );
             while ( p_row < p_end )
             {
@@ -449,7 +654,7 @@
 
         #ifdef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
             }
-            catch(...)
+            catch (...)
             {
                 destroy_read_struct();
                 throw;
@@ -468,49 +673,28 @@
     unsigned int number_of_channels() const { return ::png_get_channels ( &png_object(), &info_object() ); }
     std::size_t  bit_depth         () const { return ::png_get_bit_depth( &png_object(), &info_object() ); }
 
-    void destroy_read_struct() { ::png_destroy_read_struct( &p_png_, &p_info_, NULL ); }
+    void destroy_read_struct() { ::png_destroy_read_struct( &png_object_for_destruction(), &info_object_for_destruction(), NULL ); }
 
-    void read_row( png_byte * const p_row ) const
-    #ifdef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
-        throw(...)
-    #endif // BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+    void read_row( png_byte * const p_row ) const BOOST_GIL_CAN_THROW
     {
         ::png_read_row( &png_object(), p_row, NULL );
     }
 
-    png_struct & png_object() const
+    static void PNGAPI png_read_data( png_structp const png_ptr, png_bytep const data, png_size_t const length )
     {
-        png_struct & png( *p_png_ );
-        __assume( &png != 0 );
-        return png;
-    }
+        BOOST_ASSERT( png_ptr );
 
-    png_info & info_object() const
-    {
-        png_info & info( *p_info_ );
-        __assume( &info != 0 );
-        return info;
-    }
+        png_size_t const read_size
+        (
+            static_cast<png_size_t>( std::fread( data, 1, length, static_cast<FILE *>( png_ptr->io_ptr ) ) )
+        );
 
-private:
-    png_struct * __restrict /*const*/ p_png_ ;
-    png_info   * __restrict /*const*/ p_info_;
+        if ( read_size != length )
+            detail::png_error_function( png_ptr, "Read Error" );
+    }
 };
 
 
-class libpng_image_from_char
-    :
-    private detail::c_file_guard,
-    public  libpng_image
-{
-public:
-    libpng_image_from_char( char const * const file_name )
-        :
-        detail::c_file_guard( file_name ),
-        libpng_image        ( get()     )
-    {}
-};
-
 //------------------------------------------------------------------------------
 } // namespace gil
 //------------------------------------------------------------------------------
Copied: sandbox/gil/boost/gil/extension/io2/libtiff_image.hpp (from r65436, /sandbox/gil/boost/gil/extension/io2/libtiff_private_base.hpp)
==============================================================================
--- /sandbox/gil/boost/gil/extension/io2/libtiff_private_base.hpp	(original)
+++ sandbox/gil/boost/gil/extension/io2/libtiff_image.hpp	2010-09-18 17:27:50 EDT (Sat, 18 Sep 2010)
@@ -1,7 +1,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 ///
-/// \file libtiff_private_base.hpp
-/// ------------------------------
+/// \file libtiff_image.hpp
+/// -----------------------
 ///
 /// Copyright (c) Domagoj Saric 2010.
 ///
@@ -14,8 +14,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 //------------------------------------------------------------------------------
 #pragma once
-#ifndef libtiff_private_base_hpp__0808D24E_CED1_4921_A832_3C12DAE93Ef7
-#define libtiff_private_base_hpp__0808D24E_CED1_4921_A832_3C12DAE93Ef7
+#ifndef libtiff_image_hpp__0808D24E_CED1_4921_A832_3C12DAE93Ef7
+#define libtiff_image_hpp__0808D24E_CED1_4921_A832_3C12DAE93Ef7
 //------------------------------------------------------------------------------
 #include "formatted_image.hpp"
 
@@ -67,7 +67,6 @@
     )
 
 
-
 union full_format_t
 {
     struct format_bitfield
@@ -204,9 +203,6 @@
 }
 
 
-struct libtiff_guard {};
-
-
 #if defined(BOOST_MSVC)
 #   pragma warning( push )
 #   pragma warning( disable : 4127 ) // "conditional expression is constant"
@@ -216,13 +212,13 @@
 struct tiff_view_data_t
 {
     template <class View>
-    tiff_view_data_t( View const & view, generic_vertical_roi::offset_t const offset )
+    explicit tiff_view_data_t( View const & view, generic_vertical_roi::offset_t const offset )
         :
         offset_    ( offset                                     ),
         dimensions_( view.dimensions()                          ),
         stride_    ( view.pixels().row_size()                   )
         #ifdef _DEBUG
-            ,format_( view_libtiff_format::apply<View>::value   )
+            ,format_id_( view_libtiff_format::apply<View>::value   )
         #endif
     {
         set_buffers( view, is_planar<View>() );
@@ -230,7 +226,7 @@
 
     void set_format( full_format_t::format_id const format )
     {
-        //BOOST_ASSERT( ( format_ == format ) && !"libtiff does not provide builtin conversion." );
+        BOOST_ASSERT( ( format_id_ == format ) && !"libtiff does not provide builtin conversion." );
         ignore_unused_variable_warning( format );
     }
 
@@ -241,7 +237,7 @@
     array<unsigned char *, 4>              plane_buffers_;
 
     #ifdef _DEBUG
-        unsigned int format_;
+        unsigned int format_id_;
     #endif
 
 private: // this should probably go to the base formatted_image class...
@@ -265,68 +261,208 @@
     void operator=( tiff_view_data_t const & );
 };
 
+struct tiff_writer_view_data_t : public tiff_view_data_t
+{
+    template <class View>
+    tiff_writer_view_data_t( View const & view )
+        :
+        tiff_view_data_t( view, 0 )
+    {
+        format_.number = view_libtiff_format::apply<View>::value;
+    }
+
+    full_format_t format_;
+};
+
+class libtiff_base
+{
+public:
+    TIFF & lib_object() const { BOOST_ASSERT( p_tiff_ ); return *p_tiff_; }
+
+protected:
+    libtiff_base( char const * const file_name, char const * const access_mode )
+        :
+        p_tiff_( ::TIFFOpen( file_name, access_mode ) )
+    {
+        BOOST_ASSERT( file_name );
+        construction_check();
+    }
+
+    explicit libtiff_base( FILE & file )
+        :
+        p_tiff_
+        (
+            ::TIFFClientOpen
+            (
+                "", "",
+                &file,
+                &detail::FILE_read_proc,
+                &detail::FILE_write_proc,
+                &detail::FILE_seek_proc,
+                &detail::FILE_close_proc_nop,
+                &detail::FILE_size_proc,
+                &detail::FILE_map_proc,
+                &detail::FILE_unmap_proc
+            )
+        )
+    {
+        construction_check();
+    }
+
+
+    ~libtiff_base()
+    {
+        ::TIFFClose( &lib_object() );
+    }
+
+protected:
+    class cumulative_result : public detail::cumulative_result
+    {
+    public:
+        void throw_if_error() const { detail::cumulative_result::throw_if_error( "Error reading TIFF file" ); }
+    };
+
+private:
+    void construction_check() const
+    {
+        io_error_if_not( p_tiff_, "Failed to open TIFF input file" );
+    }
+
+private:
+    TIFF * const p_tiff_;
+};
+
+class libtiff_writer : public libtiff_base, public configure_on_write_writer
+{
+public:
+    explicit libtiff_writer( char const * const file_name ) : detail::libtiff_base( file_name, "w" ) {}
+
+    explicit libtiff_writer( FILE & file ) : detail::libtiff_base( file ) {}
+
+    void write_default( tiff_writer_view_data_t const & view )
+    {
+        full_format_t::format_bitfield const format_bits( view.format_.bits );
+        //BOOST_ASSERT( ( format_bits.planar_configuration == PLANARCONFIG_CONTIG ) && "Add planar support..." );
+
+        set_field( TIFFTAG_IMAGEWIDTH , view.dimensions_.x );
+        set_field( TIFFTAG_IMAGELENGTH, view.dimensions_.y );
+        set_field( TIFFTAG_BITSPERSAMPLE, format_bits.bits_per_sample );
+        set_field( TIFFTAG_SAMPLESPERPIXEL, format_bits.samples_per_pixel );
+        set_field( TIFFTAG_PLANARCONFIG, format_bits.planar_configuration );
+        set_field( TIFFTAG_PHOTOMETRIC, format_bits.photometric );
+        set_field( TIFFTAG_INKSET, format_bits.ink_set );
+        set_field( TIFFTAG_SAMPLEFORMAT, format_bits.sample_format );
+
+        set_field( TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT );
+
+        if ( format_bits.samples_per_pixel == 4 && format_bits.photometric == PHOTOMETRIC_RGB )
+        {
+            uint16 const type( EXTRASAMPLE_UNASSALPHA );
+            set_field( TIFFTAG_EXTRASAMPLES, 1, &type );
+        }
+
+        write( view );
+    }
+
+    void write( tiff_writer_view_data_t const & view )
+    {
+        cumulative_result result;
+
+        for ( unsigned int plane( 0 ); plane < view.number_of_planes_; ++plane )
+        {
+            unsigned char * buf( view.plane_buffers_[ plane ] );
+
+            unsigned int       row       ( 0                  );
+            unsigned int const target_row( view.dimensions_.y );
+            while ( row < target_row )
+            {
+                result.accumulate_equal( ::TIFFWriteScanline( &lib_object(), buf, row++, static_cast<tsample_t>( plane ) ), 1 );
+                buf += view.stride_;
+            }
+        }
+
+        result.throw_if_error();
+    }
+
+private:
+    template <typename T>
+    void set_field( ttag_t const tag, T value )
+    {
+        BOOST_VERIFY( ::TIFFVSetField( &lib_object(), tag, gil_reinterpret_cast<va_list>( &value ) ) );
+    }
+
+    template <typename T1, typename T2>
+    void set_field( ttag_t const tag, T1 const value1, T2 const value2 )
+    {
+        BOOST_VERIFY( ::TIFFSetField( &lib_object(), tag, value1, value2 ) );
+    }
+};
+
+//------------------------------------------------------------------------------
+} // namespace detail
+
 class libtiff_image;
 
 template <>
 struct formatted_image_traits<libtiff_image>
 {
-    typedef full_format_t::format_id format_t;
+    typedef detail::full_format_t::format_id format_t;
 
-    typedef libtiff_supported_pixel_formats supported_pixel_formats_t;
+    typedef detail::libtiff_supported_pixel_formats supported_pixel_formats_t;
 
-    typedef generic_vertical_roi roi_t;
+    typedef detail::generic_vertical_roi roi_t;
 
-    typedef view_libtiff_format view_to_native_format;
+    typedef detail::view_libtiff_format view_to_native_format;
 
-    typedef tiff_view_data_t view_data_t;
+    typedef detail::tiff_view_data_t view_data_t;
 
     template <class View>
-    struct is_supported : mpl::true_ {};
+    struct is_supported : mpl::true_ {}; //...zzz...
 
-    BOOST_STATIC_CONSTANT( unsigned int, desired_alignment = 0 );
+    typedef mpl::map2
+    <
+        mpl::pair<char const *, libtiff_image>,
+        mpl::pair<FILE       &, libtiff_image>
+    > readers;
 
-    BOOST_STATIC_CONSTANT( bool, builtin_conversion = false );
+    typedef mpl::map2
+    <
+        mpl::pair<char const *, detail::libtiff_writer>,
+        mpl::pair<FILE       &, detail::libtiff_writer>
+    > writers;
+
+    typedef detail::tiff_writer_view_data_t writer_view_data_t;
+
+    BOOST_STATIC_CONSTANT( unsigned int, desired_alignment  = sizeof( void *) );
+    BOOST_STATIC_CONSTANT( bool        , builtin_conversion = false           );
+    BOOST_STATIC_CONSTANT( bool        , writers_need_source_first = false    );
 };
 
 
 class libtiff_image
     :
-    public  detail::formatted_image<libtiff_image>
+    public detail::libtiff_base,
+    public detail::formatted_image<libtiff_image>
 {
+private:
+    typedef detail::full_format_t full_format_t;
+
+public:
+    struct guard {};
+
 public: /// \ingroup Construction
     explicit libtiff_image( char const * const file_name )
         :
-        p_tiff_( ::TIFFOpen( file_name, "r" ) )
+        detail::libtiff_base( file_name, "r" )
     {
-        BOOST_ASSERT( file_name );
-        constructor_tail();
+        get_format();
     }
 
-    explicit libtiff_image( FILE * const p_file )
+    explicit libtiff_image( FILE & file )
         :
-        p_tiff_
-        (
-            ::TIFFClientOpen
-            (
-                "", "",
-                p_file,
-                &FILE_read_proc,
-                &FILE_write_proc,
-                &FILE_seek_proc,
-                &FILE_close_proc_nop,
-                &FILE_size_proc,
-                &FILE_map_proc,
-                &FILE_unmap_proc
-            )
-        )
-    {
-        BOOST_ASSERT( p_file );
-        constructor_tail();
-    }
-
-    ~libtiff_image()
+        detail::libtiff_base( file )
     {
-        ::TIFFClose( p_tiff_ );
+        get_format();
     }
 
 public:
@@ -344,18 +480,14 @@
         return bits.bits_per_sample * ( ( bits.planar_configuration == PLANARCONFIG_CONTIG ) ? bits.samples_per_pixel : 1 ) / 8;
     }
 
-    full_format_t::format_bitfield const & format_bits() const {return format_.bits; }
-
-
-    TIFF       & lib_object()       { return *p_tiff_; }
-    TIFF const & lib_object() const { return const_cast<libtiff_image &>( *this ).lib_object(); }
+    detail::full_format_t::format_bitfield const & format_bits() const { return format_.bits; }
 
 private:
     template <typename T>
     T get_field( ttag_t const tag ) const
     {
         T value; T * p_value( &value );
-        BOOST_VERIFY( ::TIFFVGetFieldDefaulted( p_tiff_, tag, gil_reinterpret_cast<va_list>( &p_value ) ) );
+        BOOST_VERIFY( ::TIFFVGetFieldDefaulted( &lib_object(), tag, gil_reinterpret_cast<va_list>( &p_value ) ) );
         return value;
     }
 
@@ -363,7 +495,7 @@
     std::pair<T1, T2> get_field( ttag_t const tag, int & cumulative_result ) const
     {
         std::pair<T1, T2> value;
-        cumulative_result &= ::TIFFGetFieldDefaulted( p_tiff_, tag, &value.first, &value.second );
+        cumulative_result &= ::TIFFGetFieldDefaulted( &lib_object(), tag, &value.first, &value.second );
         return value;
     }
 
@@ -405,24 +537,12 @@
             }
         }
 
-        detail::io_error_if( !cumulative_result || unsupported_format || ( orientation != ORIENTATION_TOPLEFT ), "TeeF" );
+        detail::io_error_if( !cumulative_result || unsupported_format || ( orientation != ORIENTATION_TOPLEFT ), "Unsupported TIFF format" );
 
         format_.number = LIBTIFF_FORMAT( samples_per_pixel, bits_per_sample, ( sample_format == SAMPLEFORMAT_VOID ) ? SAMPLEFORMAT_UINT : sample_format, planar_configuration, photometric, ink_set );
     }
 
-
 private:
-    void construction_check() const
-    {
-        detail::io_error_if_not( p_tiff_, "Failed to open TIFF input file" );
-    }
-
-    void constructor_tail()
-    {
-        construction_check();
-        get_format        ();
-    }
-
     static unsigned int round_up_divide( unsigned int const dividend, unsigned int const divisor )
     {
         return ( dividend + divisor - 1 ) / divisor;
@@ -450,9 +570,9 @@
             rows_to_skip               ( offset % tile_height ),
             number_of_tiles            ( round_up_divide( dimensions.y, tile_height ) * tiles_per_row * ( source.format_bits().planar_configuration == PLANARCONFIG_SEPARATE ? source.format_bits().samples_per_pixel : 1 ) )
         {
-            BOOST_ASSERT( static_cast<tsize_t>( tile_width_bytes ) == ::TIFFTileRowSize( source.p_tiff_ ) );
-            BOOST_ASSERT( static_cast<tsize_t>( tile_size_bytes  ) == ::TIFFTileSize   ( source.p_tiff_ ) );
-            BOOST_ASSERT( starting_tile + number_of_tiles <= ::TIFFNumberOfTiles( source.p_tiff_ ) );
+            BOOST_ASSERT( static_cast<tsize_t>( tile_width_bytes ) == ::TIFFTileRowSize( &source.lib_object() ) );
+            BOOST_ASSERT( static_cast<tsize_t>( tile_size_bytes  ) == ::TIFFTileSize   ( &source.lib_object() ) );
+            BOOST_ASSERT( starting_tile + number_of_tiles <= ::TIFFNumberOfTiles( &source.lib_object() ) );
             if ( tile_height > static_cast<uint32>( dimensions.y ) )
             {
                 rows_to_read_per_tile = end_rows_to_read = dimensions.y;
@@ -505,17 +625,11 @@
         unsigned int starting_strip;
     };
 
-    class cumulative_result : public detail::cumulative_result
-    {
-    public:
-        void throw_if_error() const { detail::cumulative_result::throw_if_error( "Error reading TIFF file" ); }
-    };
-
-    void raw_copy_to_prepared_view( tiff_view_data_t const view_data ) const
+    void raw_copy_to_prepared_view( view_data_t const & view_data ) const
     {
         cumulative_result result;
 
-        if ( ::TIFFIsTiled( p_tiff_ ) )
+        if ( ::TIFFIsTiled( &lib_object() ) )
         {
             tile_setup_t setup( *this, view_data.dimensions_, view_data.offset_, false );
 
@@ -529,7 +643,7 @@
                     bool         const last_row_tile        ( !--setup.current_row_tiles_remaining                                     );
                     unsigned int const this_tile_width_bytes( last_row_tile ? setup.last_row_tile_width_bytes : setup.tile_width_bytes );
 
-                    result.accumulate_equal( ::TIFFReadEncodedTile( p_tiff_, current_tile, setup.p_tile_buffer.get(), setup.tile_size_bytes ), setup.tile_size_bytes );
+                    result.accumulate_equal( ::TIFFReadEncodedTile( &lib_object(), current_tile, setup.p_tile_buffer.get(), setup.tile_size_bytes ), setup.tile_size_bytes );
                     unsigned char const * p_tile_buffer_location( setup.p_tile_buffer.get() + ( setup.rows_to_skip * this_tile_width_bytes ) );
                     unsigned char       * p_target_local        ( p_target                                                                   );
                     for ( unsigned int row( setup.rows_to_skip ); row < setup.rows_to_read_per_tile; ++row )
@@ -556,7 +670,7 @@
         }
         else
         {
-            BOOST_ASSERT( ::TIFFScanlineSize( p_tiff_ ) <= static_cast<tsize_t>( view_data.stride_ ) );
+            BOOST_ASSERT( ::TIFFScanlineSize( &lib_object() ) <= static_cast<tsize_t>( view_data.stride_ ) );
             for ( unsigned int plane( 0 ); plane < view_data.number_of_planes_; ++plane )
             {
                 unsigned char * buf( view_data.plane_buffers_[ plane ] );
@@ -567,16 +681,16 @@
                 unsigned int row( view_data.offset_ );
                 while ( row != ( view_data.offset_ + skip_result.rows_to_read_using_scanlines ) )
                 {
-                    result.accumulate_equal( ::TIFFReadScanline( p_tiff_, buf, row++, static_cast<tsample_t>( plane ) ), 1 );
+                    result.accumulate_equal( ::TIFFReadScanline( &lib_object(), buf, row++, static_cast<tsample_t>( plane ) ), 1 );
                     buf += view_data.stride_;
                 }
 
                 unsigned int const view_strip_increment( view_data.stride_ * skip_result.rows_per_strip );
-                if ( view_strip_increment == static_cast<unsigned int>( ::TIFFStripSize( p_tiff_ ) ) )
+                if ( view_strip_increment == static_cast<unsigned int>( ::TIFFStripSize( &lib_object() ) ) )
                 {
                     for ( unsigned int strip( skip_result.starting_strip ); strip < number_of_strips; ++strip )
                     {
-                        result.accumulate_different( ::TIFFReadEncodedStrip( p_tiff_, strip, buf, view_strip_increment ), -1 );
+                        result.accumulate_different( ::TIFFReadEncodedStrip( &lib_object(), strip, buf, view_strip_increment ), -1 );
                         buf += view_strip_increment;
                         row += skip_result.rows_per_strip;
                     }
@@ -585,7 +699,7 @@
                 unsigned int const target_row( view_data.offset_ + view_data.dimensions_.y );
                 while ( row < target_row )
                 {
-                    result.accumulate_equal( ::TIFFReadScanline( p_tiff_, buf, row++, static_cast<tsample_t>( plane ) ), 1 );
+                    result.accumulate_equal( ::TIFFReadScanline( &lib_object(), buf, row++, static_cast<tsample_t>( plane ) ), 1 );
                     buf += view_data.stride_;
                 }
             }
@@ -594,6 +708,20 @@
         result.throw_if_error();
     }
 
+    
+    ////////////////////////////////////////////////////////////////////////////
+    //
+    // generic_convert_to_prepared_view()
+    // ----------------------------------
+    //
+    ////////////////////////////////////////////////////////////////////////////
+    ///
+    /// \todo Cleanup, document, split up and refactor this humongous beast
+    /// (remove duplication, extract non-template and shared functionality...).
+    ///                                    (16.09.2010.) (Domagoj Saric)
+    ///
+    ////////////////////////////////////////////////////////////////////////////
+    
     template <class MyView, class TargetView, class Converter>
     void generic_convert_to_prepared_view( TargetView const & view, Converter const & converter ) const
     {
@@ -635,7 +763,7 @@
         // Tiled
         ////////////////////////////////////////////////////////////////////////
 
-        if ( ::TIFFIsTiled( p_tiff_ ) )
+        if ( ::TIFFIsTiled( &lib_object() ) )
         {
             tile_setup_t setup
             (
@@ -679,7 +807,7 @@
                         (
                             ::TIFFReadEncodedTile
                             (
-                                p_tiff_,
+                                &lib_object(),
                                 raw_tile_number,
                                 //buffer_iterator.at_c_dynamic( channel_tile ),
                                 &(*buffer_iterator)[ channel_tile ],
@@ -744,7 +872,7 @@
                         //unsigned int const this_tile_size_bytes ( last_row_tile ? setup.last_row_tile_size_bytes  : setup.tile_size_bytes  );
                         unsigned int const this_tile_width_bytes( last_row_tile ? setup.last_row_tile_width_bytes : setup.tile_width_bytes );
 
-                        result.accumulate_equal( ::TIFFReadEncodedTile( p_tiff_, current_tile, setup.p_tile_buffer.get(), setup.tile_size_bytes ), setup.tile_size_bytes );
+                        result.accumulate_equal( ::TIFFReadEncodedTile( &lib_object(), current_tile, setup.p_tile_buffer.get(), setup.tile_size_bytes ), setup.tile_size_bytes );
 
                         my_pixel_t const * p_source_pixel( gil_reinterpret_cast_c<my_pixel_t const *>( setup.p_tile_buffer.get() + ( current_plane_rows_to_skip * this_tile_width_bytes ) ) );
                         target_x_iterator  p_target_pixel( p_target.base() + horizontal_offset );
@@ -816,7 +944,7 @@
                     {
                         tdata_t const p_buffer( &(*buffer_iterator)[ plane ] );
                         skip_to_row( get_offset<offset_t>( view ), plane, p_buffer, result );
-                        result.accumulate_equal( ::TIFFReadScanline( p_tiff_, p_buffer, row, static_cast<tsample_t>( plane ) ), 1 );
+                        result.accumulate_equal( ::TIFFReadScanline( &lib_object(), p_buffer, row, static_cast<tsample_t>( plane ) ), 1 );
                     }
                     typename          MyView       ::x_iterator p_source_pixel( buffer_iterator );
                     typename original_target_view_t::x_iterator p_target_pixel( p_target.base() );
@@ -842,7 +970,7 @@
                     unsigned int const target_row( row + dimensions.y           );
                     while ( row != target_row )
                     {
-                        result.accumulate_equal( ::TIFFReadScanline( p_tiff_, scanline_buffer.begin(), row++, static_cast<tsample_t>( plane ) ), 1 );
+                        result.accumulate_equal( ::TIFFReadScanline( &lib_object(), scanline_buffer.begin(), row++, static_cast<tsample_t>( plane ) ), 1 );
                         my_pixel_t const * p_source_pixel( scanline_buffer.begin() );
                         target_x_iterator  p_target_pixel( p_target.base()         );
                         while ( p_source_pixel != scanline_buffer.end() )
@@ -860,7 +988,6 @@
         result.throw_if_error();
     }
 
-
 private:
     template <typename View>
     static typename nth_channel_view_type<View>::type
@@ -955,8 +1082,8 @@
     class scanline_buffer_t : noncopyable
     {
     public:
-        scanline_buffer_t( libtiff_image const & tiff, mpl::true_ /*      nptcc  */ ) : buffer_( planar_scanline_buffer_aux( tiff          ) ) {}
-        scanline_buffer_t( libtiff_image const & tiff, mpl::false_ /* not nptcc  */ ) : buffer_( scanline_buffer_aux       ( *tiff.p_tiff_ ) ) {} 
+        scanline_buffer_t( libtiff_image const & tiff, mpl::true_ /*      nptcc  */ ) : buffer_( planar_scanline_buffer_aux( tiff              ) ) {}
+        scanline_buffer_t( libtiff_image const & tiff, mpl::false_ /* not nptcc  */ ) : buffer_( scanline_buffer_aux       ( tiff.lib_object() ) ) {} 
 
         Pixel       * begin() const { return gil_reinterpret_cast  <Pixel       *>( buffer_.first.get() ); }
         Pixel const * end  () const { return gil_reinterpret_cast_c<Pixel const *>( buffer_.second      ); }
@@ -987,7 +1114,7 @@
         cumulative_result &       error_result
     ) const
     {
-        BOOST_ASSERT( !::TIFFIsTiled( p_tiff_ ) );
+        BOOST_ASSERT( !::TIFFIsTiled( &lib_object() ) );
 
         skip_row_results_t result;
         result.rows_per_strip               = get_field<uint32>( TIFFTAG_ROWSPERSTRIP );
@@ -1008,17 +1135,15 @@
         );
         while ( row < row_to_skip_to )
         {
-            error_result.accumulate_equal( ::TIFFReadScanline( p_tiff_, buffer, row++, static_cast<tsample_t>( sample ) ), 1 );
+            error_result.accumulate_equal( ::TIFFReadScanline( &lib_object(), buffer, row++, static_cast<tsample_t>( sample ) ), 1 );
         }
 
-        //BOOST_ASSERT( !row_to_skip_to || ( ::TIFFCurrentRow( p_tiff_ ) == row_to_skip_to ) );
+        //BOOST_ASSERT( !row_to_skip_to || ( ::TIFFCurrentRow( &lib_object() ) == row_to_skip_to ) );
 
         return result;
     }
 
 private:
-    TIFF * /*const*/ p_tiff_;
-
     full_format_t format_;
 };
 
@@ -1027,13 +1152,9 @@
 #endif
 
 
-
-
-//------------------------------------------------------------------------------
-} // namespace detail
 //------------------------------------------------------------------------------
 } // namespace gil
 //------------------------------------------------------------------------------
 } // namespace boost
 //------------------------------------------------------------------------------
-#endif // libjpeg_private_base_hpp
+#endif // libtiff_image_hpp
Deleted: sandbox/gil/boost/gil/extension/io2/libtiff_private_base.hpp
==============================================================================
--- sandbox/gil/boost/gil/extension/io2/libtiff_private_base.hpp	2010-09-18 17:27:50 EDT (Sat, 18 Sep 2010)
+++ (empty file)
@@ -1,1039 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-///
-/// \file libtiff_private_base.hpp
-/// ------------------------------
-///
-/// 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 libtiff_private_base_hpp__0808D24E_CED1_4921_A832_3C12DAE93Ef7
-#define libtiff_private_base_hpp__0808D24E_CED1_4921_A832_3C12DAE93Ef7
-//------------------------------------------------------------------------------
-#include "formatted_image.hpp"
-
-#include "detail/io_error.hpp"
-#include "detail/libx_shared.hpp"
-
-#if BOOST_MPL_LIMIT_VECTOR_SIZE < 35
-    ...error...libtiff support requires mpl vectors of size 35 or greater...
-#endif
-
-#include <boost/array.hpp>
-#include <boost/mpl/vector.hpp>
-#include <boost/smart_ptr/scoped_array.hpp>
-
-#include "tiff.h"
-#include "tiffio.h"
-
-#include <cstdio>
-#include <set>
-#include "io.h"
-//------------------------------------------------------------------------------
-namespace boost
-{
-//------------------------------------------------------------------------------
-namespace gil
-{
-//------------------------------------------------------------------------------
-namespace detail
-{
-//------------------------------------------------------------------------------
-
-unsigned short const unknown( static_cast<unsigned short>( -1 ) );
-
-#define LIBTIFF_SPP(         param ) ( ( param ) << ( 0 ) )
-#define LIBTIFF_BPS(         param ) ( ( param ) << ( 0 + 3 ) )
-#define LIBTIFF_FMT(         param ) ( ( param ) << ( 0 + 3 + 5 ) )
-#define LIBTIFF_PLANAR(      param ) ( ( param ) << ( 0 + 3 + 5 + 3 ) )
-#define LIBTIFF_PHOTOMETRIC( param ) ( ( param ) << ( 0 + 3 + 5 + 3 + 2 ) )
-#define LIBTIFF_INKSET(      param ) ( ( param ) << ( 0 + 3 + 5 + 3 + 2 + 2 ) )
-
-#define LIBTIFF_FORMAT( spp, bps, sample_format, planar_config, photometric_interpretation, inkset )    \
-    (                                                                                                   \
-        LIBTIFF_SPP(         spp                        ) |                                             \
-        LIBTIFF_BPS(         bps                        ) |                                             \
-        LIBTIFF_FMT(         sample_format              ) |                                             \
-        LIBTIFF_PLANAR(      planar_config              ) |                                             \
-        LIBTIFF_PHOTOMETRIC( photometric_interpretation ) |                                             \
-        LIBTIFF_INKSET(      inkset                     )                                               \
-    )
-
-
-
-union full_format_t
-{
-    struct format_bitfield
-    {
-        unsigned int samples_per_pixel    : 3;
-        unsigned int bits_per_sample      : 5;
-        unsigned int sample_format        : 3;
-        unsigned int planar_configuration : 2;
-        unsigned int photometric          : 2;
-        unsigned int ink_set              : 2;
-    };
-
-    typedef unsigned int format_id;
-
-    format_bitfield bits  ;
-    format_id       number;
-};
-
-
-template <typename Pixel, bool isPlanar>
-struct gil_to_libtiff_format
-    :
-    mpl::int_
-    <
-        LIBTIFF_FORMAT
-        (
-            num_channels<Pixel>::value,
-            sizeof( typename channel_type<Pixel>::type ) * 8,
-            (
-                ( is_unsigned      <typename channel_type<Pixel>::type>::value * SAMPLEFORMAT_UINT   ) |
-                ( is_signed        <typename channel_type<Pixel>::type>::value * SAMPLEFORMAT_INT    ) |
-                ( is_floating_point<typename channel_type<Pixel>::type>::value * SAMPLEFORMAT_IEEEFP )
-            ),
-            isPlanar ? PLANARCONFIG_SEPARATE : PLANARCONFIG_CONTIG,
-            (
-                ( is_same<typename color_space_type<Pixel>::type, rgb_t >::value * PHOTOMETRIC_RGB        ) |
-                ( is_same<typename color_space_type<Pixel>::type, cmyk_t>::value * PHOTOMETRIC_SEPARATED  ) |
-                ( is_same<typename color_space_type<Pixel>::type, gray_t>::value * PHOTOMETRIC_MINISBLACK )
-            ),
-            ( is_same<typename color_space_type<Pixel>::type, cmyk_t>::value ? INKSET_CMYK : 0 )
-        )
-    >
-{};
-
-
-struct view_libtiff_format
-{
-    template <class View>
-    struct apply : gil_to_libtiff_format<typename View::value_type, is_planar<View>::value> {};
-};
-
-
-typedef mpl::vector35
-<
-    image<rgb8_pixel_t , false>,
-    image<rgb8_pixel_t , true >,
-    image<rgba8_pixel_t, false>,
-    image<rgba8_pixel_t, true >,
-    image<cmyk8_pixel_t, false>,
-    image<cmyk8_pixel_t, true >,
-    image<gray8_pixel_t, false>,
-
-    image<rgb16_pixel_t , false>,
-    image<rgb16_pixel_t , true >,
-    image<rgba16_pixel_t, false>,
-    image<rgba16_pixel_t, true >,
-    image<cmyk16_pixel_t, false>,
-    image<cmyk16_pixel_t, true >,
-    image<gray16_pixel_t, false>,
-
-    image<rgb8s_pixel_t , false>,
-    image<rgb8s_pixel_t , true >,
-    image<rgba8s_pixel_t, false>,
-    image<rgba8s_pixel_t, true >,
-    image<cmyk8s_pixel_t, false>,
-    image<cmyk8s_pixel_t, true >,
-    image<gray8s_pixel_t, false>,
-
-    image<rgb16s_pixel_t , false>,
-    image<rgb16s_pixel_t , true >,
-    image<rgba16s_pixel_t, false>,
-    image<rgba16s_pixel_t, true >,
-    image<cmyk16s_pixel_t, false>,
-    image<cmyk16s_pixel_t, true >,
-    image<gray16s_pixel_t, false>,
-
-    image<rgb32f_pixel_t , false>,
-    image<rgb32f_pixel_t , true >,
-    image<rgba32f_pixel_t, false>,
-    image<rgba32f_pixel_t, true >,
-    image<cmyk32f_pixel_t, false>,
-    image<cmyk32f_pixel_t, true >,
-    image<gray32f_pixel_t, false>
-> libtiff_supported_pixel_formats;
-
-
-inline tsize_t FILE_read_proc( thandle_t const handle, tdata_t const buf, tsize_t const size )
-{
-    return static_cast<tsize_t>( std::fread( buf, 1, size,  reinterpret_cast<FILE *>( handle ) ) );
-}
-
-inline tsize_t FILE_write_proc( thandle_t const handle, tdata_t const buf, tsize_t const size )
-{
-    return static_cast<tsize_t>( std::fwrite( buf, 1, size,  reinterpret_cast<FILE *>( handle ) ) );
-}
-
-inline toff_t FILE_seek_proc( thandle_t const handle, toff_t const off, int const whence )
-{
-    return static_cast<tsize_t>( std::fseek( reinterpret_cast<FILE *>( handle ), off, whence ) );
-}
-
-inline int FILE_close_proc( thandle_t const handle )
-{
-    return std::fclose( reinterpret_cast<FILE *>( handle ) );
-}
-
-inline int FILE_close_proc_nop( thandle_t /*handle*/ )
-{
-    return 0;
-}
-
-inline toff_t FILE_size_proc( thandle_t const fd )
-{
-    return /*std*/::_filelength( /*std*/::_fileno( gil_reinterpret_cast<FILE *>( fd ) ) );
-}
-
-inline int FILE_map_proc( thandle_t /*handle*/, tdata_t * /*pbase*/, toff_t * /*psize*/ )
-{
-    return 0;
-}
-
-inline void FILE_unmap_proc( thandle_t /*handle*/, tdata_t /*base*/, toff_t /*size*/ )
-{
-}
-
-
-struct libtiff_guard {};
-
-
-#if defined(BOOST_MSVC)
-#   pragma warning( push )
-#   pragma warning( disable : 4127 ) // "conditional expression is constant"
-#endif
-
-
-struct tiff_view_data_t
-{
-    template <class View>
-    tiff_view_data_t( View const & view, generic_vertical_roi::offset_t const offset )
-        :
-        offset_    ( offset                                     ),
-        dimensions_( view.dimensions()                          ),
-        stride_    ( view.pixels().row_size()                   )
-        #ifdef _DEBUG
-            ,format_( view_libtiff_format::apply<View>::value   )
-        #endif
-    {
-        set_buffers( view, is_planar<View>() );
-    }
-
-    void set_format( full_format_t::format_id const format )
-    {
-        //BOOST_ASSERT( ( format_ == format ) && !"libtiff does not provide builtin conversion." );
-        ignore_unused_variable_warning( format );
-    }
-
-    generic_vertical_roi::offset_t         offset_;
-    point2<std::ptrdiff_t>         const & dimensions_;
-    unsigned int                           stride_;
-    unsigned int                           number_of_planes_;
-    array<unsigned char *, 4>              plane_buffers_;
-
-    #ifdef _DEBUG
-        unsigned int format_;
-    #endif
-
-private: // this should probably go to the base formatted_image class...
-    template <class View>
-    void set_buffers( View const & view, mpl::true_ /*is planar*/ )
-    {
-        for ( number_of_planes_ = 0; number_of_planes_ < num_channels<View>::value; ++number_of_planes_ )
-        {
-            plane_buffers_[ number_of_planes_ ] = gil_reinterpret_cast<unsigned char *>( planar_view_get_raw_data( view, number_of_planes_ ) );
-        }
-        BOOST_ASSERT( number_of_planes_ == num_channels<View>::value );
-    }
-
-    template <class View>
-    void set_buffers( View const & view, mpl::false_ /*is not planar*/ )
-    {
-        number_of_planes_ = 1;
-        plane_buffers_[ 0 ] = formatted_image_base::get_raw_data( view );
-    }
-
-    void operator=( tiff_view_data_t const & );
-};
-
-class libtiff_image;
-
-template <>
-struct formatted_image_traits<libtiff_image>
-{
-    typedef full_format_t::format_id format_t;
-
-    typedef libtiff_supported_pixel_formats supported_pixel_formats_t;
-
-    typedef generic_vertical_roi roi_t;
-
-    typedef view_libtiff_format view_to_native_format;
-
-    typedef tiff_view_data_t view_data_t;
-
-    template <class View>
-    struct is_supported : mpl::true_ {};
-
-    BOOST_STATIC_CONSTANT( unsigned int, desired_alignment = 0 );
-
-    BOOST_STATIC_CONSTANT( bool, builtin_conversion = false );
-};
-
-
-class libtiff_image
-    :
-    public  detail::formatted_image<libtiff_image>
-{
-public: /// \ingroup Construction
-    explicit libtiff_image( char const * const file_name )
-        :
-        p_tiff_( ::TIFFOpen( file_name, "r" ) )
-    {
-        BOOST_ASSERT( file_name );
-        constructor_tail();
-    }
-
-    explicit libtiff_image( FILE * const p_file )
-        :
-        p_tiff_
-        (
-            ::TIFFClientOpen
-            (
-                "", "",
-                p_file,
-                &FILE_read_proc,
-                &FILE_write_proc,
-                &FILE_seek_proc,
-                &FILE_close_proc_nop,
-                &FILE_size_proc,
-                &FILE_map_proc,
-                &FILE_unmap_proc
-            )
-        )
-    {
-        BOOST_ASSERT( p_file );
-        constructor_tail();
-    }
-
-    ~libtiff_image()
-    {
-        ::TIFFClose( p_tiff_ );
-    }
-
-public:
-    point2<std::ptrdiff_t> dimensions() const
-    {
-        return point2<std::ptrdiff_t>( get_field<uint32>( TIFFTAG_IMAGEWIDTH ), get_field<uint32>( TIFFTAG_IMAGELENGTH ) );
-    }
-
-    format_t const & format                      () const { return format_.number; }
-    format_t const & closest_gil_supported_format() const { return format()      ; }
-
-    static std::size_t format_size( format_t const format )
-    {
-        full_format_t::format_bitfield const & bits( reinterpret_cast<full_format_t const &>( format ).bits );
-        return bits.bits_per_sample * ( ( bits.planar_configuration == PLANARCONFIG_CONTIG ) ? bits.samples_per_pixel : 1 ) / 8;
-    }
-
-    full_format_t::format_bitfield const & format_bits() const {return format_.bits; }
-
-
-    TIFF       & lib_object()       { return *p_tiff_; }
-    TIFF const & lib_object() const { return const_cast<libtiff_image &>( *this ).lib_object(); }
-
-private:
-    template <typename T>
-    T get_field( ttag_t const tag ) const
-    {
-        T value; T * p_value( &value );
-        BOOST_VERIFY( ::TIFFVGetFieldDefaulted( p_tiff_, tag, gil_reinterpret_cast<va_list>( &p_value ) ) );
-        return value;
-    }
-
-    template <typename T1, typename T2>
-    std::pair<T1, T2> get_field( ttag_t const tag, int & cumulative_result ) const
-    {
-        std::pair<T1, T2> value;
-        cumulative_result &= ::TIFFGetFieldDefaulted( p_tiff_, tag, &value.first, &value.second );
-        return value;
-    }
-
-    void get_format()
-    {
-        int cumulative_result( true );
-
-        unsigned const samples_per_pixel   ( get_field<uint16>( TIFFTAG_SAMPLESPERPIXEL ) );
-        unsigned const bits_per_sample     ( get_field<uint16>( TIFFTAG_BITSPERSAMPLE   ) );
-        unsigned const sample_format       ( get_field<uint16>( TIFFTAG_SAMPLEFORMAT    ) );
-        unsigned const planar_configuration( get_field<uint16>( TIFFTAG_PLANARCONFIG    ) );
-        //...mrmlj...
-        unsigned /*const*/ photometric         ( get_field<uint16>( TIFFTAG_PHOTOMETRIC     ) ); if ( photometric == PHOTOMETRIC_MINISWHITE ) photometric = PHOTOMETRIC_MINISBLACK;
-
-        unsigned const orientation         ( get_field<uint16>( TIFFTAG_ORIENTATION     ) );
-
-        unsigned ink_set( 0 );
-        bool unsupported_format( false );
-        if ( samples_per_pixel == 4 )
-        {
-            switch ( photometric )
-            {
-                case PHOTOMETRIC_RGB:
-                {
-                    std::pair<uint16, uint16 *> const extrasamples( get_field<uint16, uint16 *>( TIFFTAG_EXTRASAMPLES, cumulative_result ) );
-                    unsupported_format = ( extrasamples.first != 1 || *extrasamples.second != EXTRASAMPLE_UNASSALPHA );
-                    break;
-                }
-
-                case PHOTOMETRIC_SEPARATED:
-                {
-                    ink_set = get_field<uint16>( TIFFTAG_INKSET );
-                    unsupported_format = ( ink_set != INKSET_CMYK );
-                    break;
-                }
-
-                default:
-                    unsupported_format = true;
-            }
-        }
-
-        detail::io_error_if( !cumulative_result || unsupported_format || ( orientation != ORIENTATION_TOPLEFT ), "TeeF" );
-
-        format_.number = LIBTIFF_FORMAT( samples_per_pixel, bits_per_sample, ( sample_format == SAMPLEFORMAT_VOID ) ? SAMPLEFORMAT_UINT : sample_format, planar_configuration, photometric, ink_set );
-    }
-
-
-private:
-    void construction_check() const
-    {
-        detail::io_error_if_not( p_tiff_, "Failed to open TIFF input file" );
-    }
-
-    void constructor_tail()
-    {
-        construction_check();
-        get_format        ();
-    }
-
-    static unsigned int round_up_divide( unsigned int const dividend, unsigned int const divisor )
-    {
-        return ( dividend + divisor - 1 ) / divisor;
-    }
-
-private: // Private formatted_image_base interface.
-    friend base_t;
-    struct tile_setup_t : boost::noncopyable
-    {
-        tile_setup_t( libtiff_image const & source, point2<std::ptrdiff_t> const & dimensions, offset_t const offset, bool const nptcc )
-            :
-            tile_height                ( source.get_field<uint32>( TIFFTAG_TILELENGTH ) ),
-            tile_width                 ( source.get_field<uint32>( TIFFTAG_TILEWIDTH  ) ),
-            row_tiles                  ( source.get_field<uint32>( TIFFTAG_IMAGEWIDTH ) / tile_width ),
-            size_of_pixel              ( ( source.format_bits().planar_configuration == PLANARCONFIG_CONTIG ? source.format_bits().samples_per_pixel : 1 ) * source.format_bits().bits_per_sample / 8 ),
-            tile_width_bytes           ( tile_width * size_of_pixel ),
-            tile_size_bytes            ( tile_width_bytes * tile_height ),
-            p_tile_buffer              ( new unsigned char[ tile_size_bytes * ( nptcc ? source.format_bits().samples_per_pixel : 1 ) ] ),
-            last_row_tile_width        ( modulo_unless_zero( dimensions.x, tile_width ) /*dimensions.x % tile_width*/ ),
-            tiles_per_row              ( ( dimensions.x / tile_width ) + /*( last_row_tile_width != 0 )*/ ( ( dimensions.x % tile_width ) != 0 ) ),
-            last_row_tile_width_bytes  ( last_row_tile_width * size_of_pixel ),
-            last_row_tile_size_bytes   ( last_row_tile_width_bytes * tile_height  ),
-            current_row_tiles_remaining( tiles_per_row ),
-            starting_tile              ( offset / tile_height * tiles_per_row ),
-            rows_to_skip               ( offset % tile_height ),
-            number_of_tiles            ( round_up_divide( dimensions.y, tile_height ) * tiles_per_row * ( source.format_bits().planar_configuration == PLANARCONFIG_SEPARATE ? source.format_bits().samples_per_pixel : 1 ) )
-        {
-            BOOST_ASSERT( static_cast<tsize_t>( tile_width_bytes ) == ::TIFFTileRowSize( source.p_tiff_ ) );
-            BOOST_ASSERT( static_cast<tsize_t>( tile_size_bytes  ) == ::TIFFTileSize   ( source.p_tiff_ ) );
-            BOOST_ASSERT( starting_tile + number_of_tiles <= ::TIFFNumberOfTiles( source.p_tiff_ ) );
-            if ( tile_height > static_cast<uint32>( dimensions.y ) )
-            {
-                rows_to_read_per_tile = end_rows_to_read = dimensions.y;
-            }
-            else
-            {
-                end_rows_to_read = modulo_unless_zero( dimensions.y - ( tile_height - rows_to_skip ), tile_height );
-                bool const starting_at_last_row( ( number_of_tiles - starting_tile ) <= tiles_per_row );
-                rows_to_read_per_tile = starting_at_last_row ? end_rows_to_read : tile_height;
-            }
-
-            #ifdef _DEBUG
-                std::memset( p_tile_buffer.get(), 0xFF, tile_size_bytes * ( nptcc ? source.format_bits().samples_per_pixel : 1 ) );
-            #endif // _DEBUG
-        }
-
-        uint32 const tile_height;
-        uint32 const tile_width ;
-        uint32 const row_tiles  ;
-
-        unsigned int const size_of_pixel   ;
-        size_t       const tile_width_bytes;
-        tsize_t      const tile_size_bytes ;
-
-        scoped_array<unsigned char> p_tile_buffer;
-
-        unsigned int const last_row_tile_width        ;
-        unsigned int const tiles_per_row              ;
-        unsigned int const last_row_tile_width_bytes  ;
-        unsigned int const last_row_tile_size_bytes   ;
-        unsigned int       current_row_tiles_remaining;
-        ttile_t      const starting_tile              ;
-        unsigned int       rows_to_skip               ;
-        ttile_t      const number_of_tiles            ;
-        unsigned int /*const*/ end_rows_to_read           ;
-        unsigned int       rows_to_read_per_tile      ;
-
-    private:
-        static unsigned int modulo_unless_zero( unsigned int const dividend, unsigned int const divisor )
-        {
-            unsigned int const modulo( dividend % divisor );
-            return ( modulo != 0 ) ? modulo : divisor;
-        }
-    };
-
-    struct skip_row_results_t
-    {
-        unsigned int rows_per_strip;
-        unsigned int rows_to_read_using_scanlines;
-        unsigned int starting_strip;
-    };
-
-    class cumulative_result : public detail::cumulative_result
-    {
-    public:
-        void throw_if_error() const { detail::cumulative_result::throw_if_error( "Error reading TIFF file" ); }
-    };
-
-    void raw_copy_to_prepared_view( tiff_view_data_t const view_data ) const
-    {
-        cumulative_result result;
-
-        if ( ::TIFFIsTiled( p_tiff_ ) )
-        {
-            tile_setup_t setup( *this, view_data.dimensions_, view_data.offset_, false );
-
-            ttile_t current_tile( 0 );
-
-            for ( unsigned int plane( 0 ); plane < view_data.number_of_planes_; ++plane )
-            {
-                unsigned char * p_target( view_data.plane_buffers_[ plane ] );
-                for ( current_tile += setup.starting_tile; current_tile < setup.number_of_tiles; ++current_tile )
-                {
-                    bool         const last_row_tile        ( !--setup.current_row_tiles_remaining                                     );
-                    unsigned int const this_tile_width_bytes( last_row_tile ? setup.last_row_tile_width_bytes : setup.tile_width_bytes );
-
-                    result.accumulate_equal( ::TIFFReadEncodedTile( p_tiff_, current_tile, setup.p_tile_buffer.get(), setup.tile_size_bytes ), setup.tile_size_bytes );
-                    unsigned char const * p_tile_buffer_location( setup.p_tile_buffer.get() + ( setup.rows_to_skip * this_tile_width_bytes ) );
-                    unsigned char       * p_target_local        ( p_target                                                                   );
-                    for ( unsigned int row( setup.rows_to_skip ); row < setup.rows_to_read_per_tile; ++row )
-                    {
-                        std::memcpy( p_target_local, p_tile_buffer_location, this_tile_width_bytes );
-                        memunit_advance( p_tile_buffer_location, setup.tile_width_bytes );
-                        memunit_advance( p_target_local        , view_data.stride_      );
-                    }
-                    memunit_advance( p_target, this_tile_width_bytes );
-                    if ( last_row_tile )
-                    {
-                        p_target += ( ( setup.rows_to_read_per_tile - 1 - setup.rows_to_skip ) * view_data.stride_ );
-                        setup.rows_to_skip = 0;
-                        setup.current_row_tiles_remaining = setup.tiles_per_row;
-                        bool const next_row_is_last_row( ( setup.number_of_tiles - ( current_tile + 1 ) ) == setup.tiles_per_row );
-                        if ( next_row_is_last_row )
-                            setup.rows_to_read_per_tile = setup.end_rows_to_read;
-                    }
-                    //BOOST_ASSERT( p_tile_buffer_location == ( setup.p_tile_buffer.get() + this_tile_size_bytes ) || ( setup.rows_to_read_per_tile != setup.tile_height ) );
-                    BOOST_ASSERT( p_target <= view_data.plane_buffers_[ plane ] + ( view_data.stride_ * view_data.dimensions_.y ) );
-                }
-                BOOST_ASSERT( p_target == view_data.plane_buffers_[ plane ] + ( view_data.stride_ * view_data.dimensions_.y ) );
-            }
-        }
-        else
-        {
-            BOOST_ASSERT( ::TIFFScanlineSize( p_tiff_ ) <= static_cast<tsize_t>( view_data.stride_ ) );
-            for ( unsigned int plane( 0 ); plane < view_data.number_of_planes_; ++plane )
-            {
-                unsigned char * buf( view_data.plane_buffers_[ plane ] );
-                skip_row_results_t skip_result( skip_to_row( view_data.offset_, plane, buf, result ) );
-                ttile_t const number_of_strips( ( view_data.dimensions_.y - skip_result.rows_to_read_using_scanlines + skip_result.rows_per_strip - 1 ) / skip_result.rows_per_strip );
-                skip_result.rows_to_read_using_scanlines = std::min<unsigned int>( skip_result.rows_to_read_using_scanlines, view_data.dimensions_.y );
-
-                unsigned int row( view_data.offset_ );
-                while ( row != ( view_data.offset_ + skip_result.rows_to_read_using_scanlines ) )
-                {
-                    result.accumulate_equal( ::TIFFReadScanline( p_tiff_, buf, row++, static_cast<tsample_t>( plane ) ), 1 );
-                    buf += view_data.stride_;
-                }
-
-                unsigned int const view_strip_increment( view_data.stride_ * skip_result.rows_per_strip );
-                if ( view_strip_increment == static_cast<unsigned int>( ::TIFFStripSize( p_tiff_ ) ) )
-                {
-                    for ( unsigned int strip( skip_result.starting_strip ); strip < number_of_strips; ++strip )
-                    {
-                        result.accumulate_different( ::TIFFReadEncodedStrip( p_tiff_, strip, buf, view_strip_increment ), -1 );
-                        buf += view_strip_increment;
-                        row += skip_result.rows_per_strip;
-                    }
-                }
-
-                unsigned int const target_row( view_data.offset_ + view_data.dimensions_.y );
-                while ( row < target_row )
-                {
-                    result.accumulate_equal( ::TIFFReadScanline( p_tiff_, buf, row++, static_cast<tsample_t>( plane ) ), 1 );
-                    buf += view_data.stride_;
-                }
-            }
-        }
-
-        result.throw_if_error();
-    }
-
-    template <class MyView, class TargetView, class Converter>
-    void generic_convert_to_prepared_view( TargetView const & view, Converter const & converter ) const
-    {
-        typedef typename get_original_view_t<TargetView>::type original_target_view_t;
-
-        typedef typename mpl::eval_if
-            <
-                is_planar<MyView>,
-                nth_channel_view_type<original_target_view_t>,
-                get_original_view_t<TargetView>
-            >::type local_target_view_t;
-        typedef typename get_original_view_t<local_target_view_t>::type::x_iterator target_x_iterator;
-        typedef typename get_original_view_t<local_target_view_t>::type::y_iterator target_y_iterator;
-
-        typedef typename mpl::eval_if
-            <
-                is_planar<MyView>,
-                nth_channel_view_type<MyView>,
-                mpl::identity<MyView>
-            >::type::value_type my_pixel_t;
-
-        bool const nondirect_planar_to_contig_conversion
-        (
-             is_planar<MyView                >::value &&
-            !is_planar<original_target_view_t>::value &&
-            (
-                !is_same<typename color_space_type    <MyView>::type, typename color_space_type    <original_target_view_t>::type>::value ||
-                !is_same<typename channel_mapping_type<MyView>::type, typename channel_mapping_type<original_target_view_t>::type>::value
-            )
-        );
-
-        cumulative_result result;
-
-        unsigned int const number_of_planes( is_planar<MyView>::value ? num_channels<MyView>::value : 1 );
-
-        point2<std::ptrdiff_t> const & dimensions( original_view( view ).dimensions() );
-
-        ////////////////////////////////////////////////////////////////////////
-        // Tiled
-        ////////////////////////////////////////////////////////////////////////
-
-        if ( ::TIFFIsTiled( p_tiff_ ) )
-        {
-            tile_setup_t setup
-            (
-                *this,
-                dimensions,
-                get_offset<offset_t>( view ),
-                nondirect_planar_to_contig_conversion
-            );
-
-            unsigned int const tiles_per_plane( setup.number_of_tiles / number_of_planes );
-            ttile_t            current_tile   ( 0                                        );
-
-            if ( nondirect_planar_to_contig_conversion )
-            {
-                // For NPTCC there is no need for target view
-                // planar<->non-planar adjustment because here we read whole
-                // pixels before copying to the target view...
-                typename original_target_view_t::y_iterator p_target( original_view( view ).y_at( 0, 0 ) );
-
-                typename MyView::x_iterator const buffer_iterator
-                (
-                    make_planar_buffer_iterator<typename MyView::x_iterator>
-                    (
-                        setup.p_tile_buffer.get(),
-                        setup.tile_size_bytes,
-                        mpl::int_<number_of_planes>()
-                    )
-                );
-
-                unsigned int horizontal_offset( 0 );
-
-                for ( current_tile += setup.starting_tile; current_tile < tiles_per_plane; ++current_tile )
-                {
-                    bool         const last_row_tile  ( !--setup.current_row_tiles_remaining                         );
-                    unsigned int const this_tile_width( last_row_tile ? setup.last_row_tile_width : setup.tile_width );
-
-                    for ( unsigned int channel_tile( 0 ); channel_tile < number_of_planes; ++channel_tile )
-                    {
-                        ttile_t const raw_tile_number( current_tile + ( channel_tile * tiles_per_plane ) );
-                        result.accumulate_equal
-                        (
-                            ::TIFFReadEncodedTile
-                            (
-                                p_tiff_,
-                                raw_tile_number,
-                                //buffer_iterator.at_c_dynamic( channel_tile ),
-                                &(*buffer_iterator)[ channel_tile ],
-                                setup.tile_size_bytes
-                            ),
-                            setup.tile_size_bytes
-                        );
-                    }
-
-                    typename          MyView       ::x_iterator p_source_pixel( buffer_iterator + ( setup.rows_to_skip * this_tile_width ) );
-                    typename original_target_view_t::x_iterator p_target_pixel( p_target.base() + horizontal_offset                        );
-                    for ( unsigned int row( setup.rows_to_skip ); row < setup.rows_to_read_per_tile; ++row )
-                    {
-                        typename MyView::x_iterator const local_end( p_source_pixel + this_tile_width );
-                        while ( p_source_pixel < local_end )
-                        {
-                            converter( *p_source_pixel, *p_target_pixel );
-                            ++p_source_pixel;
-                            ++p_target_pixel;
-                        }
-                        BOOST_ASSERT( p_source_pixel == local_end );
-                        p_source_pixel += setup.tile_width - this_tile_width;
-                        memunit_advance( p_target_pixel, original_view( view ).pixels().row_size() );
-                        p_target_pixel -= this_tile_width;
-                    }
-                    if ( last_row_tile )
-                    {
-                        p_target += ( setup.rows_to_read_per_tile /*- 1*/ - setup.rows_to_skip );
-                        setup.rows_to_skip = 0;
-                        setup.current_row_tiles_remaining = setup.tiles_per_row;
-                        bool const next_row_is_last_row( ( tiles_per_plane - ( current_tile + 1 ) ) == setup.tiles_per_row );
-                        if ( next_row_is_last_row )
-                            setup.rows_to_read_per_tile = setup.end_rows_to_read;
-                    }
-                    else
-                        horizontal_offset += setup.tile_width;
-                    //...make NPTCC version...BOOST_ASSERT( p_source_pixel == reinterpret_cast<my_pixel_t const *>( setup.p_tile_buffer.get() + this_tile_size_bytes ) || ( setup.rows_to_read_per_tile != setup.tile_height ) );
-                    BOOST_ASSERT( p_target <= original_view( view ).col_end( 0 ) );
-                }
-                BOOST_ASSERT( p_target == original_view( view ).col_end( 0 ) );
-            }
-            else // non NPTCC...
-            {
-                for
-                (
-                    unsigned int plane( 0 ), current_plane_end_tile( tiles_per_plane );
-                    plane < number_of_planes;
-                    ++plane, current_plane_end_tile += tiles_per_plane
-                )
-                {
-                    local_target_view_t const & target_view( adjust_target_to_my_view( original_view( view ), plane, is_planar<MyView>() ) );
-                    target_y_iterator p_target( target_view.y_at( 0, 0 ) );
-                    BOOST_ASSERT( p_target.step() == original_view( view ).pixels().row_size() );
-
-                    unsigned int horizontal_offset                  ( 0                           );
-                    unsigned int current_plane_rows_to_read_per_tile( setup.rows_to_read_per_tile );
-                    unsigned int current_plane_rows_to_skip         ( setup.rows_to_skip          );
-
-                    for ( current_tile += setup.starting_tile; current_tile < current_plane_end_tile; ++current_tile )
-                    {
-                        bool         const last_row_tile        ( !--setup.current_row_tiles_remaining                                     );
-                        //unsigned int const this_tile_size_bytes ( last_row_tile ? setup.last_row_tile_size_bytes  : setup.tile_size_bytes  );
-                        unsigned int const this_tile_width_bytes( last_row_tile ? setup.last_row_tile_width_bytes : setup.tile_width_bytes );
-
-                        result.accumulate_equal( ::TIFFReadEncodedTile( p_tiff_, current_tile, setup.p_tile_buffer.get(), setup.tile_size_bytes ), setup.tile_size_bytes );
-
-                        my_pixel_t const * p_source_pixel( gil_reinterpret_cast_c<my_pixel_t const *>( setup.p_tile_buffer.get() + ( current_plane_rows_to_skip * this_tile_width_bytes ) ) );
-                        target_x_iterator  p_target_pixel( p_target.base() + horizontal_offset );
-                        for ( unsigned int row( current_plane_rows_to_skip ); row < current_plane_rows_to_read_per_tile; ++row )
-                        {
-                            my_pixel_t const * const local_end( memunit_advanced( p_source_pixel, this_tile_width_bytes ) );
-                            while ( p_source_pixel < local_end )
-                            {
-                                converter( *p_source_pixel, *p_target_pixel );
-                                ++p_source_pixel;
-                                ++p_target_pixel;
-                            }
-                            BOOST_ASSERT( p_source_pixel == local_end );
-                            memunit_advance( p_source_pixel, setup.tile_width_bytes - this_tile_width_bytes );
-                            memunit_advance( p_target_pixel, original_view( view ).pixels().row_size() - ( this_tile_width_bytes * memunit_step( p_target_pixel ) / memunit_step( p_source_pixel ) ) );
-                        }
-                        BOOST_ASSERT
-                        (
-                            ( p_source_pixel == reinterpret_cast<my_pixel_t const *>( setup.p_tile_buffer.get() + setup.tile_size_bytes ) ) ||
-                            ( current_plane_rows_to_read_per_tile != setup.tile_height )
-                        );
-                        if ( last_row_tile )
-                        {
-                            p_target += ( current_plane_rows_to_read_per_tile /*- 1*/ - current_plane_rows_to_skip );
-                            current_plane_rows_to_skip = 0;
-                            horizontal_offset          = 0;
-                            setup.current_row_tiles_remaining = setup.tiles_per_row;
-                            bool const next_row_is_last_row( ( current_plane_end_tile - ( current_tile + 1 ) ) == setup.tiles_per_row );
-                            if ( next_row_is_last_row )
-                                current_plane_rows_to_read_per_tile = setup.end_rows_to_read;
-                        }
-                        else
-                        {
-                            BOOST_ASSERT( this_tile_width_bytes == setup.tile_width_bytes );
-                            horizontal_offset += setup.tile_width;
-                        }
-                        BOOST_ASSERT( p_target.base() <= target_view.end().x() );
-                    }
-                    BOOST_ASSERT( p_target.base() == target_view.end().x() );
-                }
-            }
-        }
-        else
-        ////////////////////////////////////////////////////////////////////////
-        // Striped
-        ////////////////////////////////////////////////////////////////////////
-        {
-            scanline_buffer_t<my_pixel_t> const scanline_buffer( *this, mpl::bool_<nondirect_planar_to_contig_conversion>() );
-
-            if ( nondirect_planar_to_contig_conversion )
-            {
-                typename original_target_view_t::y_iterator p_target( original_view( view ).y_at( 0, 0 ) );
-                unsigned int       row       ( get_offset<offset_t>( view ) );
-                unsigned int const target_row( row + dimensions.y           );
-
-                typename MyView::x_iterator const buffer_iterator
-                (
-                    make_planar_buffer_iterator<typename MyView::x_iterator>
-                    (
-                        scanline_buffer.begin(),
-                        dimensions.x,
-                        mpl::int_<number_of_planes>()
-                    )
-                );
-
-                while ( row != target_row )
-                {
-                    for ( unsigned int plane( 0 ); plane < number_of_planes; ++plane )
-                    {
-                        tdata_t const p_buffer( &(*buffer_iterator)[ plane ] );
-                        skip_to_row( get_offset<offset_t>( view ), plane, p_buffer, result );
-                        result.accumulate_equal( ::TIFFReadScanline( p_tiff_, p_buffer, row, static_cast<tsample_t>( plane ) ), 1 );
-                    }
-                    typename          MyView       ::x_iterator p_source_pixel( buffer_iterator );
-                    typename original_target_view_t::x_iterator p_target_pixel( p_target.base() );
-                    while ( &(*p_source_pixel)[ 0 ] < &(*scanline_buffer.end())[ 0 ] )
-                    {
-                        converter( *p_source_pixel, *p_target_pixel );
-                        ++p_source_pixel;
-                        ++p_target_pixel;
-                    }
-                    ++p_target;
-                    ++row;
-                }
-            }
-            else
-            {
-                for ( unsigned int plane( 0 ); plane < number_of_planes; ++plane )
-                {
-                    skip_to_row( get_offset<offset_t>( view ), plane, scanline_buffer.begin(), result );
-
-                    local_target_view_t const & target_view( adjust_target_to_my_view( original_view( view ), plane, is_planar<MyView>() ) );
-                    target_y_iterator p_target( target_view.y_at( 0, 0 ) );
-                    unsigned int       row       ( get_offset<offset_t>( view ) );
-                    unsigned int const target_row( row + dimensions.y           );
-                    while ( row != target_row )
-                    {
-                        result.accumulate_equal( ::TIFFReadScanline( p_tiff_, scanline_buffer.begin(), row++, static_cast<tsample_t>( plane ) ), 1 );
-                        my_pixel_t const * p_source_pixel( scanline_buffer.begin() );
-                        target_x_iterator  p_target_pixel( p_target.base()         );
-                        while ( p_source_pixel != scanline_buffer.end() )
-                        {
-                            converter( *p_source_pixel, *p_target_pixel );
-                            ++p_source_pixel;
-                            ++p_target_pixel;
-                        }
-                        ++p_target;
-                    }
-                }
-            }
-        }
-
-        result.throw_if_error();
-    }
-
-
-private:
-    template <typename View>
-    static typename nth_channel_view_type<View>::type
-    adjust_target_to_my_view( View const & view, unsigned int const plane, mpl::true_ /*source is planar*/ )
-    {
-        return nth_channel_view( view, plane );
-    }
-
-    template <typename View>
-    static View const &
-    adjust_target_to_my_view( View const & view, unsigned int const plane, mpl::false_ /*source is not planar*/ )
-    {
-        BOOST_ASSERT( plane == 0 );
-        ignore_unused_variable_warning( plane );
-        return view;
-    }
-
-    template <typename PixelIterator>
-    static PixelIterator
-    make_planar_buffer_iterator( void * const p_buffer, unsigned int /*row_width*/, mpl::int_<1> )
-    {
-        BOOST_ASSERT( !"Should not get called." );
-        return static_cast<PixelIterator>( p_buffer );
-    }
-
-    template <typename PlanarPixelIterator>
-    static PlanarPixelIterator
-    make_planar_buffer_iterator( void * const p_buffer, unsigned int const row_width, mpl::int_<2> )
-    {
-        typedef typename channel_type<PlanarPixelIterator>::type * ptr_t;
-        unsigned int const stride( row_width * memunit_step( ptr_t() ) );
-        ptr_t const first ( static_cast<ptr_t>( p_buffer ) );
-        ptr_t const second( first + stride                 );
-        return PlanarPixelIterator( first, second );
-    }
-
-    template <typename PlanarPixelIterator>
-    static PlanarPixelIterator
-    make_planar_buffer_iterator( void * const p_buffer, unsigned int const row_width, mpl::int_<3> )
-    {
-        typedef typename channel_type<PlanarPixelIterator>::type * ptr_t;
-        unsigned int const stride( row_width * memunit_step( ptr_t() ) );
-        ptr_t const first ( static_cast<ptr_t>( p_buffer ) );
-        ptr_t const second( first  + stride                );
-        ptr_t const third ( second + stride                );
-        return PlanarPixelIterator( first, second, third );
-    }
-
-    template <typename PlanarPixelIterator>
-    static PlanarPixelIterator
-    make_planar_buffer_iterator( void * const p_buffer, unsigned int const row_width, mpl::int_<4> )
-    {
-        //...eradicate this triplication...
-        typedef typename channel_type<PlanarPixelIterator>::type * ptr_t;
-        unsigned int const stride( row_width * memunit_step( ptr_t() ) );
-        ptr_t const first ( static_cast<ptr_t>( p_buffer ) );
-        ptr_t const second( memunit_advanced( first , stride ) );
-        ptr_t const third ( memunit_advanced( second, stride ) );
-        ptr_t const fourth( memunit_advanced( third , stride ) );
-        return PlanarPixelIterator( first, second, third, fourth );
-    }
-
-    typedef std::pair
-        <
-            scoped_array<unsigned char> const,
-            unsigned char const * const
-        > generic_scanline_buffer_t;
-
-    static generic_scanline_buffer_t scanline_buffer_aux( TIFF & tiff )
-    {
-        unsigned int const scanlineSize( ::TIFFScanlineSize( &tiff ) );
-        unsigned char * const p_buffer( new unsigned char[ scanlineSize ] );
-        #ifdef _DEBUG
-            std::memset( p_buffer, 0xFF, scanlineSize );
-        #endif // _DEBUG
-        return std::make_pair( p_buffer, p_buffer + scanlineSize );
-    }
-
-    // This one makes the end pointer point to the end of the scanline/row of
-    // the first plane not the end of the buffer itself...ugh...to be cleaned up...
-    static generic_scanline_buffer_t planar_scanline_buffer_aux( libtiff_image const & tiff )
-    {
-        unsigned int const scanlineSize( tiff.format_bits().bits_per_sample * tiff.dimensions().x / 8 );
-        unsigned char * const p_buffer( new unsigned char[ scanlineSize * tiff.format_bits().samples_per_pixel ] );
-        #ifdef _DEBUG
-            std::memset( p_buffer, 0xFF, scanlineSize * tiff.format_bits().samples_per_pixel );
-        #endif // _DEBUG
-        return std::make_pair( p_buffer, p_buffer + scanlineSize );
-    }
-
-    template <typename Pixel>
-    class scanline_buffer_t : noncopyable
-    {
-    public:
-        scanline_buffer_t( libtiff_image const & tiff, mpl::true_ /*      nptcc  */ ) : buffer_( planar_scanline_buffer_aux( tiff          ) ) {}
-        scanline_buffer_t( libtiff_image const & tiff, mpl::false_ /* not nptcc  */ ) : buffer_( scanline_buffer_aux       ( *tiff.p_tiff_ ) ) {} 
-
-        Pixel       * begin() const { return gil_reinterpret_cast  <Pixel       *>( buffer_.first.get() ); }
-        Pixel const * end  () const { return gil_reinterpret_cast_c<Pixel const *>( buffer_.second      ); }
-
-    private:
-        generic_scanline_buffer_t const buffer_;
-    };
-
-    template <typename Pixel>
-    class planar_scanline_buffer_t : noncopyable
-    {
-    public:
-        planar_scanline_buffer_t( libtiff_image & image ) : buffer_( planar_scanline_buffer_aux( tiff ) ) {}
-
-        Pixel       * begin() const { return gil_reinterpret_cast  <Pixel       *>( buffer_.first.get() ); }
-        Pixel const * end  () const { return gil_reinterpret_cast_c<Pixel const *>( buffer_.second      ); }
-
-    private:
-        generic_scanline_buffer_t const buffer_;
-    };
-
-
-    skip_row_results_t skip_to_row
-    (
-        unsigned int        const row_to_skip_to,
-        unsigned int        const sample,
-        tdata_t             const buffer,
-        cumulative_result &       error_result
-    ) const
-    {
-        BOOST_ASSERT( !::TIFFIsTiled( p_tiff_ ) );
-
-        skip_row_results_t result;
-        result.rows_per_strip               = get_field<uint32>( TIFFTAG_ROWSPERSTRIP );
-        unsigned int const number_of_rows_to_skip_using_scanlines( row_to_skip_to % result.rows_per_strip );
-        result.starting_strip               = ( row_to_skip_to / result.rows_per_strip ) + ( number_of_rows_to_skip_using_scanlines != 0 ) + sample * get_field<uint32>( TIFFTAG_IMAGEWIDTH );
-        result.rows_to_read_using_scanlines = row_to_skip_to ? ( result.rows_per_strip - number_of_rows_to_skip_using_scanlines - 1 ) : 0;
-
-        bool const canSkipDirectly
-        (
-            ( result.rows_per_strip                    == 1                ) ||
-            ( get_field<uint16>( TIFFTAG_COMPRESSION ) == COMPRESSION_NONE )
-        );
-        unsigned int row
-        (
-            canSkipDirectly
-                ? row_to_skip_to
-                : ( row_to_skip_to - number_of_rows_to_skip_using_scanlines )
-        );
-        while ( row < row_to_skip_to )
-        {
-            error_result.accumulate_equal( ::TIFFReadScanline( p_tiff_, buffer, row++, static_cast<tsample_t>( sample ) ), 1 );
-        }
-
-        //BOOST_ASSERT( !row_to_skip_to || ( ::TIFFCurrentRow( p_tiff_ ) == row_to_skip_to ) );
-
-        return result;
-    }
-
-private:
-    TIFF * /*const*/ p_tiff_;
-
-    full_format_t format_;
-};
-
-#if defined(BOOST_MSVC)
-#   pragma warning( pop )
-#endif
-
-
-
-
-//------------------------------------------------------------------------------
-} // namespace detail
-//------------------------------------------------------------------------------
-} // namespace gil
-//------------------------------------------------------------------------------
-} // namespace boost
-//------------------------------------------------------------------------------
-#endif // libjpeg_private_base_hpp
Modified: sandbox/gil/boost/gil/extension/io2/wic_image.hpp
==============================================================================
--- sandbox/gil/boost/gil/extension/io2/wic_image.hpp	(original)
+++ sandbox/gil/boost/gil/extension/io2/wic_image.hpp	2010-09-18 17:27:50 EDT (Sat, 18 Sep 2010)
@@ -42,23 +42,22 @@
 namespace gil
 {
 //------------------------------------------------------------------------------
-
-class wic_image;
-
 namespace detail
 {
 //------------------------------------------------------------------------------
 
-template <GUID const & guid>
+typedef WICPixelFormatGUID const & wic_format_t;
+
+template <wic_format_t guid>
 struct format_guid
 {
     typedef format_guid type;
 
-    static GUID const & value;
+    static wic_format_t & value;
 };
 
-template <GUID const & guid>
-GUID const & format_guid<guid>::value( guid );
+template <wic_format_t guid>
+wic_format_t format_guid<guid>::value( guid );
 
 template <typename Pixel, bool IsPlanar>
 struct gil_to_wic_format : format_guid<GUID_WICPixelFormatUndefined> {};
@@ -74,7 +73,7 @@
 template <> struct gil_to_wic_format<bgra16_pixel_t    , false> : format_guid<GUID_WICPixelFormat64bppBGRA  > {};
 template <> struct gil_to_wic_format<cmyk8_pixel_t     , false> : format_guid<GUID_WICPixelFormat32bppCMYK  > {};
 
-template <GUID const & wic_format>
+template <wic_format_t wic_format>
 struct is_supported_format
     : is_same
       <
@@ -132,95 +131,191 @@
 };
 
 
-template <>
-struct formatted_image_traits<wic_image>
+inline void ensure_result( HRESULT const result )
 {
-    typedef WICPixelFormatGUID const & format_t;
-
-    typedef wic_supported_pixel_formats supported_pixel_formats_t;
+    io_error_if( result != S_OK, "WIC failure"/*error_string( result )*/ );
+}
 
-    typedef wic_roi roi_t;
+inline void verify_result( HRESULT const result )
+{
+    BOOST_VERIFY( result == S_OK );
+}
 
-    typedef view_wic_format view_to_native_format;
+struct wic_view_data_t
+{
+    template <typename View>
+    wic_view_data_t( View const & view )
+        :
+        p_roi_ ( 0                                   ),
+        format_( view_wic_format::apply<View>::value )
+    {
+        set_bitmapdata_for_view( view );
+    }
 
-    template <class View>
-    struct is_supported
+    template <typename View>
+    wic_view_data_t( View const & view, wic_roi::offset_t const & offset )
         :
-        mpl::not_
-        <
-            is_same
-            <
-                typename view_wic_format::apply<View>::type,
-                //format_guid<wic_format                  >,
-                format_guid<GUID_WICPixelFormatUndefined>
-            >
-        > {};
+        p_roi_ ( static_cast<wic_roi const *>( optional_roi_.address() ) ),
+        format_( view_wic_format::apply<View>::value                     )
+    {
+        set_bitmapdata_for_view( view );
+        new ( optional_roi_.address() ) wic_roi( offset, width_, height_ );
+    }
+
+    WICRect      const * const p_roi_ ;
+    unsigned int         /*const*/ width_ ;
+    unsigned int         /*const*/ height_;
+    unsigned int         /*const*/ stride_;
+    unsigned int         /*const*/ pixel_size_;
+    BYTE               * /*const*/ p_buffer_;
+    wic_format_t               format_;
+
+private:
+    template <typename View>
+    void set_bitmapdata_for_view( View const & view )
+    {
+        width_      = view.width();
+        height_     = view.height();
+        stride_     = view.pixels().row_size();
+        pixel_size_ = memunit_step( typename View::x_iterator() );
+        //format_     = view_wic_format::apply<View>::value;
+        p_buffer_   = detail::formatted_image_base::get_raw_data( view );
+    }
+
+    void operator=( wic_view_data_t const & );
+
+private:
+    aligned_storage<sizeof( wic_roi ), alignment_of<wic_roi>::value>::type optional_roi_;
+};
+
+
+class wic_writer : public configure_on_write_writer
+{
+public:
+    struct lib_object_t
+    {
+        CComPtr<IWICBitmapFrameEncode>   p_frame_           ;
+        CComPtr<IWICBitmapEncoder    >   p_encoder_         ;
+        IPropertyBag2                  * p_frame_parameters_;
+    };
+
+    lib_object_t & lib_object() { return lib_object_; }
+
+public:
+    wic_writer( IStream & target )
+    {
+        create_encoder( GUID_ContainerFormatPng, target );
+    }
 
-    struct view_data_t
+    void write_default( wic_view_data_t const & view_data )
     {
-        template <typename View>
-        view_data_t( View const & view )
-            :
-            p_roi_ ( 0                                   ),
-            format_( view_wic_format::apply<View>::value )
+        HRESULT hr( frame().Initialize( lib_object().p_frame_parameters_ ) );
+
+        if ( SUCCEEDED( hr ) )
         {
-            set_bitmapdata_for_view( view );
+            hr = frame().SetSize( view_data.width_, view_data.height_ );
         }
 
-        template <typename View>
-        view_data_t( View const & view, wic_roi::offset_t const & offset )
-            :
-            p_roi_ ( static_cast<wic_roi const *>( optional_roi_.address() ) ),
-            format_( view_wic_format::apply<View>::value )
+        if ( SUCCEEDED( hr ) )
         {
-            set_bitmapdata_for_view( view );
-            new ( optional_roi_.address() ) wic_roi( offset, width_, height_ );
+            WICPixelFormatGUID formatGUID( view_data.format_ );
+            hr = frame().SetPixelFormat( &formatGUID );
+            if ( SUCCEEDED( hr ) )
+            {
+                hr = ( formatGUID == view_data.format_ ) ? S_OK : E_FAIL;
+            }
         }
 
-        WICRect      const * const p_roi_ ;
-        unsigned int         /*const*/ width_ ;
-        unsigned int         /*const*/ height_;
-        unsigned int         /*const*/ stride_;
-        unsigned int         /*const*/ pixel_size_;
-        BYTE               * /*const*/ p_buffer_;
-        format_t                   format_;
-
-    private:
-        template <typename View>
-        void set_bitmapdata_for_view( View const & view )
+        if ( SUCCEEDED( hr ) )
         {
-            width_      = view.width();
-            height_     = view.height();
-            stride_     = view.pixels().row_size();
-            pixel_size_ = memunit_step( typename View::x_iterator() );
-            //format_     = view_wic_format::apply<View>::value;
-            p_buffer_   = formatted_image_base::get_raw_data( view );
+            hr = frame().WritePixels( view_data.height_, view_data.stride_, view_data.height_ * view_data.stride_, view_data.p_buffer_ );
         }
 
-        void operator=( view_data_t const & );
+        if ( SUCCEEDED( hr ) )
+        {
+            hr = frame().Commit();
+        }
 
-    private:
-        aligned_storage<sizeof( wic_roi ), alignment_of<wic_roi>::value>::type optional_roi_;
-    };
+        if ( SUCCEEDED( hr ) )
+        {
+            hr = encoder().Commit();
+        }
 
-    BOOST_STATIC_CONSTANT( unsigned int, desired_alignment  = sizeof( void * ) );
-    BOOST_STATIC_CONSTANT( bool        , builtin_conversion = true             );
-};
+        ensure_result( hr );
+    }
 
+    void write( wic_view_data_t const & view_data ) { write_default( view_data ); }
 
-inline void ensure_result( HRESULT const result )
-{
-    io_error_if( result != S_OK, "WIC failure"/*error_string( result )*/ );
-}
+private:
+    void create_encoder( GUID const & format, IStream & target )
+    {
+        ensure_result( wic_factory<>::singleton().CreateEncoder( format, NULL, &lib_object().p_encoder_ ) );
+        ensure_result( lib_object().p_encoder_->Initialize( &target, WICBitmapEncoderNoCache )            );
+        ensure_result( lib_object().p_encoder_->CreateNewFrame( &lib_object().p_frame_, &lib_object().p_frame_parameters_ ) );
+    }
 
-inline void verify_result( HRESULT const result )
-{
-    BOOST_VERIFY( result == S_OK );
-}
+    IWICBitmapFrameEncode & frame  () { return *lib_object().p_frame_  ; }
+    IWICBitmapEncoder     & encoder() { return *lib_object().p_encoder_; }
+    
+private:
+    lib_object_t lib_object_;
+};
 
 //------------------------------------------------------------------------------
 } // namespace detail
 
+class wic_image;
+
+template <>
+struct formatted_image_traits<wic_image>
+{
+    typedef detail::wic_format_t format_t;
+
+    typedef detail::wic_supported_pixel_formats supported_pixel_formats_t;
+
+    typedef detail::wic_roi roi_t;
+
+    typedef detail::view_wic_format view_to_native_format;
+
+    template <class View>
+    struct is_supported
+        :
+        mpl::not_
+        <
+            is_same
+            <
+                typename view_to_native_format::apply<View>::type,
+                //format_guid<wic_format                  >,
+                detail::format_guid<GUID_WICPixelFormatUndefined>
+            >
+        > {};
+
+    typedef mpl::map6
+    <
+        mpl::pair<char                    const *,                                                    wic_image  >,
+        mpl::pair<wchar_t                 const *,                                                    wic_image  >,
+        mpl::pair<HANDLE                         ,                                                    wic_image  >,
+        mpl::pair<IStream                       &,                                                    wic_image  >,
+        mpl::pair<FILE                          &, detail::input_FILE_for_IStream_extender           <wic_image> >,
+        mpl::pair<writable_memory_chunk_t const &, detail::writable_memory_chunk_for_IStream_extender<wic_image> >
+    > readers;
+
+    typedef mpl::map4
+    <
+        mpl::pair<char           const *,  detail::output_c_str_for_c_file_extender<detail::output_FILE_for_IStream_extender <detail::wic_writer> > >,
+        //mpl::pair<wchar_t        const *,                                           wic_image  >,
+        mpl::pair<IStream              &,                                           detail::wic_writer  >,
+        mpl::pair<FILE                 &, detail::output_FILE_for_IStream_extender <detail::wic_writer> >,
+        mpl::pair<memory_chunk_t const &, detail::memory_chunk_for_IStream_extender<detail::wic_writer> >
+    > writers;
+
+    typedef detail::wic_view_data_t view_data_t       ;
+    typedef view_data_t             writer_view_data_t;
+
+    BOOST_STATIC_CONSTANT( unsigned int, desired_alignment  = sizeof( void * ) );
+    BOOST_STATIC_CONSTANT( bool        , builtin_conversion = true             );
+    BOOST_STATIC_CONSTANT( bool        , writers_need_source_first = true      );
+};
 
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -239,9 +334,9 @@
 public:
     // Implementation note:
     //   The IWICBitmapDecoder instance is not otherwise necessary once an
-    // IWICBitmapDecoder is created but we keep it here and make it accessible
-    // to the user to enable the use of multi frame/page/picture formats like
-    // GIF and TIFF.
+    // IWICBitmapFrameDecode instance is created but we keep it here and make it
+    // accessible to the user to enable the use of multi frame/page/picture
+    // formats like GIF and TIFF.
     //                                        (26.07.2010.) (Domagoj Saric)
     typedef std::pair
             <
@@ -249,7 +344,7 @@
                 CComPtr<IWICBitmapDecoder    >
             > lib_object_t;
 
-    typedef detail::wic_user_guard guard_t;
+    typedef detail::wic_user_guard guard;
 
 public:
     explicit wic_image( wchar_t const * const filename )
@@ -305,8 +400,9 @@
     point2<std::ptrdiff_t> dimensions() const
     {
         using namespace detail;
-        aligned_storage<sizeof( wic_roi ), alignment_of<wic_roi>::value>::type placeholder;
-        point2<std::ptrdiff_t> & result( *gil_reinterpret_cast<point2<std::ptrdiff_t> *>( placeholder.address() ) );
+        typedef point2<std::ptrdiff_t> result_t;
+        aligned_storage<sizeof( result_t ), alignment_of<result_t>::value>::type placeholder;
+        result_t & result( *gil_reinterpret_cast<result_t *>( placeholder.address() ) );
         verify_result( frame_decoder().GetSize( gil_reinterpret_cast<UINT *>( &result.x ), gil_reinterpret_cast<UINT *>( &result.y ) ) );
         return result;
     }
@@ -349,7 +445,6 @@
     void generic_convert_to_prepared_view( TargetView const & view, Converter const & converter ) const
     {
         BOOST_ASSERT( !dimensions_mismatch( view ) );
-        //BOOST_ASSERT( !formats_mismatch   ( view ) );
 
         using namespace detail;
 
@@ -385,7 +480,7 @@
     }
 
 
-    void raw_convert_to_prepared_view( detail::formatted_image_traits<wic_image>::view_data_t const & view_data ) const
+    void raw_convert_to_prepared_view( view_data_t const & view_data ) const
     {
         BOOST_ASSERT( view_data.format_ != GUID_WICPixelFormatUndefined ); //...zzz...
         using namespace detail;
@@ -405,7 +500,7 @@
     }
 
 
-    void raw_copy_to_prepared_view( detail::formatted_image_traits<wic_image>::view_data_t const & view_data ) const
+    void raw_copy_to_prepared_view( view_data_t const & view_data ) const
     {
         detail::ensure_result
         (