doc/html
doc/latex
src/version.cc
-src/lut.cc
-src/lut.h
*.pyc
__pycache__
GPATH
+++ /dev/null
-from __future__ import print_function
-import math
-
-BIT_DEPTH = 12
-DCI_GAMMA = 2.6
-SRGB_GAMMA = 2.4;
-BIT_LENGTH = int(math.pow(2, BIT_DEPTH))
-COLOR_DEPTH = BIT_LENGTH - 1
-
-def boilerplate(f):
- print("""/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-
-/* This file is auto-generated by the build scripts; edits will be lost
- on ./waf configure.
-*/
-""", file=f)
-
-def make_luts():
- cc = open('src/lut.cc', 'w')
-
- boilerplate(cc)
-
- print("#include \"lut.h\"", file=cc)
-
- print("""
-/* sRGB color matrix for XYZ -> RGB */
-float color_matrix[3][3] = {
- { 3.240454836, -1.537138850, -0.498531547},
- {-0.969266390, 1.876010929, 0.041556082},
- { 0.055643420, -0.204025854, 1.057225162}
-};\n\n
-""", file=cc)
-
- print("""
-float lut_in[COLOR_DEPTH + 1] = {\n
-\t/* Bit depth: %d
-\t * Reference white: DCI
-\t * Gamma: %f
-\t */
-""" % (BIT_DEPTH, DCI_GAMMA), file=cc)
-
- c = 0
- for i in range(0, BIT_LENGTH):
- v = math.pow (i / (BIT_LENGTH - 1.0), DCI_GAMMA);
-
- if (c == 0):
- print(" ", end='', file=cc)
-
- if i < BIT_LENGTH - 1:
- print("%06f, " % v, end="", file=cc)
- if c == 12:
- c = 0;
- print("", file=cc)
- else:
- c += 1
- else:
- print("%06f" % v, file=cc)
-
- print("};", file=cc)
-
- print("""
-int lut_out[COLOR_DEPTH + 1] = {
-\t/* Bit depth: %d
-\t * Reference white: sRGB
-\t * Gamma: %f
-\t */
-""", file=cc)
-
- c = 0
- for i in range (0, BIT_LENGTH):
- v = i / (BIT_LENGTH - 1.0)
-
- if (v < (0.04045 / 12.92)):
- v *= 12.92
- else:
- v = (1.055 * pow (v, (1 / SRGB_GAMMA))) - 0.055
-
- v *= 255
-
- if c == 0:
- print(" ", end="", file=cc)
-
- if i < BIT_LENGTH - 1:
- print("%d, " % v, end="", file=cc)
- if c == 12:
- c = 0;
- print("", file=cc)
- else:
- c += 1
- else:
- print("%d" % v, file=cc)
-
- print("};", file=cc)
-
- h = open('src/lut.h', 'w')
-
- boilerplate(h)
-
- print("""
-#define COLOR_DEPTH (%d)
-#define DCI_COEFFICIENT (48.0/52.37)
-
-extern float color_matrix[3][3];
-extern int lut_out[COLOR_DEPTH + 1];
-extern float lut_in[COLOR_DEPTH + 1];
-""" % COLOR_DEPTH, file=h)
-
-if __name__ == "__main__":
- make_luts()
--- /dev/null
+#include <cmath>
+#include "gamma_lut.h"
+#include "lut_cache.h"
+
+using namespace libdcp;
+
+LUTCache<GammaLUT> GammaLUT::cache;
+
+GammaLUT::GammaLUT(int bits, float gamma)
+ : LUT<float> (bits, gamma)
+{
+ int const bit_length = pow(2, bits);
+ for (int i = 0; i < bit_length; ++i) {
+ _lut[i] = pow(float(i) / (bit_length - 1), gamma);
+ }
+}
--- /dev/null
+#include "lut.h"
+#include "lut_cache.h"
+
+namespace libdcp {
+
+class GammaLUT : public LUT<float>
+{
+public:
+ GammaLUT (int bit_length, float gamma);
+ static LUTCache<GammaLUT> cache;
+};
+
+}
--- /dev/null
+/*
+ Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LIBDCP_LUT_H
+#define LIBDCP_LUT_H
+
+#include <cmath>
+
+namespace libdcp {
+
+template<typename T>
+class LUT
+{
+public:
+ LUT(int bit_depth, float gamma)
+ : _lut(0)
+ , _bit_depth (bit_depth)
+ , _gamma (gamma)
+ {
+ _lut = new T[int(std::pow(2, _bit_depth))];
+ }
+
+ virtual ~LUT() {
+ delete[] _lut;
+ }
+
+ T const * lut() const {
+ return _lut;
+ }
+
+ int bit_depth () const {
+ return _bit_depth;
+ }
+
+ float gamma () const {
+ return _gamma;
+ }
+
+protected:
+ T* _lut;
+ int _bit_depth;
+ float _gamma;
+};
+
+}
+
+#endif
--- /dev/null
+#ifndef LIBDCP_LUT_CACHE_H
+#define LIBDCP_LUT_CACHE_H
+
+#include <list>
+#include <boost/shared_ptr.hpp>
+
+template<class T>
+class LUTCache
+{
+public:
+ boost::shared_ptr<T> get (int bit_depth, float gamma)
+ {
+ for (typename std::list<boost::shared_ptr<T> >::iterator i = _cache.begin(); i != _cache.end(); ++i) {
+ if ((*i)->bit_depth() == bit_depth && (*i)->gamma() == gamma) {
+ return *i;
+ }
+ }
+
+ boost::shared_ptr<T> lut (new T (bit_depth, gamma));
+ _cache.push_back (lut);
+ return lut;
+ }
+
+private:
+ std::list<boost::shared_ptr<T> > _cache;
+};
+
+#endif
#include "argb_frame.h"
#include "lut.h"
#include "util.h"
+#include "gamma_lut.h"
+#include "xyz_srgb_lut.h"
+
+#define DCI_GAMMA 2.6
using std::string;
using boost::shared_ptr;
*
*/
shared_ptr<ARGBFrame>
-MonoPictureFrame::argb_frame (int reduce) const
+MonoPictureFrame::argb_frame (int reduce, float srgb_gamma) const
{
opj_image_t* xyz_frame = decompress_j2k (const_cast<uint8_t*> (_buffer->RoData()), _buffer->Size(), reduce);
assert (xyz_frame->numcomps == 3);
- shared_ptr<ARGBFrame> f = xyz_to_rgb (xyz_frame);
+ shared_ptr<ARGBFrame> f = xyz_to_rgb (xyz_frame, GammaLUT::cache.get (12, DCI_GAMMA), XYZsRGBLUT::cache.get (12, srgb_gamma));
opj_image_destroy (xyz_frame);
return f;
}
*
*/
shared_ptr<ARGBFrame>
-StereoPictureFrame::argb_frame (Eye eye, int reduce) const
+StereoPictureFrame::argb_frame (Eye eye, int reduce, float srgb_gamma) const
{
opj_image_t* xyz_frame = 0;
switch (eye) {
}
assert (xyz_frame->numcomps == 3);
- shared_ptr<ARGBFrame> f = xyz_to_rgb (xyz_frame);
+ shared_ptr<ARGBFrame> f = xyz_to_rgb (xyz_frame, GammaLUT::cache.get (12, DCI_GAMMA), XYZsRGBLUT::cache.get (12, srgb_gamma));
opj_image_destroy (xyz_frame);
return f;
}
MonoPictureFrame (std::string mxf_path, int n);
~MonoPictureFrame ();
- boost::shared_ptr<ARGBFrame> argb_frame (int reduce = 0) const;
+ boost::shared_ptr<ARGBFrame> argb_frame (int reduce = 0, float srgb_gamma = 2.4) const;
uint8_t const * j2k_data () const;
int j2k_size () const;
StereoPictureFrame (std::string mxf_path, int n);
~StereoPictureFrame ();
- boost::shared_ptr<ARGBFrame> argb_frame (Eye eye, int reduce = 0) const;
+ boost::shared_ptr<ARGBFrame> argb_frame (Eye eye, int reduce = 0, float srgb_gamma = 2.4) const;
uint8_t const * left_j2k_data () const;
int left_j2k_size () const;
uint8_t const * right_j2k_data () const;
#include "exceptions.h"
#include "types.h"
#include "argb_frame.h"
-#include "lut.h"
+#include "gamma_lut.h"
+#include "xyz_srgb_lut.h"
using std::string;
using std::stringstream;
* @return RGB image.
*/
shared_ptr<ARGBFrame>
-libdcp::xyz_to_rgb (opj_image_t* xyz_frame)
+libdcp::xyz_to_rgb (opj_image_t* xyz_frame, shared_ptr<const GammaLUT> lut_in, shared_ptr<const XYZsRGBLUT> lut_out)
{
+ float const dci_coefficient = 48.0 / 52.37;
+
+ /* sRGB color matrix for XYZ -> RGB */
+ float const colour_matrix[3][3] = {
+ { 3.240454836, -1.537138850, -0.498531547},
+ {-0.969266390, 1.876010929, 0.041556082},
+ { 0.055643420, -0.204025854, 1.057225162}
+ };
+
+ int const max_colour = pow (2, lut_out->bit_depth()) - 1;
+
struct {
double x, y, z;
} s;
assert (*xyz_x >= 0 && *xyz_y >= 0 && *xyz_z >= 0 && *xyz_x < 4096 && *xyz_x < 4096 && *xyz_z < 4096);
/* In gamma LUT */
- s.x = lut_in[*xyz_x++];
- s.y = lut_in[*xyz_y++];
- s.z = lut_in[*xyz_z++];
+ s.x = lut_in->lut()[*xyz_x++];
+ s.y = lut_in->lut()[*xyz_y++];
+ s.z = lut_in->lut()[*xyz_z++];
/* DCI companding */
- s.x /= DCI_COEFFICIENT;
- s.y /= DCI_COEFFICIENT;
- s.z /= DCI_COEFFICIENT;
+ s.x /= dci_coefficient;
+ s.y /= dci_coefficient;
+ s.z /= dci_coefficient;
/* XYZ to RGB */
- d.r = ((s.x * color_matrix[0][0]) + (s.y * color_matrix[0][1]) + (s.z * color_matrix[0][2]));
- d.g = ((s.x * color_matrix[1][0]) + (s.y * color_matrix[1][1]) + (s.z * color_matrix[1][2]));
- d.b = ((s.x * color_matrix[2][0]) + (s.y * color_matrix[2][1]) + (s.z * color_matrix[2][2]));
+ d.r = ((s.x * colour_matrix[0][0]) + (s.y * colour_matrix[0][1]) + (s.z * colour_matrix[0][2]));
+ d.g = ((s.x * colour_matrix[1][0]) + (s.y * colour_matrix[1][1]) + (s.z * colour_matrix[1][2]));
+ d.b = ((s.x * colour_matrix[2][0]) + (s.y * colour_matrix[2][1]) + (s.z * colour_matrix[2][2]));
d.r = min (d.r, 1.0);
d.r = max (d.r, 0.0);
d.b = max (d.b, 0.0);
/* Out gamma LUT */
- *argb_line++ = lut_out[(int) (d.b * COLOR_DEPTH)];
- *argb_line++ = lut_out[(int) (d.g * COLOR_DEPTH)];
- *argb_line++ = lut_out[(int) (d.r * COLOR_DEPTH)];
+ *argb_line++ = lut_out->lut()[(int) (d.b * max_colour)];
+ *argb_line++ = lut_out->lut()[(int) (d.g * max_colour)];
+ *argb_line++ = lut_out->lut()[(int) (d.r * max_colour)];
*argb_line++ = 0xff;
}
namespace libdcp {
class ARGBFrame;
+class GammaLUT;
+class XYZsRGBLUT;
struct Size {
Size ()
extern ContentKind content_kind_from_string (std::string kind);
extern bool empty_or_white_space (std::string s);
extern opj_image_t* decompress_j2k (uint8_t* data, int64_t size, int reduce);
-extern boost::shared_ptr<ARGBFrame> xyz_to_rgb (opj_image_t* xyz_frame);
+extern boost::shared_ptr<ARGBFrame> xyz_to_rgb (opj_image_t* xyz_frame, boost::shared_ptr<const GammaLUT>, boost::shared_ptr<const XYZsRGBLUT>);
}
cpl_file.cc
dcp.cc
dcp_time.cc
- lut.cc
+ gamma_lut.cc
metadata.cc
mxf_asset.cc
picture_asset.cc
util.cc
version.cc
xml.cc
+ xyz_srgb_lut.cc
"""
headers = """
--- /dev/null
+#include <iostream>
+#include <cmath>
+#include "xyz_srgb_lut.h"
+
+using namespace libdcp;
+
+LUTCache<XYZsRGBLUT> XYZsRGBLUT::cache;
+
+XYZsRGBLUT::XYZsRGBLUT(int bits, float gamma)
+ : LUT<int> (bits, gamma)
+{
+ int const bit_length = pow(2, bits);
+
+ for (int i = 0; i < bit_length; ++i) {
+ float v = float(i) / (bit_length - 1);
+ if (v < (0.04045 / 12.92)) {
+ v *= 12.92;
+ } else {
+ v = (1.055 * pow (v, (1 / gamma))) - 0.055;
+ }
+
+ _lut[i] = int(v * 255);
+ }
+}
--- /dev/null
+#include "lut.h"
+#include "lut_cache.h"
+
+namespace libdcp {
+
+class XYZsRGBLUT : public LUT<int>
+{
+public:
+ XYZsRGBLUT(int colour_depth, float gamma);
+ static LUTCache<XYZsRGBLUT> cache;
+};
+
+}
#include "picture_asset.h"
#include "sound_asset.h"
#include "reel.h"
+#include "gamma_lut.h"
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE libdcp_test
import subprocess
import os
-import lut
APPNAME = 'libdcp'
VERSION = '0.40pre'
msg = 'Checking for boost signals2 library',
uselib_store = 'BOOST_SIGNALS2')
- lut.make_luts()
-
conf.recurse('test')
conf.recurse('asdcplib')