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>
39 using boost::shared_ptr;
40 using boost::optional;
41 using boost::dynamic_pointer_cast;
43 using dcp::raw_convert;
45 /** Construct a J2KImageProxy from a JPEG2000 file */
46 J2KImageProxy::J2KImageProxy (boost::filesystem::path path, dcp::Size size, AVPixelFormat pixel_format)
49 , _pixel_format (pixel_format)
54 J2KImageProxy::J2KImageProxy (shared_ptr<const dcp::MonoPictureFrame> frame, dcp::Size size, AVPixelFormat pixel_format)
55 : _data (frame->j2k_size ())
57 , _pixel_format (pixel_format)
59 memcpy (_data.data().get(), frame->j2k_data(), _data.size ());
62 J2KImageProxy::J2KImageProxy (shared_ptr<const dcp::StereoPictureFrame> frame, dcp::Size size, dcp::Eye eye, AVPixelFormat pixel_format)
65 , _pixel_format (pixel_format)
69 _data = Data (frame->left_j2k_size ());
70 memcpy (_data.data().get(), frame->left_j2k_data(), _data.size ());
73 _data = Data (frame->right_j2k_size ());
74 memcpy (_data.data().get(), frame->right_j2k_data(), _data.size ());
79 J2KImageProxy::J2KImageProxy (shared_ptr<cxml::Node> xml, shared_ptr<Socket> socket)
81 _size = dcp::Size (xml->number_child<int> ("Width"), xml->number_child<int> ("Height"));
82 if (xml->optional_number_child<int> ("Eye")) {
83 _eye = static_cast<dcp::Eye> (xml->number_child<int> ("Eye"));
85 _data = Data (xml->number_child<int> ("Size"));
86 /* This only matters when we are using J2KImageProxy for the preview, which
87 will never use this constructor (which is only used for passing data to
88 encode servers). So we can put anything in here. It's a bit of a hack.
90 _pixel_format = AV_PIX_FMT_XYZ12LE;
91 socket->read (_data.data().get (), _data.size ());
95 J2KImageProxy::ensure_j2k () const
98 _j2k = dcp::decompress_j2k (const_cast<uint8_t*> (_data.data().get()), _data.size (), 0);
103 J2KImageProxy::image (optional<dcp::NoteHandler>) const
107 if (_j2k->precision(0) < 12) {
108 int const shift = 12 - _j2k->precision (0);
109 for (int c = 0; c < 3; ++c) {
110 int* p = _j2k->data (c);
111 for (int y = 0; y < _j2k->size().height; ++y) {
112 for (int x = 0; x < _j2k->size().width; ++x) {
119 shared_ptr<Image> image (new Image (_pixel_format, _size, true));
121 /* Copy data in whatever format (sRGB or XYZ) into our Image; I'm assuming
122 the data is 12-bit either way.
126 for (int y = 0; y < _j2k->size().height; ++y) {
127 uint16_t* q = (uint16_t *) (image->data()[0] + y * image->stride()[0]);
128 for (int x = 0; x < _j2k->size().width; ++x) {
129 for (int c = 0; c < 3; ++c) {
130 *q++ = _j2k->data(c)[p] << 4;
140 J2KImageProxy::add_metadata (xmlpp::Node* node) const
142 node->add_child("Type")->add_child_text (N_("J2K"));
143 node->add_child("Width")->add_child_text (raw_convert<string> (_size.width));
144 node->add_child("Height")->add_child_text (raw_convert<string> (_size.height));
146 node->add_child("Eye")->add_child_text (raw_convert<string> (static_cast<int> (_eye.get ())));
148 node->add_child("Size")->add_child_text (raw_convert<string> (_data.size ()));
152 J2KImageProxy::send_binary (shared_ptr<Socket> socket) const
154 socket->write (_data.data().get(), _data.size());
158 J2KImageProxy::same (shared_ptr<const ImageProxy> other) const
160 shared_ptr<const J2KImageProxy> jp = dynamic_pointer_cast<const J2KImageProxy> (other);
165 if (_data.size() != jp->_data.size()) {
169 return memcmp (_data.data().get(), jp->_data.data().get(), _data.size()) == 0;
172 J2KImageProxy::J2KImageProxy (Data data, dcp::Size size, AVPixelFormat pixel_format)
175 , _pixel_format (pixel_format)