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 
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

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google