2 Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic 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 DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
21 #include "j2k_image_proxy.h"
22 #include "dcpomatic_socket.h"
24 #include "dcpomatic_assert.h"
25 #include <dcp/raw_convert.h>
26 #include <dcp/openjpeg_image.h>
27 #include <dcp/mono_picture_frame.h>
28 #include <dcp/stereo_picture_frame.h>
29 #include <dcp/colour_conversion.h>
30 #include <dcp/rgb_xyz.h>
32 #include <libcxml/cxml.h>
33 #include <libxml++/libxml++.h>
43 using boost::shared_ptr;
44 using boost::optional;
45 using boost::dynamic_pointer_cast;
47 using dcp::raw_convert;
49 /** Construct a J2KImageProxy from a JPEG2000 file */
50 J2KImageProxy::J2KImageProxy (boost::filesystem::path path, dcp::Size size, AVPixelFormat pixel_format)
53 , _pixel_format (pixel_format)
56 /* ::image assumes 16bpp */
57 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB48 || _pixel_format == AV_PIX_FMT_XYZ12LE);
60 J2KImageProxy::J2KImageProxy (
61 shared_ptr<const dcp::MonoPictureFrame> frame,
63 AVPixelFormat pixel_format,
64 optional<int> forced_reduction
66 : _data (frame->j2k_size ())
68 , _pixel_format (pixel_format)
69 , _forced_reduction (forced_reduction)
72 /* ::image assumes 16bpp */
73 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB48 || _pixel_format == AV_PIX_FMT_XYZ12LE);
74 memcpy (_data.data().get(), frame->j2k_data(), _data.size ());
77 J2KImageProxy::J2KImageProxy (
78 shared_ptr<const dcp::StereoPictureFrame> frame,
81 AVPixelFormat pixel_format,
82 optional<int> forced_reduction
86 , _pixel_format (pixel_format)
87 , _forced_reduction (forced_reduction)
90 /* ::image assumes 16bpp */
91 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB48 || _pixel_format == AV_PIX_FMT_XYZ12LE);
94 _data = Data (frame->left_j2k_size ());
95 memcpy (_data.data().get(), frame->left_j2k_data(), _data.size ());
98 _data = Data (frame->right_j2k_size ());
99 memcpy (_data.data().get(), frame->right_j2k_data(), _data.size ());
104 J2KImageProxy::J2KImageProxy (shared_ptr<cxml::Node> xml, shared_ptr<Socket> socket)
107 _size = dcp::Size (xml->number_child<int> ("Width"), xml->number_child<int> ("Height"));
108 if (xml->optional_number_child<int> ("Eye")) {
109 _eye = static_cast<dcp::Eye> (xml->number_child<int> ("Eye"));
111 _data = Data (xml->number_child<int> ("Size"));
112 /* This only matters when we are using J2KImageProxy for the preview, which
113 will never use this constructor (which is only used for passing data to
114 encode servers). So we can put anything in here. It's a bit of a hack.
116 _pixel_format = AV_PIX_FMT_XYZ12LE;
117 socket->read (_data.data().get (), _data.size ());
121 J2KImageProxy::prepare (optional<dcp::Size> target_size) const
123 boost::mutex::scoped_lock lm (_mutex);
125 if (_image && target_size == _target_size) {
126 DCPOMATIC_ASSERT (_reduce);
132 if (_forced_reduction) {
133 reduce = *_forced_reduction;
135 while (target_size && (_size.width / pow(2, reduce)) > target_size->width && (_size.height / pow(2, reduce)) > target_size->height) {
140 reduce = max (0, reduce);
144 shared_ptr<dcp::OpenJPEGImage> decompressed = dcp::decompress_j2k (const_cast<uint8_t*> (_data.data().get()), _data.size (), reduce);
145 _image.reset (new Image (_pixel_format, decompressed->size(), true));
147 int const shift = 16 - decompressed->precision (0);
149 /* Copy data in whatever format (sRGB or XYZ) into our Image; I'm assuming
150 the data is 12-bit either way.
153 int const width = decompressed->size().width;
156 int* decomp_0 = decompressed->data (0);
157 int* decomp_1 = decompressed->data (1);
158 int* decomp_2 = decompressed->data (2);
159 for (int y = 0; y < decompressed->size().height; ++y) {
160 uint16_t* q = (uint16_t *) (_image->data()[0] + y * _image->stride()[0]);
161 for (int x = 0; x < width; ++x) {
162 *q++ = decomp_0[p] << shift;
163 *q++ = decomp_1[p] << shift;
164 *q++ = decomp_2[p] << shift;
168 } catch (dcp::J2KDecompressionError& e) {
169 _image.reset (new Image (_pixel_format, _size, true));
170 _image->make_black ();
174 _target_size = target_size;
182 J2KImageProxy::image (optional<dcp::Size> target_size) const
184 int const r = prepare (target_size);
186 /* I think this is safe without a lock on mutex. _image is guaranteed to be
187 set up when prepare() has happened.
189 return Result (_image, r, _error);
194 J2KImageProxy::add_metadata (xmlpp::Node* node) const
196 node->add_child("Type")->add_child_text (N_("J2K"));
197 node->add_child("Width")->add_child_text (raw_convert<string> (_size.width));
198 node->add_child("Height")->add_child_text (raw_convert<string> (_size.height));
200 node->add_child("Eye")->add_child_text (raw_convert<string> (static_cast<int> (_eye.get ())));
202 node->add_child("Size")->add_child_text (raw_convert<string> (_data.size ()));
206 J2KImageProxy::write_to_socket (shared_ptr<Socket> socket) const
208 socket->write (_data.data().get(), _data.size());
212 J2KImageProxy::same (shared_ptr<const ImageProxy> other) const
214 shared_ptr<const J2KImageProxy> jp = dynamic_pointer_cast<const J2KImageProxy> (other);
219 if (_data.size() != jp->_data.size()) {
223 return memcmp (_data.data().get(), jp->_data.data().get(), _data.size()) == 0;
226 J2KImageProxy::J2KImageProxy (Data data, dcp::Size size, AVPixelFormat pixel_format)
229 , _pixel_format (pixel_format)
231 /* ::image assumes 16bpp */
232 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB48 || _pixel_format == AV_PIX_FMT_XYZ12LE);
236 J2KImageProxy::memory_used () const
238 size_t m = _data.size();
240 /* 3 components, 16-bits per pixel */
241 m += 3 * 2 * _image->size().width * _image->size().height;