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 (shared_ptr<const dcp::MonoPictureFrame> frame, dcp::Size size, AVPixelFormat pixel_format)
57 : _data (frame->j2k_size ())
59 , _pixel_format (pixel_format)
61 memcpy (_data.data().get(), frame->j2k_data(), _data.size ());
64 J2KImageProxy::J2KImageProxy (shared_ptr<const dcp::StereoPictureFrame> frame, dcp::Size size, dcp::Eye eye, AVPixelFormat pixel_format)
67 , _pixel_format (pixel_format)
71 _data = Data (frame->left_j2k_size ());
72 memcpy (_data.data().get(), frame->left_j2k_data(), _data.size ());
75 _data = Data (frame->right_j2k_size ());
76 memcpy (_data.data().get(), frame->right_j2k_data(), _data.size ());
81 J2KImageProxy::J2KImageProxy (shared_ptr<cxml::Node> xml, shared_ptr<Socket> socket)
83 _size = dcp::Size (xml->number_child<int> ("Width"), xml->number_child<int> ("Height"));
84 if (xml->optional_number_child<int> ("Eye")) {
85 _eye = static_cast<dcp::Eye> (xml->number_child<int> ("Eye"));
87 _data = Data (xml->number_child<int> ("Size"));
88 /* This only matters when we are using J2KImageProxy for the preview, which
89 will never use this constructor (which is only used for passing data to
90 encode servers). So we can put anything in here. It's a bit of a hack.
92 _pixel_format = AV_PIX_FMT_XYZ12LE;
93 socket->read (_data.data().get (), _data.size ());
97 J2KImageProxy::prepare (optional<dcp::Size> target_size) const
99 boost::mutex::scoped_lock lm (_mutex);
101 if (_decompressed && target_size == _target_size) {
107 while (target_size && (_size.width / pow(2, reduce)) > target_size->width && (_size.height / pow(2, reduce)) > target_size->height) {
112 reduce = max (0, reduce);
113 _decompressed = dcp::decompress_j2k (const_cast<uint8_t*> (_data.data().get()), _data.size (), reduce);
115 if (_decompressed->precision(0) < 12) {
116 int const shift = 12 - _decompressed->precision (0);
117 for (int c = 0; c < 3; ++c) {
118 int* p = _decompressed->data (c);
119 for (int y = 0; y < _decompressed->size().height; ++y) {
120 for (int x = 0; x < _decompressed->size().width; ++x) {
127 _target_size = target_size;
131 J2KImageProxy::image (optional<dcp::NoteHandler>, optional<dcp::Size> target_size) const
133 prepare (target_size);
135 shared_ptr<Image> image (new Image (_pixel_format, _decompressed->size(), true));
137 /* Copy data in whatever format (sRGB or XYZ) into our Image; I'm assuming
138 the data is 12-bit either way.
141 int const width = _decompressed->size().width;
144 for (int y = 0; y < _decompressed->size().height; ++y) {
145 uint16_t* q = (uint16_t *) (image->data()[0] + y * image->stride()[0]);
146 for (int x = 0; x < width; ++x) {
147 for (int c = 0; c < 3; ++c) {
148 *q++ = _decompressed->data(c)[p] << 4;
158 J2KImageProxy::add_metadata (xmlpp::Node* node) const
160 node->add_child("Type")->add_child_text (N_("J2K"));
161 node->add_child("Width")->add_child_text (raw_convert<string> (_size.width));
162 node->add_child("Height")->add_child_text (raw_convert<string> (_size.height));
164 node->add_child("Eye")->add_child_text (raw_convert<string> (static_cast<int> (_eye.get ())));
166 node->add_child("Size")->add_child_text (raw_convert<string> (_data.size ()));
170 J2KImageProxy::send_binary (shared_ptr<Socket> socket) const
172 socket->write (_data.data().get(), _data.size());
176 J2KImageProxy::same (shared_ptr<const ImageProxy> other) const
178 shared_ptr<const J2KImageProxy> jp = dynamic_pointer_cast<const J2KImageProxy> (other);
183 if (_data.size() != jp->_data.size()) {
187 return memcmp (_data.data().get(), jp->_data.data().get(), _data.size()) == 0;
190 J2KImageProxy::J2KImageProxy (Data data, dcp::Size size, AVPixelFormat pixel_format)
193 , _pixel_format (pixel_format)