jpeg_io_private.hppGo to the documentation of this file.00001 /* 00002 Copyright 2005-2007 Adobe Systems Incorporated 00003 00004 Use, modification and distribution are subject to the Boost Software License, 00005 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 00006 http://www.boost.org/LICENSE_1_0.txt). 00007 00008 See http://opensource.adobe.com/gil for most recent version including documentation. 00009 */ 00010 00011 /*************************************************************************************************/ 00012 00013 #ifndef GIL_JPEG_IO_PRIVATE_H 00014 #define GIL_JPEG_IO_PRIVATE_H 00015 00021 00022 #include <stdio.h> 00023 #include <boost/static_assert.hpp> 00024 #include <vector> 00025 #include "../../gil_all.hpp" 00026 #include "io_error.hpp" 00027 00028 namespace boost { namespace gil { 00029 00030 namespace detail { 00031 00032 // lbourdev: What is the advantage of having channel and colorspace together? Are there cases where they are interrelated? 00033 00034 template <typename Channel,typename ColorSpace> 00035 struct jpeg_read_support_private { 00036 BOOST_STATIC_CONSTANT(bool,is_supported=false); 00037 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_UNKNOWN); 00038 }; 00039 template <> 00040 struct jpeg_read_support_private<bits8,gray_t> { 00041 BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8); 00042 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00043 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_GRAYSCALE); 00044 }; 00045 template <> 00046 struct jpeg_read_support_private<bits8,rgb_t> { 00047 BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8); 00048 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00049 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_RGB); 00050 }; 00051 template <> 00052 struct jpeg_read_support_private<bits8,cmyk_t> { 00053 BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8); 00054 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00055 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_CMYK); 00056 }; 00057 template <typename Channel,typename ColorSpace> 00058 struct jpeg_write_support_private { 00059 BOOST_STATIC_CONSTANT(bool,is_supported=false); 00060 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_UNKNOWN); 00061 }; 00062 template <> 00063 struct jpeg_write_support_private<bits8,gray_t> { 00064 BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8); 00065 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00066 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_GRAYSCALE); 00067 }; 00068 template <> 00069 struct jpeg_write_support_private<bits8,rgb_t> { 00070 BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8); 00071 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00072 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_RGB); 00073 }; 00074 template <> 00075 struct jpeg_write_support_private<bits8,cmyk_t> { 00076 BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8); 00077 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00078 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_CMYK); 00079 }; 00080 00081 00082 class jpeg_reader : public file_mgr { 00083 protected: 00084 jpeg_decompress_struct _cinfo; 00085 jpeg_error_mgr _jerr; 00086 00087 void init() { 00088 _cinfo.err=jpeg_std_error(&_jerr); 00089 jpeg_create_decompress(&_cinfo); 00090 jpeg_stdio_src(&_cinfo,_fp.get()); 00091 jpeg_read_header(&_cinfo,TRUE); 00092 } 00093 public: 00094 jpeg_reader(FILE* file) : file_mgr(file) { init(); } 00095 jpeg_reader(const char* filename) : file_mgr(filename, "rb") { init(); } 00096 00097 ~jpeg_reader() { jpeg_destroy_decompress(&_cinfo); } 00098 00099 template <typename View> 00100 void apply(const View& view) { 00101 jpeg_start_decompress(&_cinfo); // lbourdev: Can this return an error? You need to check and throw. Check all other library methods that can return an error state... 00102 io_error_if(_cinfo.data_precision!=8,"jpeg_reader::apply(): this image file is not supported"); 00103 io_error_if(_cinfo.out_color_space!=jpeg_read_support_private<typename channel_type<View>::type, 00104 typename color_space_type<View>::type>::color_type, 00105 "jpeg_reader::apply(): input view type does not match the image file"); 00106 io_error_if(view.dimensions() != get_dimensions(), "jpeg_reader::apply(): input view dimensions do not match the image file"); 00107 std::vector<pixel<bits8,layout<typename color_space_type<View>::type> > > row(view.width()); 00108 JSAMPLE* row_address=(JSAMPLE*)&row.front(); 00109 for(int y=0;y<view.height();++y) { 00110 io_error_if(jpeg_read_scanlines(&_cinfo,(JSAMPARRAY)&row_address,1)!=1, 00111 "jpeg_reader::apply(): fail to read JPEG file"); 00112 std::copy(row.begin(),row.end(),view.row_begin(y)); 00113 } 00114 jpeg_finish_decompress(&_cinfo); 00115 } 00116 00117 template <typename Image> 00118 void read_image(Image& im) { 00119 im.recreate(get_dimensions()); 00120 apply(view(im)); 00121 } 00122 00123 point2<std::ptrdiff_t> get_dimensions() const { 00124 return point2<std::ptrdiff_t>(_cinfo.image_width,_cinfo.image_height); 00125 } 00126 }; 00127 00128 // This code will be simplified... 00129 template <typename CC> 00130 class jpeg_reader_color_convert : public jpeg_reader { 00131 private: 00132 CC _cc; 00133 public: 00134 jpeg_reader_color_convert(FILE* file,CC cc_in) : jpeg_reader(file),_cc(cc_in) {} 00135 jpeg_reader_color_convert(FILE* file) : jpeg_reader(file) {} 00136 jpeg_reader_color_convert(const char* filename,CC cc_in) : jpeg_reader(filename),_cc(cc_in) {} 00137 jpeg_reader_color_convert(const char* filename) : jpeg_reader(filename) {} 00138 template <typename View> 00139 void apply(const View& view) { 00140 jpeg_start_decompress(&_cinfo); // lbourdev: Can this return an error? You need to check and throw. Check all other library methods that can return an error state... 00141 io_error_if(_cinfo.data_precision!=8,"jpeg_reader_color_covert::apply(): this image file is not supported"); 00142 io_error_if(view.dimensions() != get_dimensions(), "jpeg_reader_color_covert::apply(): input view dimensions don't match the image file"); 00143 switch (_cinfo.out_color_space) { 00144 case JCS_GRAYSCALE: { 00145 std::vector<gray8_pixel_t> row(view.width()); 00146 JSAMPLE* row_address=(JSAMPLE*)&row.front(); 00147 for(int y=0;y<view.height();++y) { 00148 io_error_if(jpeg_read_scanlines(&_cinfo,(JSAMPARRAY)&row_address,1)!=1, 00149 "jpeg_reader_color_covert::apply(): fail to read JPEG file"); 00150 std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<gray8_ref_t, typename View::value_type,CC>(_cc)); 00151 } 00152 break; 00153 } 00154 case JCS_RGB: { 00155 std::vector<rgb8_pixel_t> row(view.width()); 00156 JSAMPLE* row_address=(JSAMPLE*)&row.front(); 00157 for(int y=0;y<view.height();++y) { 00158 io_error_if(jpeg_read_scanlines(&_cinfo,(JSAMPARRAY)&row_address,1)!=1, 00159 "jpeg_reader_color_covert::apply(): fail to read JPEG file"); 00160 std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<rgb8_ref_t, typename View::value_type,CC>(_cc)); 00161 } 00162 break; 00163 } 00164 case JCS_CMYK: { 00165 std::vector<cmyk8_pixel_t> row(view.width()); 00166 JSAMPLE* row_address=(JSAMPLE*)&row.front(); 00167 for(int y=0;y<view.height();++y) { 00168 io_error_if(jpeg_read_scanlines(&_cinfo,(JSAMPARRAY)&row_address,1)!=1, 00169 "jpeg_reader_color_covert::apply(): fail to read JPEG file"); 00170 std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<cmyk8_ref_t, typename View::value_type,CC>(_cc)); 00171 } 00172 break; 00173 } 00174 default: 00175 io_error("jpeg_reader_color_covert::apply(): unknown color type"); 00176 } 00177 jpeg_finish_decompress(&_cinfo); 00178 } 00179 template <typename Image> 00180 void read_image(Image& im) { 00181 im.recreate(get_dimensions()); 00182 apply(view(im)); 00183 } 00184 }; 00185 00186 class jpeg_writer : public file_mgr { 00187 jpeg_compress_struct _cinfo; 00188 jpeg_error_mgr _jerr; 00189 00190 void init() { 00191 _cinfo.err=jpeg_std_error(&_jerr); 00192 jpeg_create_compress(&_cinfo); 00193 jpeg_stdio_dest(&_cinfo,_fp.get()); 00194 } 00195 public: 00196 jpeg_writer(FILE* file) : file_mgr(file) { init(); } 00197 jpeg_writer(const char* filename) : file_mgr(filename, "wb") { init(); } 00198 ~jpeg_writer() { jpeg_destroy_compress(&_cinfo); } 00199 00200 template <typename View> 00201 void apply(const View& view,int quality=100) { 00202 _cinfo.image_width = (JDIMENSION)view.width(); 00203 _cinfo.image_height = (JDIMENSION)view.height(); 00204 _cinfo.input_components=num_channels<View>::value; 00205 _cinfo.in_color_space = jpeg_write_support_private<typename channel_type<View>::type, 00206 typename color_space_type<View>::type>::color_type; 00207 jpeg_set_defaults(&_cinfo); 00208 jpeg_set_quality(&_cinfo, quality, TRUE); 00209 jpeg_start_compress(&_cinfo, TRUE); 00210 std::vector<pixel<bits8,layout<typename color_space_type<View>::type> > > row(view.width()); 00211 JSAMPLE* row_address=(JSAMPLE*)&row.front(); 00212 for (int y=0;y<view.height(); ++y) { 00213 std::copy(view.row_begin(y),view.row_end(y),row.begin()); 00214 io_error_if(jpeg_write_scanlines(&_cinfo,(JSAMPARRAY)&row_address,1) != 1, 00215 "jpeg_writer::apply(): fail to write file"); 00216 } 00217 jpeg_finish_compress(&_cinfo); 00218 } 00219 }; 00220 00221 } // namespace detail 00222 00223 } } // namespace boost::gil 00224 00225 #endif Generated on Thu Nov 8 21:53:17 2007 for Generic Image Library by 1.4.4 |