File indexing completed on 2025-01-18 09:36:57
0001
0002
0003
0004
0005
0006
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)
0021 #pragma warning(disable:4611)
0022 #endif
0023
0024 namespace detail {
0025
0026
0027
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
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 }
0069
0070
0071
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
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
0098 _jerr.error_exit = &writer_backend< Device, jpeg_tag >::error_exit;
0099
0100
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
0117
0118
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 }
0192 }
0193
0194 #endif