2 Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
4 This file is part of libdcp.
6 libdcp is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 libdcp is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with libdcp. If not, see <http://www.gnu.org/licenses/>.
19 In addition, as a special exception, the copyright holders give
20 permission to link the code of portions of this program with the
21 OpenSSL library under certain conditions as described in each
22 individual source file, and distribute linked combinations
25 You must obey the GNU General Public License in all respects
26 for all of the code used other than OpenSSL. If you modify
27 file(s) with this exception, you may extend this exception to your
28 version of the file(s), but you are not obligated to do so. If you
29 do not wish to do so, delete this exception statement from your
30 version. If you delete this exception statement from all source
31 files in the program, then also delete it here.
35 #include "exceptions.h"
36 #include "openjpeg_image.h"
38 #include "dcp_assert.h"
39 #include "compose.hpp"
46 using boost::shared_ptr;
47 using boost::shared_array;
50 shared_ptr<dcp::OpenJPEGImage>
51 dcp::decompress_j2k (Data data, int reduce)
53 return dcp::decompress_j2k (data.data().get(), data.size(), reduce);
59 ReadBuffer (uint8_t* data, int64_t size)
65 OPJ_SIZE_T read (void* buffer, OPJ_SIZE_T nb_bytes)
67 int64_t N = min (nb_bytes, _size - _offset);
68 memcpy (buffer, _data + _offset, N);
80 read_function (void* buffer, OPJ_SIZE_T nb_bytes, void* data)
82 return reinterpret_cast<ReadBuffer*>(data)->read (buffer, nb_bytes);
86 read_free_function (void* data)
88 delete reinterpret_cast<ReadBuffer*>(data);
91 /** Decompress a JPEG2000 image to a bitmap.
92 * @param data JPEG2000 data.
93 * @param size Size of data in bytes.
94 * @param reduce A power of 2 by which to reduce the size of the decoded image;
95 * e.g. 0 reduces by (2^0 == 1), ie keeping the same size.
96 * 1 reduces by (2^1 == 2), ie halving the size of the image.
97 * This is useful for scaling 4K DCP images down to 2K.
98 * @return OpenJPEGImage.
100 shared_ptr<dcp::OpenJPEGImage>
101 dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
103 uint8_t const jp2_magic[] = {
114 OPJ_CODEC_FORMAT format = OPJ_CODEC_J2K;
115 if (size >= int (sizeof (jp2_magic)) && memcmp (data, jp2_magic, sizeof (jp2_magic)) == 0) {
116 format = OPJ_CODEC_JP2;
119 opj_codec_t* decoder = opj_create_decompress (format);
121 boost::throw_exception (DCPReadError ("could not create JPEG2000 decompresser"));
123 opj_dparameters_t parameters;
124 opj_set_default_decoder_parameters (¶meters);
125 parameters.cp_reduce = reduce;
126 opj_setup_decoder (decoder, ¶meters);
128 opj_stream_t* stream = opj_stream_default_create (OPJ_TRUE);
130 throw MiscError ("could not create JPEG2000 stream");
133 opj_stream_set_read_function (stream, read_function);
134 ReadBuffer* buffer = new ReadBuffer (data, size);
135 opj_stream_set_user_data (stream, buffer, read_free_function);
136 opj_stream_set_user_data_length (stream, size);
138 opj_image_t* image = 0;
139 opj_read_header (stream, decoder, &image);
140 if (opj_decode (decoder, stream, image) == OPJ_FALSE) {
141 opj_destroy_codec (decoder);
142 opj_stream_destroy (stream);
143 if (format == OPJ_CODEC_J2K) {
144 boost::throw_exception (DCPReadError (String::compose ("could not decode JPEG2000 codestream of %1 bytes.", size)));
146 boost::throw_exception (DCPReadError (String::compose ("could not decode JP2 file of %1 bytes.", size)));
150 opj_destroy_codec (decoder);
151 opj_stream_destroy (stream);
153 image->x1 = rint (float(image->x1) / pow (2.0f, reduce));
154 image->y1 = rint (float(image->y1) / pow (2.0f, reduce));
155 return shared_ptr<OpenJPEGImage> (new OpenJPEGImage (image));
161 /* XXX: is there a better strategy for this? */
162 #define MAX_J2K_SIZE (1024 * 1024 * 2)
164 : _data (shared_array<uint8_t> (new uint8_t[MAX_J2K_SIZE]), MAX_J2K_SIZE)
170 OPJ_SIZE_T write (void* buffer, OPJ_SIZE_T nb_bytes)
172 DCP_ASSERT ((_offset + nb_bytes) < MAX_J2K_SIZE);
173 memcpy (_data.data().get() + _offset, buffer, nb_bytes);
175 if (_offset > OPJ_SIZE_T (_data.size())) {
176 _data.set_size (_offset);
181 OPJ_BOOL seek (OPJ_SIZE_T nb_bytes)
198 write_function (void* buffer, OPJ_SIZE_T nb_bytes, void* data)
200 return reinterpret_cast<WriteBuffer*>(data)->write (buffer, nb_bytes);
204 write_free_function (void* data)
206 delete reinterpret_cast<WriteBuffer*>(data);
210 seek_function (OPJ_OFF_T nb_bytes, void* data)
212 return reinterpret_cast<WriteBuffer*>(data)->seek (nb_bytes);
216 error_callback (char const * msg, void *)
218 throw MiscError (msg);
222 dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frames_per_second, bool threed, bool fourk)
224 /* get a J2K compressor handle */
225 opj_codec_t* encoder = opj_create_compress (OPJ_CODEC_J2K);
227 throw MiscError ("could not create JPEG2000 encoder");
230 opj_set_error_handler (encoder, error_callback, 0);
232 /* Set encoding parameters to default values */
233 opj_cparameters_t parameters;
234 opj_set_default_encoder_parameters (¶meters);
235 parameters.rsiz = fourk ? OPJ_PROFILE_CINEMA_4K : OPJ_PROFILE_CINEMA_2K;
236 parameters.cp_comment = strdup ("libdcp");
239 parameters.max_cs_size = (bandwidth / 8) / frames_per_second;
241 /* In 3D we have only half the normal bandwidth per eye */
242 parameters.max_cs_size /= 2;
244 parameters.max_comp_size = parameters.max_cs_size / 1.25;
245 parameters.tcp_numlayers = 1;
246 parameters.tcp_mct = 1;
248 /* Setup the encoder parameters using the current image and user parameters */
249 opj_setup_encoder (encoder, ¶meters, xyz->opj_image());
251 opj_stream_t* stream = opj_stream_default_create (OPJ_FALSE);
253 throw MiscError ("could not create JPEG2000 stream");
256 opj_stream_set_write_function (stream, write_function);
257 opj_stream_set_seek_function (stream, seek_function);
258 WriteBuffer* buffer = new WriteBuffer ();
259 opj_stream_set_user_data (stream, buffer, write_free_function);
261 if (!opj_start_compress (encoder, xyz->opj_image(), stream)) {
262 throw MiscError ("could not start JPEG2000 encoding");
265 if (!opj_encode (encoder, stream)) {
266 opj_destroy_codec (encoder);
267 opj_stream_destroy (stream);
268 throw MiscError ("JPEG2000 encoding failed");
271 if (!opj_end_compress (encoder, stream)) {
272 opj_destroy_codec (encoder);
273 opj_stream_destroy (stream);
274 throw MiscError ("could not end JPEG2000 encoding");
277 Data enc (buffer->data ());
279 free (parameters.cp_comment);
280 opj_destroy_codec (encoder);
281 opj_stream_destroy (stream);