|
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