Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r65366 - in sandbox/gil/boost/gil/extension/io2: . detail
From: dsaritz_at_[hidden]
Date: 2010-09-09 13:53:07


Author: psiha
Date: 2010-09-09 13:53:03 EDT (Thu, 09 Sep 2010)
New Revision: 65366
URL: http://svn.boost.org/trac/boost/changeset/65366

Log:
Added:
 - BOOST_GIL_THROW_THROUGH_C_SUPPORTED support to the LibJPEG backend
 - custom source manager for the LibJPEG backend.
Text files modified:
   sandbox/gil/boost/gil/extension/io2/detail/shared.hpp | 6
   sandbox/gil/boost/gil/extension/io2/libjpeg_image.hpp | 308 +++++++++++++++++++++++++++++++--------
   2 files changed, 245 insertions(+), 69 deletions(-)

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-09 13:53:03 EDT (Thu, 09 Sep 2010)
@@ -35,6 +35,12 @@
     #endif
 #endif
 
+#ifdef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+ #define BOOST_GIL_CAN_THROW throw(...)
+#else
+ #define BOOST_GIL_CAN_THROW
+#endif
+
 //------------------------------------------------------------------------------
 } // 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-09 13:53:03 EDT (Thu, 09 Sep 2010)
@@ -20,6 +20,7 @@
 #include "formatted_image.hpp"
 #include "detail/io_error.hpp"
 #include "detail/libx_shared.hpp"
+#include "detail/shared.hpp"
 
 #include <boost/smart_ptr/scoped_ptr.hpp>
 
@@ -27,7 +28,9 @@
 #include "jpeglib.h"
 #undef JPEG_INTERNALS
 
-#include <csetjmp>
+#ifndef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+ #include <csetjmp>
+#endif // BOOST_GIL_THROW_THROUGH_C_SUPPORTED
 #include <cstdlib>
 //------------------------------------------------------------------------------
 namespace boost
@@ -94,16 +97,20 @@
     libjpeg_base( for_decompressor ) throw(...)
     {
         initialize_error_handler();
- if ( setjmp( error_handler_target() ) )
- throw_jpeg_error();
+ #ifndef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+ if ( setjmp( error_handler_target() ) )
+ throw_jpeg_error();
+ #endif // BOOST_GIL_THROW_THROUGH_C_SUPPORTED
         jpeg_create_decompress( &decompressor() );
     }
 
     libjpeg_base( for_compressor ) throw(...)
     {
         initialize_error_handler();
- if ( setjmp( error_handler_target() ) )
- throw_jpeg_error();
+ #ifndef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+ if ( setjmp( error_handler_target() ) )
+ throw_jpeg_error();
+ #endif // BOOST_GIL_THROW_THROUGH_C_SUPPORTED
         jpeg_create_compress( &compressor() );
     }
 
@@ -111,8 +118,6 @@
 
     void abort() const { jpeg_abort( &mutable_this().common() ); }
 
- jmp_buf & error_handler_target() const { return longjmp_target_; }
-
     jpeg_common_struct & common () { return *gil_reinterpret_cast<j_common_ptr>( &libjpeg_object.compressor_ ); }
     jpeg_common_struct const & common () const { return const_cast<libjpeg_base &>( *this ).common (); }
     jpeg_compress_struct & compressor () { return libjpeg_object.compressor_ ; }
@@ -128,16 +133,23 @@
         return *static_cast<libjpeg_base *>( gil_reinterpret_cast<libjpeg_object_wrapper_t *>( p_libjpeg_object ) );
     }
 
- __declspec( noreturn )
- static void throw_jpeg_error() throw(...)
+ #ifndef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+ jmp_buf & error_handler_target() const { return longjmp_target_; }
+ #endif // BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+
+ static void fatal_error_handler( j_common_ptr const p_cinfo )
     {
- io_error( "jpeg error" );
+ #ifdef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+ throw_jpeg_error();
+ ignore_unused_variable_warning( p_cinfo );
+ #else
+ longjmp( base( p_cinfo ).error_handler_target(), 1 );
+ #endif // BOOST_GIL_THROW_THROUGH_C_SUPPORTED
     }
 
- __declspec( noreturn )
- static inline void libX_fatal_error_handler( j_common_ptr const p_cinfo )
+ static void throw_jpeg_error()
     {
- longjmp( base( p_cinfo ).error_handler_target(), 1 );
+ io_error( "LibJPEG error" );
     }
 
 private:
@@ -163,7 +175,7 @@
             p_cinfo->err->output_message( p_cinfo );
         #endif
 
- libX_fatal_error_handler( p_cinfo );
+ fatal_error_handler( p_cinfo );
     }
 
     static void __cdecl output_message( j_common_ptr /*p_cinfo*/ ) {}
@@ -178,9 +190,9 @@
     }
 
 private:
- //#ifndef BOOST_MSVC
- mutable jmp_buf longjmp_target_;
- //#endif // BOOST_MSVC
+ #ifndef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+ mutable jmp_buf longjmp_target_;
+ #endif // BOOST_GIL_THROW_THROUGH_C_SUPPORTED
 
     jpeg_error_mgr jerr_ ;
 };
@@ -234,7 +246,6 @@
         setup_destination( p_target_file_name );
     }
 
-
     ~libjpeg_writer()
     {
         jpeg_finish_compress( &compressor() );
@@ -248,26 +259,42 @@
         BOOST_ASSERT( view.format_ != JCS_UNKNOWN );
 
         libjpeg_writer writer( p_target_file_name );
+
+ #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_;
- jpeg_set_defaults ( &writer.compressor() );
- //jpeg_set_quality ( &writer.compressor(), 100, false );
- jpeg_start_compress( &writer.compressor(), false );
+
+ writer.setup_compression();
 
         JSAMPLE * p_row( view.buffer_ );
         JSAMPLE * const p_end( memunit_advanced( view.buffer_, view.height_ * view.stride_ ) );
         while ( p_row < p_end )
         {
- io_error_if( jpeg_write_scanlines( &writer.compressor(), &p_row, 1 ) != 1 );
+ writer.write_row( p_row );
             memunit_advance( p_row, view.stride_ );
         }
     }
 
 private:
- static libjpeg_writer & writer( j_compress_ptr const p_cinfo )
+ 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 );
+ }
+
+ static libjpeg_writer & writer( j_compress_ptr const p_cinfo )
     {
         libjpeg_writer & writer( static_cast<libjpeg_writer &>( base( gil_reinterpret_cast<j_common_ptr>( p_cinfo ) ) ) );
         BOOST_ASSERT( p_cinfo->dest == &writer.destination_manager_ );
@@ -323,7 +350,7 @@
                 static_cast<FILE *>( compressor().client_data )
             ) != 1
         )
- libX_fatal_error_handler( &common() );
+ fatal_error_handler( &common() );
     }
     
     static boolean __cdecl empty_FILE_buffer( j_compress_ptr const p_cinfo )
@@ -343,6 +370,7 @@
         writer.write_FILE_bytes( remaining_bytes );
     }
 
+ // Ensure that jpeg_finish_compress() is called so that this gets called...
     static void __cdecl term_and_close_FILE_destination( j_compress_ptr const p_cinfo )
     {
         term_FILE_destination( p_cinfo );
@@ -442,7 +470,8 @@
                 return 1;
 
             default:
- BOOST_ASSERT( !"Invalid or unknown format specified." ); __assume( false );
+ BOOST_ASSERT( !"Invalid or unknown format specified." );
+ __assume( false );
                 return 0;
         }
     }
@@ -456,24 +485,36 @@
     // return decompressor().output_components;
     //}
 
-
 public: /// \ingroup Construction
- explicit libjpeg_image( FILE * const p_file )
+ explicit libjpeg_image( FILE & file )
         :
         libjpeg_base( for_decompressor() )
     {
- BOOST_ASSERT( p_file );
+ #ifndef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+ if ( setjmp( error_handler_target() ) )
+ throw_jpeg_error();
+ #endif // BOOST_GIL_THROW_THROUGH_C_SUPPORTED
 
- if ( setjmp( error_handler_target() ) )
- throw_jpeg_error();
+ setup_source( file );
 
- jpeg_stdio_src( &decompressor(), p_file );
+ read_header();
+ }
 
- BOOST_VERIFY( jpeg_read_header( &decompressor(), true ) == JPEG_HEADER_OK );
+ explicit libjpeg_image( char const * const file_name )
+ :
+ libjpeg_base( for_decompressor() )
+ {
+ BOOST_ASSERT( file_name );
 
- io_error_if( decompressor().data_precision != 8, "Unsupported image file data precision." );
- }
+ #ifndef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+ if ( setjmp( error_handler_target() ) )
+ throw_jpeg_error();
+ #endif // BOOST_GIL_THROW_THROUGH_C_SUPPORTED
 
+ setup_source( file_name );
+
+ read_header();
+ }
 
 public:
     point2<std::ptrdiff_t> dimensions() const
@@ -490,8 +531,10 @@
     {
         setup_decompression( view_data );
 
- if ( setjmp( error_handler_target() ) )
- throw_jpeg_error();
+ #ifndef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+ if ( setjmp( error_handler_target() ) )
+ throw_jpeg_error();
+ #endif // BOOST_GIL_THROW_THROUGH_C_SUPPORTED
 
         JSAMPROW scanlines[ 4 ] =
         {
@@ -508,9 +551,8 @@
             BOOST_ASSERT( scanlines_to_read <= ( decompressor().output_height - decompressor().output_scanline ) );
             unsigned int const lines_read
             (
- jpeg_read_scanlines
+ read_scanlines
                 (
- &mutable_this().decompressor(),
                     scanlines,
                     (std::min)( _countof( scanlines ), scanlines_to_read )
                 )
@@ -549,21 +591,15 @@
         BOOST_ASSERT( decompressor().output_width == decompressor().image_width );
         BOOST_ASSERT( decompressor().output_components == decompressor().num_components );
         
- if ( setjmp( error_handler_target() ) )
- throw_jpeg_error();
+ #ifndef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+ if ( setjmp( error_handler_target() ) )
+ throw_jpeg_error();
+ #endif // BOOST_GIL_THROW_THROUGH_C_SUPPORTED
 
         unsigned int const scanlines_to_read( detail::original_view( view ).dimensions().y );
         for ( unsigned int scanline_index( 0 ); scanline_index < scanlines_to_read; ++scanline_index )
         {
- BOOST_VERIFY
- (
- jpeg_read_scanlines
- (
- &mutable_this().decompressor(),
- &scanline,
- 1
- ) == 1
- );
+ read_scanline( scanline );
 
             pixel_t const * p_source_pixel( gil_reinterpret_cast_c<pixel_t const *>( scanline ) );
             typename TargetView::x_iterator p_target_pixel( view.row_begin( scanline_index ) );
@@ -602,8 +638,10 @@
                 ( state == DSTATE_SCANNING )
             );
 
- if ( setjmp( error_handler_target() ) )
- throw_jpeg_error();
+ #ifndef BOOST_GIL_THROW_THROUGH_C_SUPPORTED
+ if ( setjmp( error_handler_target() ) )
+ throw_jpeg_error();
+ #endif // BOOST_GIL_THROW_THROUGH_C_SUPPORTED
 
             if ( state == DSTATE_SCANNING )
                 abort();
@@ -651,15 +689,7 @@
         while ( number_of_rows_to_skip_using_raw )
         {
             unsigned int const lines_to_read( _countof( dummy_component_2d_array ) );
- BOOST_VERIFY
- (
- jpeg_read_raw_data
- (
- &mutable_this().decompressor(),
- dummy_scan_lines,
- lines_to_read
- ) == lines_to_read
- );
+ read_raw_data( dummy_scan_lines, lines_to_read );
             number_of_rows_to_skip_using_raw -= lines_to_read;
         }
 
@@ -667,23 +697,163 @@
         mutable_this().decompressor().global_state = DSTATE_SCANNING;
         while ( number_of_rows_to_skip_using_scanlines-- )
         {
- BOOST_VERIFY
- (
- jpeg_read_scanlines
- (
- &mutable_this().decompressor(),
- &dummy_scanline_buffer,
- 1
- ) == 1
- );
+ read_scanline( dummy_scanline_buffer );
         }
     }
 
+ unsigned int read_scanlines( JSAMPROW scanlines[], unsigned int const scanlines_to_read ) const BOOST_GIL_CAN_THROW
+ {
+ return jpeg_read_scanlines
+ (
+ &mutable_this().decompressor(),
+ scanlines,
+ scanlines_to_read
+ );
+ }
+
+ void read_scanline( JSAMPROW scanline ) const BOOST_GIL_CAN_THROW
+ {
+ BOOST_VERIFY
+ (
+ read_scanlines( &scanline, 1 ) == 1
+ );
+ }
+
+ void read_raw_data( JSAMPARRAY scanlines[], unsigned int const scanlines_to_read ) const BOOST_GIL_CAN_THROW
+ {
+ BOOST_VERIFY
+ (
+ jpeg_read_raw_data
+ (
+ &mutable_this().decompressor(),
+ scanlines,
+ scanlines_to_read
+ ) == scanlines_to_read
+ );
+ }
+
     libjpeg_image & mutable_this() const { return static_cast<libjpeg_image &>( libjpeg_base::mutable_this() ); }
 
 private:
     friend class libjpeg_view_base;
 
+ void read_header()
+ {
+ BOOST_VERIFY( jpeg_read_header( &decompressor(), true ) == JPEG_HEADER_OK );
+
+ io_error_if( decompressor().data_precision != 8, "Unsupported image file data precision." );
+ }
+
+ // Unextracted "libjpeg_reader" interface.
+ void setup_source()
+ {
+ source_manager_.next_input_byte = read_buffer_.begin();
+ source_manager_.bytes_in_buffer = 0;
+
+ BOOST_ASSERT( decompressor().src == NULL );
+ decompressor().src = &source_manager_;
+ }
+
+ void setup_source( FILE & file )
+ {
+ setup_source();
+
+ decompressor().client_data = &file;
+
+ source_manager_.init_source = &init_FILE_source ;
+ source_manager_.fill_input_buffer = &fill_FILE_buffer ;
+ source_manager_.skip_input_data = &skip_FILE_data ;
+ source_manager_.resync_to_restart = &jpeg_resync_to_restart;
+ source_manager_.term_source = &term_FILE_source ;
+ }
+
+ void setup_source( char const * const p_file_name )
+ {
+ FILE * const p_file( /*std*/::fopen( p_file_name, "rb" ) );
+ if ( !p_file )
+ throw_jpeg_error();
+ setup_source( *p_file );
+ source_manager_.term_source = &term_and_close_FILE_source;
+ }
+
+ static void __cdecl init_FILE_source( j_decompress_ptr const p_cinfo )
+ {
+ libjpeg_image & reader( reader( p_cinfo ) );
+
+ reader.source_manager_.next_input_byte = reader.read_buffer_.begin();
+ reader.source_manager_.bytes_in_buffer = 0;
+ }
+
+ static boolean __cdecl fill_FILE_buffer( j_decompress_ptr const p_cinfo )
+ {
+ libjpeg_image & reader( reader( p_cinfo ) );
+
+ std::size_t bytes_read
+ (
+ /*std*/::fread
+ (
+ reader.read_buffer_.begin(),
+ 1,
+ reader.read_buffer_.size(),
+ static_cast<FILE *>( reader.decompressor().client_data )
+ )
+ );
+
+ if ( bytes_read == 0 )
+ {
+ // Insert a fake EOI marker (see the comment for the default library
+ // implementation).
+ reader.read_buffer_[ 0 ] = 0xFF;
+ reader.read_buffer_[ 1 ] = JPEG_EOI;
+
+ bytes_read = 2;
+ }
+
+ reader.source_manager_.next_input_byte = reader.read_buffer_.begin();
+ reader.source_manager_.bytes_in_buffer = bytes_read;
+
+ return true;
+ }
+
+ static void __cdecl skip_FILE_data( j_decompress_ptr const p_cinfo, long num_bytes )
+ {
+ libjpeg_image & reader( reader( p_cinfo ) );
+
+ if ( static_cast<std::size_t>( num_bytes ) <= reader.source_manager_.bytes_in_buffer )
+ {
+ reader.source_manager_.next_input_byte += num_bytes;
+ reader.source_manager_.bytes_in_buffer -= num_bytes;
+ }
+ else
+ {
+ num_bytes -= reader.source_manager_.bytes_in_buffer;
+ /*std*/::fseek( static_cast<FILE *>( reader.decompressor().client_data ), num_bytes, SEEK_CUR ); //...failure?
+ reader.source_manager_.next_input_byte = 0;
+ reader.source_manager_.bytes_in_buffer = 0;
+ }
+ }
+
+ static void __cdecl term_FILE_source( j_decompress_ptr /*p_cinfo*/ )
+ {
+ }
+
+ // Ensure that jpeg_finish_decompress() is called so that this gets called...
+ static void __cdecl term_and_close_FILE_source( j_decompress_ptr const p_cinfo )
+ {
+ term_FILE_source( p_cinfo );
+ BOOST_VERIFY( /*std*/::fclose( static_cast<FILE *>( reader( p_cinfo ).decompressor().client_data ) ) == 0 );
+ }
+
+ static libjpeg_image & reader( j_decompress_ptr const p_cinfo )
+ {
+ libjpeg_image & reader( static_cast<libjpeg_image &>( base( gil_reinterpret_cast<j_common_ptr>( p_cinfo ) ) ) );
+ BOOST_ASSERT( p_cinfo->src == &reader.source_manager_ );
+ return reader;
+ }
+
+private:
+ jpeg_source_mgr source_manager_;
+ array<JOCTET, 4096> read_buffer_ ;
 };
 
 #if defined(BOOST_MSVC)


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