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"
47 using boost::shared_ptr;
48 using boost::shared_array;
51 shared_ptr<dcp::OpenJPEGImage>
52 dcp::decompress_j2k (Data data, int reduce)
54 return dcp::decompress_j2k (data.data().get(), data.size(), reduce);
57 #ifdef LIBDCP_OPENJPEG2
62 ReadBuffer (uint8_t* data, int64_t size)
68 OPJ_SIZE_T read (void* buffer, OPJ_SIZE_T nb_bytes)
70 int64_t N = min (nb_bytes, _size - _offset);
71 memcpy (buffer, _data + _offset, N);
83 read_function (void* buffer, OPJ_SIZE_T nb_bytes, void* data)
85 return reinterpret_cast<ReadBuffer*>(data)->read (buffer, nb_bytes);
89 read_free_function (void* data)
91 delete reinterpret_cast<ReadBuffer*>(data);
96 decompress_error_callback (char const * msg, void *)
98 throw J2KDecompressionError (msg);
103 compress_error_callback (char const * msg, void *)
105 throw MiscError (msg);
108 /** Decompress a JPEG2000 image to a bitmap.
109 * @param data JPEG2000 data.
110 * @param size Size of data in bytes.
111 * @param reduce A power of 2 by which to reduce the size of the decoded image;
112 * e.g. 0 reduces by (2^0 == 1), ie keeping the same size.
113 * 1 reduces by (2^1 == 2), ie halving the size of the image.
114 * This is useful for scaling 4K DCP images down to 2K.
115 * @return OpenJPEGImage.
117 shared_ptr<dcp::OpenJPEGImage>
118 dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
120 DCP_ASSERT (reduce >= 0);
122 uint8_t const jp2_magic[] = {
133 OPJ_CODEC_FORMAT format = OPJ_CODEC_J2K;
134 if (size >= int (sizeof (jp2_magic)) && memcmp (data, jp2_magic, sizeof (jp2_magic)) == 0) {
135 format = OPJ_CODEC_JP2;
138 opj_codec_t* decoder = opj_create_decompress (format);
140 boost::throw_exception (ReadError ("could not create JPEG2000 decompresser"));
142 opj_dparameters_t parameters;
143 opj_set_default_decoder_parameters (¶meters);
144 parameters.cp_reduce = reduce;
145 opj_setup_decoder (decoder, ¶meters);
147 opj_stream_t* stream = opj_stream_default_create (OPJ_TRUE);
149 throw MiscError ("could not create JPEG2000 stream");
152 opj_set_error_handler(decoder, decompress_error_callback, 00);
154 opj_stream_set_read_function (stream, read_function);
155 ReadBuffer* buffer = new ReadBuffer (data, size);
156 opj_stream_set_user_data (stream, buffer, read_free_function);
157 opj_stream_set_user_data_length (stream, size);
159 opj_image_t* image = 0;
160 opj_read_header (stream, decoder, &image);
161 if (opj_decode (decoder, stream, image) == OPJ_FALSE) {
162 opj_destroy_codec (decoder);
163 opj_stream_destroy (stream);
164 if (format == OPJ_CODEC_J2K) {
165 boost::throw_exception (ReadError (String::compose ("could not decode JPEG2000 codestream of %1 bytes.", size)));
167 boost::throw_exception (ReadError (String::compose ("could not decode JP2 file of %1 bytes.", size)));
171 opj_destroy_codec (decoder);
172 opj_stream_destroy (stream);
174 image->x1 = rint (float(image->x1) / pow (2.0f, reduce));
175 image->y1 = rint (float(image->y1) / pow (2.0f, reduce));
176 return shared_ptr<OpenJPEGImage> (new OpenJPEGImage (image));
180 #ifdef LIBDCP_OPENJPEG1
181 /** Decompress a JPEG2000 image to a bitmap.
182 * @param data JPEG2000 data.
183 * @param size Size of data in bytes.
184 * @param reduce A power of 2 by which to reduce the size of the decoded image;
185 * e.g. 0 reduces by (2^0 == 1), ie keeping the same size.
186 * 1 reduces by (2^1 == 2), ie halving the size of the image.
187 * This is useful for scaling 4K DCP images down to 2K.
190 shared_ptr<dcp::OpenJPEGImage>
191 dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
193 opj_dinfo_t* decoder = opj_create_decompress (CODEC_J2K);
194 opj_dparameters_t parameters;
195 opj_set_default_decoder_parameters (¶meters);
196 parameters.cp_reduce = reduce;
197 opj_setup_decoder (decoder, ¶meters);
198 opj_cio_t* cio = opj_cio_open ((opj_common_ptr) decoder, data, size);
199 opj_image_t* image = opj_decode (decoder, cio);
201 opj_destroy_decompress (decoder);
203 boost::throw_exception (ReadError (String::compose ("could not decode JPEG2000 codestream of %1 bytes.", size)));
206 opj_destroy_decompress (decoder);
209 image->x1 = rint (float(image->x1) / pow (2, reduce));
210 image->y1 = rint (float(image->y1) / pow (2, reduce));
211 return shared_ptr<OpenJPEGImage> (new OpenJPEGImage (image));
215 #ifdef LIBDCP_OPENJPEG2
219 /* XXX: is there a better strategy for this? */
220 #define MAX_J2K_SIZE (1024 * 1024 * 2)
222 : _data (shared_array<uint8_t> (new uint8_t[MAX_J2K_SIZE]), MAX_J2K_SIZE)
228 OPJ_SIZE_T write (void* buffer, OPJ_SIZE_T nb_bytes)
230 DCP_ASSERT ((_offset + nb_bytes) < MAX_J2K_SIZE);
231 memcpy (_data.data().get() + _offset, buffer, nb_bytes);
233 if (_offset > OPJ_SIZE_T (_data.size())) {
234 _data.set_size (_offset);
239 OPJ_BOOL seek (OPJ_SIZE_T nb_bytes)
256 write_function (void* buffer, OPJ_SIZE_T nb_bytes, void* data)
258 return reinterpret_cast<WriteBuffer*>(data)->write (buffer, nb_bytes);
262 write_free_function (void* data)
264 delete reinterpret_cast<WriteBuffer*>(data);
268 seek_function (OPJ_OFF_T nb_bytes, void* data)
270 return reinterpret_cast<WriteBuffer*>(data)->seek (nb_bytes);
273 /** @xyz Picture to compress. Parts of xyz's data WILL BE OVERWRITTEN by libopenjpeg so xyz cannot be re-used
274 * after this call; see opj_j2k_encode where if l_reuse_data is false it will set l_tilec->data = l_img_comp->data.
277 dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frames_per_second, bool threed, bool fourk, string comment)
279 /* get a J2K compressor handle */
280 opj_codec_t* encoder = opj_create_compress (OPJ_CODEC_J2K);
282 throw MiscError ("could not create JPEG2000 encoder");
285 opj_set_error_handler (encoder, compress_error_callback, 0);
287 /* Set encoding parameters to default values */
288 opj_cparameters_t parameters;
289 opj_set_default_encoder_parameters (¶meters);
291 parameters.numresolution = 7;
293 parameters.rsiz = fourk ? OPJ_PROFILE_CINEMA_4K : OPJ_PROFILE_CINEMA_2K;
294 parameters.cp_comment = strdup (comment.c_str());
297 parameters.max_cs_size = (bandwidth / 8) / frames_per_second;
299 /* In 3D we have only half the normal bandwidth per eye */
300 parameters.max_cs_size /= 2;
302 parameters.max_comp_size = parameters.max_cs_size / 1.25;
303 parameters.tcp_numlayers = 1;
304 parameters.tcp_mct = 1;
306 /* Setup the encoder parameters using the current image and user parameters */
307 opj_setup_encoder (encoder, ¶meters, xyz->opj_image());
309 opj_stream_t* stream = opj_stream_default_create (OPJ_FALSE);
311 opj_destroy_codec (encoder);
312 free (parameters.cp_comment);
313 throw MiscError ("could not create JPEG2000 stream");
316 opj_stream_set_write_function (stream, write_function);
317 opj_stream_set_seek_function (stream, seek_function);
318 WriteBuffer* buffer = new WriteBuffer ();
319 opj_stream_set_user_data (stream, buffer, write_free_function);
321 if (!opj_start_compress (encoder, xyz->opj_image(), stream)) {
322 opj_stream_destroy (stream);
323 opj_destroy_codec (encoder);
324 free (parameters.cp_comment);
325 if ((errno & 0x61500) == 0x61500) {
326 /* We've had one of the magic error codes from our patched openjpeg */
327 boost::throw_exception (StartCompressionError (errno & 0xff));
329 boost::throw_exception (StartCompressionError ());
333 if (!opj_encode (encoder, stream)) {
334 opj_stream_destroy (stream);
335 opj_destroy_codec (encoder);
336 free (parameters.cp_comment);
337 throw MiscError ("JPEG2000 encoding failed");
340 if (!opj_end_compress (encoder, stream)) {
341 opj_stream_destroy (stream);
342 opj_destroy_codec (encoder);
343 free (parameters.cp_comment);
344 throw MiscError ("could not end JPEG2000 encoding");
347 Data enc (buffer->data ());
349 opj_stream_destroy (stream);
350 opj_destroy_codec (encoder);
351 free (parameters.cp_comment);
357 #ifdef LIBDCP_OPENJPEG1
359 dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frames_per_second, bool threed, bool fourk)
361 /* Set the max image and component sizes based on frame_rate */
362 int max_cs_len = ((float) bandwidth) / 8 / frames_per_second;
364 /* In 3D we have only half the normal bandwidth per eye */
367 int const max_comp_size = max_cs_len / 1.25;
369 /* get a J2K compressor handle */
370 opj_cinfo_t* cinfo = opj_create_compress (CODEC_J2K);
372 throw MiscError ("could not create JPEG2000 encoder");
375 /* Set encoding parameters to default values */
376 opj_cparameters_t parameters;
377 opj_set_default_encoder_parameters (¶meters);
379 parameters.numresolution = 7;
382 /* Set default cinema parameters */
383 parameters.tile_size_on = false;
384 parameters.cp_tdx = 1;
385 parameters.cp_tdy = 1;
388 parameters.tp_flag = 'C';
389 parameters.tp_on = 1;
391 /* Tile and Image shall be at (0,0) */
392 parameters.cp_tx0 = 0;
393 parameters.cp_ty0 = 0;
394 parameters.image_offset_x0 = 0;
395 parameters.image_offset_y0 = 0;
397 /* Codeblock size = 32x32 */
398 parameters.cblockw_init = 32;
399 parameters.cblockh_init = 32;
400 parameters.csty |= 0x01;
402 /* The progression order shall be CPRL */
403 parameters.prog_order = CPRL;
406 parameters.roi_compno = -1;
408 parameters.subsampling_dx = 1;
409 parameters.subsampling_dy = 1;
412 parameters.irreversible = 1;
414 parameters.tcp_rates[0] = 0;
415 parameters.tcp_numlayers++;
416 parameters.cp_disto_alloc = 1;
417 parameters.cp_rsiz = fourk ? CINEMA4K : CINEMA2K;
419 parameters.numpocs = 2;
420 parameters.POC[0].tile = 1;
421 parameters.POC[0].resno0 = 0;
422 parameters.POC[0].compno0 = 0;
423 parameters.POC[0].layno1 = 1;
424 parameters.POC[0].resno1 = parameters.numresolution - 1;
425 parameters.POC[0].compno1 = 3;
426 parameters.POC[0].prg1 = CPRL;
427 parameters.POC[1].tile = 1;
428 parameters.POC[1].resno0 = parameters.numresolution - 1;
429 parameters.POC[1].compno0 = 0;
430 parameters.POC[1].layno1 = 1;
431 parameters.POC[1].resno1 = parameters.numresolution;
432 parameters.POC[1].compno1 = 3;
433 parameters.POC[1].prg1 = CPRL;
436 parameters.cp_comment = strdup ("libdcp");
437 parameters.cp_cinema = fourk ? CINEMA4K_24 : CINEMA2K_24;
439 /* 3 components, so use MCT */
440 parameters.tcp_mct = 1;
443 parameters.max_comp_size = max_comp_size;
444 parameters.tcp_rates[0] = ((float) (3 * xyz->size().width * xyz->size().height * 12)) / (max_cs_len * 8);
446 /* Set event manager to null (openjpeg 1.3 bug) */
447 cinfo->event_mgr = 0;
449 /* Setup the encoder parameters using the current image and user parameters */
450 opj_setup_encoder (cinfo, ¶meters, xyz->opj_image ());
452 opj_cio_t* cio = opj_cio_open ((opj_common_ptr) cinfo, 0, 0);
454 opj_destroy_compress (cinfo);
455 throw MiscError ("could not open JPEG2000 stream");
458 int const r = opj_encode (cinfo, cio, xyz->opj_image(), 0);
461 opj_destroy_compress (cinfo);
462 throw MiscError ("JPEG2000 encoding failed");
465 Data enc (cio->buffer, cio_tell (cio));
468 free (parameters.cp_comment);
469 opj_destroy_compress (cinfo);