jpeg_io_private.hpp

Go 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  doxygen 1.5.6