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 <dcp/raw_convert.h>
25 #include <dcp/openjpeg_image.h>
26 #include <dcp/mono_picture_frame.h>
27 #include <dcp/stereo_picture_frame.h>
28 #include <dcp/colour_conversion.h>
29 #include <dcp/rgb_xyz.h>
31 #include <libcxml/cxml.h>
32 #include <libxml++/libxml++.h>
41 using boost::shared_ptr;
42 using boost::optional;
43 using boost::dynamic_pointer_cast;
45 using dcp::raw_convert;
47 /** Construct a J2KImageProxy from a JPEG2000 file */
48 J2KImageProxy::J2KImageProxy (boost::filesystem::path path, dcp::Size size, AVPixelFormat pixel_format)
51 , _pixel_format (pixel_format)
56 J2KImageProxy::J2KImageProxy (
57 shared_ptr<const dcp::MonoPictureFrame> frame,
59 AVPixelFormat pixel_format,
60 optional<int> forced_reduction
62 : _data (frame->j2k_size ())
64 , _pixel_format (pixel_format)
65 , _forced_reduction (forced_reduction)
67 memcpy (_data.data().get(), frame->j2k_data(), _data.size ());
70 J2KImageProxy::J2KImageProxy (
71 shared_ptr<const dcp::StereoPictureFrame> frame,
74 AVPixelFormat pixel_format,
75 optional<int> forced_reduction
79 , _pixel_format (pixel_format)
80 , _forced_reduction (forced_reduction)
84 _data = Data (frame->left_j2k_size ());
85 memcpy (_data.data().get(), frame->left_j2k_data(), _data.size ());
88 _data = Data (frame->right_j2k_size ());
89 memcpy (_data.data().get(), frame->right_j2k_data(), _data.size ());
94 J2KImageProxy::J2KImageProxy (shared_ptr<cxml::Node> xml, shared_ptr<Socket> socket)
96 _size = dcp::Size (xml->number_child<int> ("Width"), xml->number_child<int> ("Height"));
97 if (xml->optional_number_child<int> ("Eye")) {
98 _eye = static_cast<dcp::Eye> (xml->number_child<int> ("Eye"));
100 _data = Data (xml->number_child<int> ("Size"));
101 /* This only matters when we are using J2KImageProxy for the preview, which
102 will never use this constructor (which is only used for passing data to
103 encode servers). So we can put anything in here. It's a bit of a hack.
105 _pixel_format = AV_PIX_FMT_XYZ12LE;
106 socket->read (_data.data().get (), _data.size ());
110 J2KImageProxy::prepare (optional<dcp::Size> target_size) const
112 boost::mutex::scoped_lock lm (_mutex);
114 if (_decompressed && target_size == _target_size) {
120 if (_forced_reduction) {
121 reduce = *_forced_reduction;
123 while (target_size && (_size.width / pow(2, reduce)) > target_size->width && (_size.height / pow(2, reduce)) > target_size->height) {
128 reduce = max (0, reduce);
131 _decompressed = dcp::decompress_j2k (const_cast<uint8_t*> (_data.data().get()), _data.size (), reduce);
133 if (_decompressed->precision(0) < 12) {
134 int const shift = 12 - _decompressed->precision (0);
135 for (int c = 0; c < 3; ++c) {
136 int* p = _decompressed->data (c);
137 for (int y = 0; y < _decompressed->size().height; ++y) {
138 for (int x = 0; x < _decompressed->size().width; ++x) {
145 _target_size = target_size;
149 J2KImageProxy::image (optional<dcp::NoteHandler>, optional<dcp::Size> target_size) const
151 prepare (target_size);
153 shared_ptr<Image> image (new Image (_pixel_format, _decompressed->size(), true));
155 /* Copy data in whatever format (sRGB or XYZ) into our Image; I'm assuming
156 the data is 12-bit either way.
159 int const width = _decompressed->size().width;
162 for (int y = 0; y < _decompressed->size().height; ++y) {
163 uint16_t* q = (uint16_t *) (image->data()[0] + y * image->stride()[0]);
164 for (int x = 0; x < width; ++x) {
165 for (int c = 0; c < 3; ++c) {
166 *q++ = _decompressed->data(c)[p] << 4;
176 J2KImageProxy::add_metadata (xmlpp::Node* node) const
178 node->add_child("Type")->add_child_text (N_("J2K"));
179 node->add_child("Width")->add_child_text (raw_convert<string> (_size.width));
180 node->add_child("Height")->add_child_text (raw_convert<string> (_size.height));
182 node->add_child("Eye")->add_child_text (raw_convert<string> (static_cast<int> (_eye.get ())));
184 node->add_child("Size")->add_child_text (raw_convert<string> (_data.size ()));
188 J2KImageProxy::send_binary (shared_ptr<Socket> socket) const
190 socket->write (_data.data().get(), _data.size());
194 J2KImageProxy::same (shared_ptr<const ImageProxy> other) const
196 shared_ptr<const J2KImageProxy> jp = dynamic_pointer_cast<const J2KImageProxy> (other);
201 if (_data.size() != jp->_data.size()) {
205 return memcmp (_data.data().get(), jp->_data.data().get(), _data.size()) == 0;
208 J2KImageProxy::J2KImageProxy (Data data, dcp::Size size, AVPixelFormat pixel_format)
211 , _pixel_format (pixel_format)