diff options
| author | Carl Hetherington <cth@carlh.net> | 2021-12-18 23:34:26 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2022-04-29 00:27:17 +0200 |
| commit | 59c4edb69ba926d3790198cd2b62dc601944a632 (patch) | |
| tree | 5f209c2aa5cbf60ec194bc1ab25ea63c75c4e854 /src/lib | |
| parent | 7ec6c86c913fba820870565ee757fdf43ae47433 (diff) | |
Add image_as_jpeg()
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/image_jpeg.cc | 135 | ||||
| -rw-r--r-- | src/lib/image_jpeg.h | 22 | ||||
| -rw-r--r-- | src/lib/wscript | 3 |
3 files changed, 159 insertions, 1 deletions
diff --git a/src/lib/image_jpeg.cc b/src/lib/image_jpeg.cc new file mode 100644 index 000000000..28bbb7574 --- /dev/null +++ b/src/lib/image_jpeg.cc @@ -0,0 +1,135 @@ +/* + Copyright (C) 2021 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + + +#include "dcpomatic_assert.h" +#include "exceptions.h" +#include "image.h" +#include <jpeglib.h> + +#include "i18n.h" + + +using std::shared_ptr; + + +struct destination_mgr +{ + jpeg_destination_mgr pub; + std::vector<uint8_t>* data; +}; + + +static void +init_destination (j_compress_ptr) +{ + +} + + +/* Empty the output buffer (i.e. make more space for data); we'll make + * the output buffer bigger instead. + */ +static boolean +empty_output_buffer (j_compress_ptr state) +{ + auto dest = reinterpret_cast<destination_mgr*> (state->dest); + + auto const old_size = dest->data->size(); + dest->data->resize (old_size * 2); + + dest->pub.next_output_byte = dest->data->data() + old_size; + dest->pub.free_in_buffer = old_size; + + return TRUE; +} + + +static void +term_destination (j_compress_ptr state) +{ + auto dest = reinterpret_cast<destination_mgr*> (state->dest); + + dest->data->resize (dest->data->size() - dest->pub.free_in_buffer); +} + + +void +error_exit (j_common_ptr) +{ + throw EncodeError (N_("JPEG encoding error")); +} + + +dcp::ArrayData +image_as_jpeg (shared_ptr<const Image> image, int quality) +{ + if (image->pixel_format() != AV_PIX_FMT_RGB24) { + return image_as_jpeg( + Image::ensure_alignment(image, Image::Alignment::PADDED)->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, Image::Alignment::PADDED, false), + quality + ); + } + + struct jpeg_compress_struct compress; + struct jpeg_error_mgr error; + + compress.err = jpeg_std_error (&error); + error.error_exit = error_exit; + jpeg_create_compress (&compress); + + auto mgr = new destination_mgr; + compress.dest = reinterpret_cast<jpeg_destination_mgr*>(mgr); + + mgr->pub.init_destination = init_destination; + mgr->pub.empty_output_buffer = empty_output_buffer; + mgr->pub.term_destination = term_destination; + + std::vector<uint8_t> data(4096); + mgr->data = &data; + mgr->pub.next_output_byte = data.data(); + mgr->pub.free_in_buffer = data.size(); + + compress.image_width = image->size().width; + compress.image_height = image->size().height; + compress.input_components = 3; + compress.in_color_space = JCS_RGB; + + jpeg_set_defaults (&compress); + jpeg_set_quality (&compress, quality, TRUE); + + jpeg_start_compress (&compress, TRUE); + + JSAMPROW row[1]; + auto const source_data = image->data()[0]; + auto const source_stride = image->stride()[0]; + for (auto y = 0U; y < compress.image_height; ++y) { + row[0] = source_data + y * source_stride; + jpeg_write_scanlines (&compress, row, 1); + } + + jpeg_finish_compress (&compress); + delete mgr; + jpeg_destroy_compress (&compress); + + return dcp::ArrayData (data.data(), data.size()); +} + + diff --git a/src/lib/image_jpeg.h b/src/lib/image_jpeg.h new file mode 100644 index 000000000..5c017fc2c --- /dev/null +++ b/src/lib/image_jpeg.h @@ -0,0 +1,22 @@ +/* + Copyright (C) 2021 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + + +dcp::ArrayData image_as_jpeg (std::shared_ptr<const Image> image, int quality); diff --git a/src/lib/wscript b/src/lib/wscript index 49b0e4bac..d1eef8e33 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -122,6 +122,7 @@ sources = """ image_decoder.cc image_examiner.cc image_filename_sorter.cc + image_jpeg.cc image_png.cc image_proxy.cc j2k_image_proxy.cc @@ -207,7 +208,7 @@ def build(bld): AVCODEC AVUTIL AVFORMAT AVFILTER SWSCALE BOOST_FILESYSTEM BOOST_THREAD BOOST_DATETIME BOOST_SIGNALS2 BOOST_REGEX SAMPLERATE POSTPROC TIFF SSH DCP CXML GLIB LZMA XML++ - CURL ZIP BZ2 FONTCONFIG PANGOMM CAIROMM XMLSEC SUB ICU NETTLE PNG LEQM_NRT + CURL ZIP BZ2 FONTCONFIG PANGOMM CAIROMM XMLSEC SUB ICU NETTLE PNG JPEG LEQM_NRT """ if bld.env.TARGET_OSX: |
