Some maths operations with Time.
[libdcp.git] / src / picture_frame.cc
1 /*
2     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <openjpeg.h>
21 #include "AS_DCP.h"
22 #include "KM_fileio.h"
23 #include "picture_frame.h"
24 #include "exceptions.h"
25 #include "argb_frame.h"
26 #include "lut.h"
27
28 using namespace std;
29 using namespace boost;
30 using namespace libdcp;
31
32 PictureFrame::PictureFrame (string mxf_path, int n)
33 {
34         ASDCP::JP2K::MXFReader reader;
35         if (ASDCP_FAILURE (reader.OpenRead (mxf_path.c_str()))) {
36                 throw FileError ("could not open MXF file for reading", mxf_path);
37         }
38
39         /* XXX: unfortunate guesswork on this buffer size */
40         _buffer = new ASDCP::JP2K::FrameBuffer (4 * Kumu::Megabyte);
41
42         if (ASDCP_FAILURE (reader.ReadFrame (n, *_buffer))) {
43                 throw DCPReadError ("could not read video frame");
44         }
45 }
46
47 PictureFrame::~PictureFrame ()
48 {
49         delete _buffer;
50 }
51
52 uint8_t const *
53 PictureFrame::data () const
54 {
55         return _buffer->RoData();
56 }
57
58 int
59 PictureFrame::size () const
60 {
61         return _buffer->Size ();
62 }
63
64 /** @return An ARGB representation of this frame.  This is ARGB in the
65  *  Cairo sense, so that each pixel takes up 4 bytes; the first byte
66  *  is blue, second green, third red and fourth alpha (always 255).
67  */
68 shared_ptr<ARGBFrame>
69 PictureFrame::argb_frame () const
70 {
71         /* JPEG2000 -> decompressed XYZ */
72         
73         opj_dinfo_t* decoder = opj_create_decompress (CODEC_J2K);
74         opj_dparameters_t parameters;
75         opj_set_default_decoder_parameters (&parameters);
76         opj_setup_decoder (decoder, &parameters);
77         opj_cio_t* cio = opj_cio_open ((opj_common_ptr) decoder, const_cast<unsigned char *> (data()), size());
78         opj_image_t* xyz_frame = opj_decode (decoder, cio);
79         if (!xyz_frame) {
80                 opj_destroy_decompress (decoder);
81                 opj_cio_close (cio);
82                 throw DCPReadError ("could not decode JPEG2000 codestream");
83         }
84         
85         assert (xyz_frame->numcomps == 3);
86         
87         /* XYZ -> RGB */
88         
89         struct {
90                 double x, y, z;
91         } s;
92         
93         struct {
94                 double r, g, b;
95         } d;
96         
97         int* xyz_x = xyz_frame->comps[0].data;
98         int* xyz_y = xyz_frame->comps[1].data;
99         int* xyz_z = xyz_frame->comps[2].data;
100
101         shared_ptr<ARGBFrame> argb_frame (new ARGBFrame (xyz_frame->x1, xyz_frame->y1));
102         
103         uint8_t* argb = argb_frame->data ();
104         
105         for (int y = 0; y < xyz_frame->y1; ++y) {
106                 uint8_t* argb_line = argb;
107                 for (int x = 0; x < xyz_frame->x1; ++x) {
108                         
109                         assert (*xyz_x >= 0 && *xyz_y >= 0 && *xyz_z >= 0 && *xyz_x < 4096 && *xyz_x < 4096 && *xyz_z < 4096);
110                         
111                         /* In gamma LUT */
112                         s.x = lut_in[*xyz_x++];
113                         s.y = lut_in[*xyz_y++];
114                         s.z = lut_in[*xyz_z++];
115                         
116                         /* DCI companding */
117                         s.x /= DCI_COEFFICIENT;
118                         s.y /= DCI_COEFFICIENT;
119                         s.z /= DCI_COEFFICIENT;
120                         
121                         /* XYZ to RGB */
122                         d.r = ((s.x * color_matrix[0][0]) + (s.y * color_matrix[0][1]) + (s.z * color_matrix[0][2]));
123                         d.g = ((s.x * color_matrix[1][0]) + (s.y * color_matrix[1][1]) + (s.z * color_matrix[1][2]));
124                         d.b = ((s.x * color_matrix[2][0]) + (s.y * color_matrix[2][1]) + (s.z * color_matrix[2][2]));
125                         
126                         d.r = min (d.r, 1.0);
127                         d.r = max (d.r, 0.0);
128                         
129                         d.g = min (d.g, 1.0);
130                         d.g = max (d.g, 0.0);
131                         
132                         d.b = min (d.b, 1.0);
133                         d.b = max (d.b, 0.0);
134                         
135                         /* Out gamma LUT */
136                         *argb_line++ = lut_out[(int) (d.b * COLOR_DEPTH)];
137                         *argb_line++ = lut_out[(int) (d.g * COLOR_DEPTH)];
138                         *argb_line++ = lut_out[(int) (d.r * COLOR_DEPTH)];
139                         *argb_line++ = 0xff;
140                 }
141                 
142                 argb += argb_frame->stride ();
143         }
144         
145         opj_cio_close (cio);
146         opj_image_destroy (xyz_frame);
147
148         return argb_frame;
149 }