Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:36:57

0001 //
0002 // Copyright 2012 Christian Henning
0003 //
0004 // Distributed under the Boost Software License, Version 1.0
0005 // See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt
0007 //
0008 #ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_WRITER_BACKEND_HPP
0009 #define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_WRITER_BACKEND_HPP
0010 
0011 #include <boost/gil/extension/io/jpeg/tags.hpp>
0012 #include <boost/gil/extension/io/jpeg/detail/base.hpp>
0013 
0014 #include <memory>
0015 
0016 namespace boost { namespace gil {
0017 
0018 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0019 #pragma warning(push)
0020 #pragma warning(disable:4512) //assignment operator could not be generated
0021 #pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
0022 #endif
0023 
0024 namespace detail {
0025 
0026 ///
0027 /// Wrapper for libjpeg's compress object. Implements value semantics.
0028 ///
0029 struct jpeg_compress_wrapper
0030 {
0031 protected:
0032 
0033     using jpeg_compress_ptr_t = std::shared_ptr<jpeg_compress_struct>;
0034 
0035 protected:
0036 
0037     ///
0038     /// Default Constructor
0039     ///
0040     jpeg_compress_wrapper()
0041     : _jpeg_compress_ptr( new jpeg_compress_struct()
0042                         , jpeg_compress_deleter
0043                         )
0044     {}
0045 
0046     jpeg_compress_struct*       get()       { return _jpeg_compress_ptr.get(); }
0047     const jpeg_compress_struct* get() const { return _jpeg_compress_ptr.get(); }
0048 
0049 private:
0050 
0051     static void jpeg_compress_deleter( jpeg_compress_struct* jpeg_compress_ptr )
0052     {
0053         if( jpeg_compress_ptr )
0054         {
0055             jpeg_destroy_compress( jpeg_compress_ptr );
0056 
0057             delete jpeg_compress_ptr;
0058             jpeg_compress_ptr = nullptr;
0059         }
0060     }
0061 
0062 private:
0063 
0064    jpeg_compress_ptr_t _jpeg_compress_ptr;
0065 
0066 };
0067 
0068 } // namespace detail
0069 
0070 ///
0071 /// JPEG Writer Backend
0072 ///
0073 template< typename Device >
0074 struct writer_backend< Device
0075                      , jpeg_tag
0076                      >
0077     : public jpeg_io_base
0078     , public detail::jpeg_compress_wrapper
0079 {
0080 public:
0081 
0082     using format_tag_t = jpeg_tag;
0083 
0084 public:
0085     ///
0086     /// Constructor
0087     ///
0088     writer_backend( const Device&                       io_dev
0089                   , const image_write_info< jpeg_tag >& info
0090                   )
0091     : _io_dev( io_dev )
0092     , _info( info )
0093     {
0094         get()->err         = jpeg_std_error( &_jerr );
0095         get()->client_data = this;
0096 
0097         // Error exit handler: does not return to caller.
0098         _jerr.error_exit = &writer_backend< Device, jpeg_tag >::error_exit;
0099 
0100         // Fire exception in case of error.
0101         if( setjmp( _mark )) { raise_error(); }
0102 
0103         _dest._jdest.free_in_buffer      = sizeof( buffer );
0104         _dest._jdest.next_output_byte    = buffer;
0105         _dest._jdest.init_destination    = reinterpret_cast< void(*)   ( j_compress_ptr ) >( &writer_backend< Device, jpeg_tag >::init_device  );
0106         _dest._jdest.empty_output_buffer = reinterpret_cast< boolean(*)( j_compress_ptr ) >( &writer_backend< Device, jpeg_tag >::empty_buffer );
0107         _dest._jdest.term_destination    = reinterpret_cast< void(*)   ( j_compress_ptr ) >( &writer_backend< Device, jpeg_tag >::close_device );
0108         _dest._this = this;
0109 
0110         jpeg_create_compress( get() );
0111         get()->dest = &_dest._jdest;
0112     }
0113 
0114     ~writer_backend()
0115     {
0116         // JPEG compression object destruction does not signal errors,
0117         // unlike jpeg_finish_compress called elsewhere,
0118         // so there is no need for the setjmp bookmark here.
0119         jpeg_destroy_compress( get() );
0120     }
0121 
0122 protected:
0123 
0124     struct gil_jpeg_destination_mgr
0125     {
0126         jpeg_destination_mgr _jdest;
0127         writer_backend< Device
0128                       , jpeg_tag
0129                       >* _this;
0130     };
0131 
0132     static void init_device( jpeg_compress_struct* cinfo )
0133     {
0134         gil_jpeg_destination_mgr* dest = reinterpret_cast< gil_jpeg_destination_mgr* >( cinfo->dest );
0135 
0136         dest->_jdest.free_in_buffer   = sizeof( dest->_this->buffer );
0137         dest->_jdest.next_output_byte = dest->_this->buffer;
0138     }
0139 
0140     static boolean empty_buffer( jpeg_compress_struct* cinfo )
0141     {
0142         gil_jpeg_destination_mgr* dest = reinterpret_cast< gil_jpeg_destination_mgr* >( cinfo->dest );
0143 
0144         dest->_this->_io_dev.write( dest->_this->buffer
0145                                   , buffer_size
0146                                   );
0147 
0148         writer_backend<Device,jpeg_tag>::init_device( cinfo );
0149         return static_cast<boolean>(TRUE);
0150     }
0151 
0152     static void close_device( jpeg_compress_struct* cinfo )
0153     {
0154         writer_backend< Device
0155                       , jpeg_tag
0156                       >::empty_buffer( cinfo );
0157 
0158         gil_jpeg_destination_mgr* dest = reinterpret_cast< gil_jpeg_destination_mgr* >( cinfo->dest );
0159 
0160         dest->_this->_io_dev.flush();
0161     }
0162 
0163     void raise_error()
0164     {
0165         io_error( "Cannot write jpeg file." );
0166     }
0167 
0168     static void error_exit( j_common_ptr cinfo )
0169     {
0170         writer_backend< Device, jpeg_tag >* mgr = reinterpret_cast< writer_backend< Device, jpeg_tag >* >( cinfo->client_data );
0171 
0172         longjmp( mgr->_mark, 1 );
0173     }
0174 
0175 public:
0176 
0177     Device _io_dev;
0178 
0179     image_write_info< jpeg_tag > _info;
0180 
0181     gil_jpeg_destination_mgr _dest;
0182 
0183     static const unsigned int buffer_size = 1024;
0184     JOCTET buffer[buffer_size];
0185 };
0186 
0187 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0188 #pragma warning(pop)
0189 #endif
0190 
0191 } // namespace gil
0192 } // namespace boost
0193 
0194 #endif