libdcp
openjpeg_image.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
3 
4  This file is part of libdcp.
5 
6  libdcp 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.
10 
11  libdcp 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.
15 
16  You should have received a copy of the GNU General Public License
17  along with libdcp. If not, see <http://www.gnu.org/licenses/>.
18 
19  In addition, as a special exception, the copyright holders give
20  permission to link the code of portions of this program with the
21  OpenSSL library under certain conditions as described in each
22  individual source file, and distribute linked combinations
23  including the two.
24 
25  You must obey the GNU General Public License in all respects
26  for all of the code used other than OpenSSL. If you modify
27  file(s) with this exception, you may extend this exception to your
28  version of the file(s), but you are not obligated to do so. If you
29  do not wish to do so, delete this exception statement from your
30  version. If you delete this exception statement from all source
31  files in the program, then also delete it here.
32 */
33 
34 
40 #include "openjpeg_image.h"
41 #include "dcp_assert.h"
42 #include <openjpeg.h>
43 #include <stdexcept>
44 
45 
46 using namespace dcp;
47 
48 
49 #ifdef LIBDCP_OPENJPEG1
50 #define OPJ_CLRSPC_SRGB CLRSPC_SRGB
51 #endif
52 
53 
54 OpenJPEGImage::OpenJPEGImage (opj_image_t* image)
55  : _opj_image (image)
56 {
57  DCP_ASSERT (_opj_image->numcomps == 3);
58 }
59 
60 
61 #ifdef LIBDCP_OPENJPEG1
62 typedef int32_t OPJ_INT32;
63 typedef uint8_t OPJ_BYTE;
64 #endif
65 
66 
68 {
69  _opj_image = reinterpret_cast<opj_image_t*>(malloc(sizeof(opj_image_t)));
70  DCP_ASSERT (_opj_image);
71  memcpy (_opj_image, other._opj_image, sizeof (opj_image_t));
72 
73  int const data_size = _opj_image->x1 * _opj_image->y1 * 4;
74 
75  _opj_image->comps = reinterpret_cast<opj_image_comp_t*> (malloc (_opj_image->numcomps * sizeof (opj_image_comp_t)));
76  DCP_ASSERT (_opj_image->comps);
77  memcpy (_opj_image->comps, other._opj_image->comps, _opj_image->numcomps * sizeof (opj_image_comp_t));
78  for (unsigned int i = 0; i < _opj_image->numcomps; ++i) {
79  _opj_image->comps[i].data = reinterpret_cast<OPJ_INT32*> (malloc (data_size));
80  DCP_ASSERT (_opj_image->comps[i].data);
81  memcpy (_opj_image->comps[i].data, other._opj_image->comps[i].data, data_size);
82  }
83 
84  _opj_image->icc_profile_buf = reinterpret_cast<OPJ_BYTE*> (malloc (_opj_image->icc_profile_len));
85  DCP_ASSERT (_opj_image->icc_profile_buf);
86  memcpy (_opj_image->icc_profile_buf, other._opj_image->icc_profile_buf, _opj_image->icc_profile_len);
87 }
88 
89 
91 {
92  create (size);
93 }
94 
95 
96 OpenJPEGImage::OpenJPEGImage (uint8_t const * data_16, dcp::Size size, int stride)
97 {
98  create (size);
99 
100  int jn = 0;
101  for (int y = 0; y < size.height; ++y) {
102  uint16_t const * p = reinterpret_cast<uint16_t const *> (data_16 + y * stride);
103  for (int x = 0; x < size.width; ++x) {
104  /* Truncate 16-bit to 12-bit */
105  _opj_image->comps[0].data[jn] = *p++ >> 4;
106  _opj_image->comps[1].data[jn] = *p++ >> 4;
107  _opj_image->comps[2].data[jn] = *p++ >> 4;
108  ++jn;
109  }
110  }
111 }
112 
113 
114 void
115 OpenJPEGImage::create (Size size)
116 {
117  opj_image_cmptparm_t cmptparm[3];
118 
119  for (int i = 0; i < 3; ++i) {
120  cmptparm[i].dx = 1;
121  cmptparm[i].dy = 1;
122  cmptparm[i].w = size.width;
123  cmptparm[i].h = size.height;
124  cmptparm[i].x0 = 0;
125  cmptparm[i].y0 = 0;
126  cmptparm[i].prec = 12;
127  cmptparm[i].bpp = 12;
128  cmptparm[i].sgnd = 0;
129  }
130 
131  /* XXX: is this _SRGB right? */
132  _opj_image = opj_image_create (3, &cmptparm[0], OPJ_CLRSPC_SRGB);
133  if (_opj_image == nullptr) {
134  throw std::runtime_error ("could not create libopenjpeg image");
135  }
136 
137  _opj_image->x0 = 0;
138  _opj_image->y0 = 0;
139  _opj_image->x1 = size.width;
140  _opj_image->y1 = size.height;
141 }
142 
143 
144 OpenJPEGImage::~OpenJPEGImage ()
145 {
146  opj_image_destroy (_opj_image);
147 }
148 
149 
150 int *
151 OpenJPEGImage::data (int c) const
152 {
153  DCP_ASSERT (c >= 0 && c < 3);
154  return _opj_image->comps[c].data;
155 }
156 
157 
158 dcp::Size
160 {
161  /* XXX: this may not be right; x0 and y0 can presumably be non-zero */
162  return dcp::Size (_opj_image->x1, _opj_image->y1);
163 }
164 
165 
166 int
167 OpenJPEGImage::precision (int component) const
168 {
169  return _opj_image->comps[component].prec;
170 }
171 
172 
173 int
174 OpenJPEGImage::factor (int component) const
175 {
176  return _opj_image->comps[component].factor;
177 }
178 
179 
180 bool
181 OpenJPEGImage::srgb () const
182 {
183  return _opj_image->color_space == OPJ_CLRSPC_SRGB;
184 }
A wrapper of libopenjpeg's opj_image_t.
int * data(int) const
opj_image_t * _opj_image
opj_image_t that we are managing
OpenJPEGImage(opj_image_t *)
DCP_ASSERT macro.
Namespace for everything in libdcp.
Definition: array_data.h:50
OpenJPEGImage class.
The integer, two-dimensional size of something.
Definition: types.h:71