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::image (optional<dcp::NoteHandler>, optional<dcp::Size> target_size) const
99 if (!_j2k || target_size != _j2k_target_size) {
102 while (target_size && (_size.width / pow(2, reduce)) > target_size->width && (_size.height / pow(2, reduce)) > target_size->height) {
107 reduce = max (0, reduce);
108 _j2k = dcp::decompress_j2k (const_cast<uint8_t*> (_data.data().get()), _data.size (), reduce);
110 if (_j2k->precision(0) < 12) {
111 int const shift = 12 - _j2k->precision (0);
112 for (int c = 0; c < 3; ++c) {
113 int* p = _j2k->data (c);
114 for (int y = 0; y < _j2k->size().height; ++y) {
115 for (int x = 0; x < _j2k->size().width; ++x) {
122 _j2k_target_size = target_size;
125 shared_ptr<Image> image (new Image (_pixel_format, _j2k->size(), true));
127 /* Copy data in whatever format (sRGB or XYZ) into our Image; I'm assuming
128 the data is 12-bit either way.
131 int const width = _j2k->size().width;
134 for (int y = 0; y < _j2k->size().height; ++y) {
135 uint16_t* q = (uint16_t *) (image->data()[0] + y * image->stride()[0]);
136 for (int x = 0; x < width; ++x) {
137 for (int c = 0; c < 3; ++c) {
138 *q++ = _j2k->data(c)[p] << 4;
148 J2KImageProxy::add_metadata (xmlpp::Node* node) const
150 node->add_child("Type")->add_child_text (N_("J2K"));
151 node->add_child("Width")->add_child_text (raw_convert<string> (_size.width));
152 node->add_child("Height")->add_child_text (raw_convert<string> (_size.height));
154 node->add_child("Eye")->add_child_text (raw_convert<string> (static_cast<int> (_eye.get ())));
156 node->add_child("Size")->add_child_text (raw_convert<string> (_data.size ()));
160 J2KImageProxy::send_binary (shared_ptr<Socket> socket) const
162 socket->write (_data.data().get(), _data.size());
166 J2KImageProxy::same (shared_ptr<const ImageProxy> other) const
168 shared_ptr<const J2KImageProxy> jp = dynamic_pointer_cast<const J2KImageProxy> (other);
173 if (_data.size() != jp->_data.size()) {
177 return memcmp (_data.data().get(), jp->_data.data().get(), _data.size()) == 0;
180 J2KImageProxy::J2KImageProxy (Data data, dcp::Size size, AVPixelFormat pixel_format)
183 , _pixel_format (pixel_format)