annotate DEPENDENCIES/generic/include/boost/gil/extension/io/jpeg_io_private.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 /*
Chris@16 2 Copyright 2005-2007 Adobe Systems Incorporated
Chris@16 3
Chris@16 4 Use, modification and distribution are subject to the Boost Software License,
Chris@16 5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 6 http://www.boost.org/LICENSE_1_0.txt).
Chris@16 7
Chris@16 8 See http://opensource.adobe.com/gil for most recent version including documentation.
Chris@16 9 */
Chris@16 10
Chris@16 11 /*************************************************************************************************/
Chris@16 12
Chris@16 13 #ifndef GIL_JPEG_IO_PRIVATE_H
Chris@16 14 #define GIL_JPEG_IO_PRIVATE_H
Chris@16 15
Chris@16 16 /// \file
Chris@16 17 /// \brief Internal support for reading and writing JPEG files
Chris@16 18 /// \author Hailin Jin and Lubomir Bourdev \n
Chris@16 19 /// Adobe Systems Incorporated
Chris@16 20 /// \date 2005-2007 \n Last updated September 24, 2006
Chris@16 21
Chris@16 22 #include <stdio.h>
Chris@16 23 #include <boost/static_assert.hpp>
Chris@16 24 #include <vector>
Chris@16 25 #include "../../gil_all.hpp"
Chris@16 26 #include "io_error.hpp"
Chris@16 27 #include <jpeglib.h>
Chris@16 28
Chris@16 29 namespace boost { namespace gil {
Chris@16 30
Chris@16 31 namespace detail {
Chris@16 32
Chris@16 33 // lbourdev: What is the advantage of having channel and colorspace together? Are there cases where they are interrelated?
Chris@16 34
Chris@16 35 template <typename Channel,typename ColorSpace>
Chris@16 36 struct jpeg_read_support_private {
Chris@16 37 BOOST_STATIC_CONSTANT(bool,is_supported=false);
Chris@16 38 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_UNKNOWN);
Chris@16 39 };
Chris@16 40 template <>
Chris@16 41 struct jpeg_read_support_private<bits8,gray_t> {
Chris@16 42 BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8);
Chris@16 43 BOOST_STATIC_CONSTANT(bool,is_supported=true);
Chris@16 44 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_GRAYSCALE);
Chris@16 45 };
Chris@16 46 template <>
Chris@16 47 struct jpeg_read_support_private<bits8,rgb_t> {
Chris@16 48 BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8);
Chris@16 49 BOOST_STATIC_CONSTANT(bool,is_supported=true);
Chris@16 50 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_RGB);
Chris@16 51 };
Chris@16 52 template <>
Chris@16 53 struct jpeg_read_support_private<bits8,cmyk_t> {
Chris@16 54 BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8);
Chris@16 55 BOOST_STATIC_CONSTANT(bool,is_supported=true);
Chris@16 56 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_CMYK);
Chris@16 57 };
Chris@16 58 template <typename Channel,typename ColorSpace>
Chris@16 59 struct jpeg_write_support_private {
Chris@16 60 BOOST_STATIC_CONSTANT(bool,is_supported=false);
Chris@16 61 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_UNKNOWN);
Chris@16 62 };
Chris@16 63 template <>
Chris@16 64 struct jpeg_write_support_private<bits8,gray_t> {
Chris@16 65 BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8);
Chris@16 66 BOOST_STATIC_CONSTANT(bool,is_supported=true);
Chris@16 67 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_GRAYSCALE);
Chris@16 68 };
Chris@16 69 template <>
Chris@16 70 struct jpeg_write_support_private<bits8,rgb_t> {
Chris@16 71 BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8);
Chris@16 72 BOOST_STATIC_CONSTANT(bool,is_supported=true);
Chris@16 73 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_RGB);
Chris@16 74 };
Chris@16 75 template <>
Chris@16 76 struct jpeg_write_support_private<bits8,cmyk_t> {
Chris@16 77 BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8);
Chris@16 78 BOOST_STATIC_CONSTANT(bool,is_supported=true);
Chris@16 79 BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_CMYK);
Chris@16 80 };
Chris@16 81
Chris@16 82
Chris@16 83 class jpeg_reader : public file_mgr {
Chris@16 84 protected:
Chris@16 85 jpeg_decompress_struct _cinfo;
Chris@16 86 jpeg_error_mgr _jerr;
Chris@16 87
Chris@16 88 void init() {
Chris@16 89 _cinfo.err=jpeg_std_error(&_jerr);
Chris@16 90 jpeg_create_decompress(&_cinfo);
Chris@16 91 jpeg_stdio_src(&_cinfo,_fp.get());
Chris@16 92 jpeg_read_header(&_cinfo,TRUE);
Chris@16 93 }
Chris@16 94 public:
Chris@16 95 jpeg_reader(FILE* file) : file_mgr(file) { init(); }
Chris@16 96 jpeg_reader(const char* filename) : file_mgr(filename, "rb") { init(); }
Chris@16 97
Chris@16 98 ~jpeg_reader() { jpeg_destroy_decompress(&_cinfo); }
Chris@16 99
Chris@16 100 template <typename View>
Chris@16 101 void apply(const View& view) {
Chris@16 102 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...
Chris@16 103 io_error_if(_cinfo.data_precision!=8,"jpeg_reader::apply(): this image file is not supported");
Chris@16 104 io_error_if(_cinfo.out_color_space!=jpeg_read_support_private<typename channel_type<View>::type,
Chris@16 105 typename color_space_type<View>::type>::color_type,
Chris@16 106 "jpeg_reader::apply(): input view type does not match the image file");
Chris@16 107 io_error_if(view.dimensions() != get_dimensions(), "jpeg_reader::apply(): input view dimensions do not match the image file");
Chris@16 108 std::vector<pixel<bits8,layout<typename color_space_type<View>::type> > > row(view.width());
Chris@16 109 JSAMPLE* row_address=(JSAMPLE*)&row.front();
Chris@16 110 for(int y=0;y<view.height();++y) {
Chris@16 111 io_error_if(jpeg_read_scanlines(&_cinfo,(JSAMPARRAY)&row_address,1)!=1,
Chris@16 112 "jpeg_reader::apply(): fail to read JPEG file");
Chris@16 113 std::copy(row.begin(),row.end(),view.row_begin(y));
Chris@16 114 }
Chris@16 115 jpeg_finish_decompress(&_cinfo);
Chris@16 116 }
Chris@16 117
Chris@16 118 template <typename Image>
Chris@16 119 void read_image(Image& im) {
Chris@16 120 im.recreate(get_dimensions());
Chris@16 121 apply(view(im));
Chris@16 122 }
Chris@16 123
Chris@16 124 point2<std::ptrdiff_t> get_dimensions() const {
Chris@16 125 return point2<std::ptrdiff_t>(_cinfo.image_width,_cinfo.image_height);
Chris@16 126 }
Chris@16 127 };
Chris@16 128
Chris@16 129 // This code will be simplified...
Chris@16 130 template <typename CC>
Chris@16 131 class jpeg_reader_color_convert : public jpeg_reader {
Chris@16 132 private:
Chris@16 133 CC _cc;
Chris@16 134 public:
Chris@16 135 jpeg_reader_color_convert(FILE* file,CC cc_in) : jpeg_reader(file),_cc(cc_in) {}
Chris@16 136 jpeg_reader_color_convert(FILE* file) : jpeg_reader(file) {}
Chris@16 137 jpeg_reader_color_convert(const char* filename,CC cc_in) : jpeg_reader(filename),_cc(cc_in) {}
Chris@16 138 jpeg_reader_color_convert(const char* filename) : jpeg_reader(filename) {}
Chris@16 139 template <typename View>
Chris@16 140 void apply(const View& view) {
Chris@16 141 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...
Chris@16 142 io_error_if(_cinfo.data_precision!=8,"jpeg_reader_color_covert::apply(): this image file is not supported");
Chris@16 143 io_error_if(view.dimensions() != get_dimensions(), "jpeg_reader_color_covert::apply(): input view dimensions don't match the image file");
Chris@16 144 switch (_cinfo.out_color_space) {
Chris@16 145 case JCS_GRAYSCALE: {
Chris@16 146 std::vector<gray8_pixel_t> row(view.width());
Chris@16 147 JSAMPLE* row_address=(JSAMPLE*)&row.front();
Chris@16 148 for(int y=0;y<view.height();++y) {
Chris@16 149 io_error_if(jpeg_read_scanlines(&_cinfo,(JSAMPARRAY)&row_address,1)!=1,
Chris@16 150 "jpeg_reader_color_covert::apply(): fail to read JPEG file");
Chris@16 151 std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<gray8_ref_t, typename View::value_type,CC>(_cc));
Chris@16 152 }
Chris@16 153 break;
Chris@16 154 }
Chris@16 155 case JCS_RGB: {
Chris@16 156 std::vector<rgb8_pixel_t> row(view.width());
Chris@16 157 JSAMPLE* row_address=(JSAMPLE*)&row.front();
Chris@16 158 for(int y=0;y<view.height();++y) {
Chris@16 159 io_error_if(jpeg_read_scanlines(&_cinfo,(JSAMPARRAY)&row_address,1)!=1,
Chris@16 160 "jpeg_reader_color_covert::apply(): fail to read JPEG file");
Chris@16 161 std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<rgb8_ref_t, typename View::value_type,CC>(_cc));
Chris@16 162 }
Chris@16 163 break;
Chris@16 164 }
Chris@16 165 case JCS_CMYK: {
Chris@16 166 std::vector<cmyk8_pixel_t> row(view.width());
Chris@16 167 JSAMPLE* row_address=(JSAMPLE*)&row.front();
Chris@16 168 for(int y=0;y<view.height();++y) {
Chris@16 169 io_error_if(jpeg_read_scanlines(&_cinfo,(JSAMPARRAY)&row_address,1)!=1,
Chris@16 170 "jpeg_reader_color_covert::apply(): fail to read JPEG file");
Chris@16 171 std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<cmyk8_ref_t, typename View::value_type,CC>(_cc));
Chris@16 172 }
Chris@16 173 break;
Chris@16 174 }
Chris@16 175 default:
Chris@16 176 io_error("jpeg_reader_color_covert::apply(): unknown color type");
Chris@16 177 }
Chris@16 178 jpeg_finish_decompress(&_cinfo);
Chris@16 179 }
Chris@16 180 template <typename Image>
Chris@16 181 void read_image(Image& im) {
Chris@16 182 im.recreate(get_dimensions());
Chris@16 183 apply(view(im));
Chris@16 184 }
Chris@16 185 };
Chris@16 186
Chris@16 187 class jpeg_writer : public file_mgr {
Chris@16 188 jpeg_compress_struct _cinfo;
Chris@16 189 jpeg_error_mgr _jerr;
Chris@16 190
Chris@16 191 void init() {
Chris@16 192 _cinfo.err=jpeg_std_error(&_jerr);
Chris@16 193 jpeg_create_compress(&_cinfo);
Chris@16 194 jpeg_stdio_dest(&_cinfo,_fp.get());
Chris@16 195 }
Chris@16 196 public:
Chris@16 197 jpeg_writer(FILE* file) : file_mgr(file) { init(); }
Chris@16 198 jpeg_writer(const char* filename) : file_mgr(filename, "wb") { init(); }
Chris@16 199 ~jpeg_writer() { jpeg_destroy_compress(&_cinfo); }
Chris@16 200
Chris@16 201 template <typename View>
Chris@16 202 void apply(const View& view,int quality=100) {
Chris@16 203 _cinfo.image_width = (JDIMENSION)view.width();
Chris@16 204 _cinfo.image_height = (JDIMENSION)view.height();
Chris@16 205 _cinfo.input_components=num_channels<View>::value;
Chris@16 206 _cinfo.in_color_space = jpeg_write_support_private<typename channel_type<View>::type,
Chris@16 207 typename color_space_type<View>::type>::color_type;
Chris@16 208 jpeg_set_defaults(&_cinfo);
Chris@16 209 jpeg_set_quality(&_cinfo, quality, TRUE);
Chris@16 210 jpeg_start_compress(&_cinfo, TRUE);
Chris@16 211 std::vector<pixel<bits8,layout<typename color_space_type<View>::type> > > row(view.width());
Chris@16 212 JSAMPLE* row_address=(JSAMPLE*)&row.front();
Chris@16 213 for (int y=0;y<view.height(); ++y) {
Chris@16 214 std::copy(view.row_begin(y),view.row_end(y),row.begin());
Chris@16 215 io_error_if(jpeg_write_scanlines(&_cinfo,(JSAMPARRAY)&row_address,1) != 1,
Chris@16 216 "jpeg_writer::apply(): fail to write file");
Chris@16 217 }
Chris@16 218 jpeg_finish_compress(&_cinfo);
Chris@16 219 }
Chris@16 220 };
Chris@16 221
Chris@16 222 } // namespace detail
Chris@16 223
Chris@16 224 } } // namespace boost::gil
Chris@16 225
Chris@16 226 #endif