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