X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=test%2Frgb_xyz_test.cc;h=cf42957b2597868cf07db129822af742bb79a2d3;hb=a4b28be9b47ca541bda1153feca9a37bbb304be6;hp=b33a0f4ac30106adb3b73a1d96b2c31cc10303de;hpb=9655ed4740f08899698052f232256fcf7b77c58e;p=libdcp.git diff --git a/test/rgb_xyz_test.cc b/test/rgb_xyz_test.cc index b33a0f4a..cf42957b 100644 --- a/test/rgb_xyz_test.cc +++ b/test/rgb_xyz_test.cc @@ -1,82 +1,59 @@ /* - Copyright (C) 2014 Carl Hetherington + Copyright (C) 2014-2015 Carl Hetherington - This program is free software; you can redistribute it and/or modify + This file is part of libdcp. + + libdcp 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, + libdcp 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. - + along with libdcp. If not, see . */ -#include "image.h" #include "rgb_xyz.h" -#include "xyz_frame.h" +#include "openjpeg_image.h" #include "colour_conversion.h" #include +#include +#include using std::max; +using std::list; +using std::string; +using std::cout; using boost::shared_ptr; - -class SimpleImage : public dcp::Image -{ -public: - SimpleImage (dcp::Size size) - : Image (size) - { - /* 48bpp */ - _stride[0] = _size.width * 6; - _data[0] = new uint16_t[size.height * stride()[0] / 2]; - } - - ~SimpleImage () - { - delete[] _data[0]; - } - - uint16_t * const * data () const { - return _data; - } - - int const * stride () const { - return _stride; - } - -private: - uint16_t* _data[1]; - int _stride[1]; -}; +using boost::optional; +using boost::scoped_array; /** Convert a test image from sRGB to XYZ and check that the transforms are right */ BOOST_AUTO_TEST_CASE (rgb_xyz_test) { - unsigned int seed = 0; + srand (0); dcp::Size const size (640, 480); - shared_ptr rgb (new SimpleImage (size)); + scoped_array rgb (new uint8_t[size.width * size.height * 6]); for (int y = 0; y < size.height; ++y) { - uint16_t* p = rgb->data()[0] + y * rgb->stride()[0] / 2; + uint16_t* p = reinterpret_cast (rgb.get() + y * size.width * 6); for (int x = 0; x < size.width; ++x) { /* Write a 12-bit random number for each component */ for (int c = 0; c < 3; ++c) { - *p = (rand_r (&seed) & 0xfff) << 4; + *p = (rand () & 0xfff) << 4; ++p; } } } - shared_ptr xyz = dcp::rgb_to_xyz (rgb, dcp::ColourConversion::srgb_to_xyz); + shared_ptr xyz = dcp::rgb_to_xyz (rgb.get(), size, size.width * 6, dcp::ColourConversion::srgb_to_xyz ()); for (int y = 0; y < size.height; ++y) { - uint16_t* p = rgb->data()[0] + y * rgb->stride()[0] / 2; + uint16_t* p = reinterpret_cast (rgb.get() + y * size.width * 6); for (int x = 0; x < size.width; ++x) { double cr = *p++ / 65535.0; @@ -127,3 +104,93 @@ BOOST_AUTO_TEST_CASE (rgb_xyz_test) } } } + +static list notes; + +static void +note_handler (dcp::NoteType n, string s) +{ + BOOST_REQUIRE_EQUAL (n, dcp::DCP_NOTE); + notes.push_back (s); +} + +/** Check that xyz_to_rgb clamps XYZ values correctly */ +BOOST_AUTO_TEST_CASE (xyz_rgb_range_test) +{ + shared_ptr xyz (new dcp::OpenJPEGImage (dcp::Size (2, 2))); + + xyz->data(0)[0] = -4; + xyz->data(0)[1] = 6901; + xyz->data(0)[2] = 0; + xyz->data(0)[3] = 4095; + xyz->data(1)[0] = -4; + xyz->data(1)[1] = 6901; + xyz->data(1)[2] = 0; + xyz->data(1)[3] = 4095; + xyz->data(2)[0] = -4; + xyz->data(2)[1] = 6901; + xyz->data(2)[2] = 0; + xyz->data(2)[3] = 4095; + + scoped_array rgb (new uint8_t[2 * 2 * 6]); + + notes.clear (); + dcp::xyz_to_rgb ( + xyz, dcp::ColourConversion::srgb_to_xyz (), rgb.get(), 2 * 6, boost::optional (boost::bind (¬e_handler, _1, _2)) + ); + + /* The 6 out-of-range samples should have been noted */ + BOOST_REQUIRE_EQUAL (notes.size(), 6); + list::const_iterator i = notes.begin (); + BOOST_REQUIRE_EQUAL (*i++, "XYZ value -4 out of range"); + BOOST_REQUIRE_EQUAL (*i++, "XYZ value -4 out of range"); + BOOST_REQUIRE_EQUAL (*i++, "XYZ value -4 out of range"); + BOOST_REQUIRE_EQUAL (*i++, "XYZ value 6901 out of range"); + BOOST_REQUIRE_EQUAL (*i++, "XYZ value 6901 out of range"); + BOOST_REQUIRE_EQUAL (*i++, "XYZ value 6901 out of range"); + + /* And those samples should have been clamped, so check that they give the same result + as inputs at the extremes (0 and 4095). + */ + + uint16_t* buffer = reinterpret_cast (rgb.get ()); + BOOST_REQUIRE_EQUAL (buffer[0 * 3 + 0], buffer[2 * 3 + 1]); + BOOST_REQUIRE_EQUAL (buffer[0 * 3 + 1], buffer[2 * 3 + 1]); + BOOST_REQUIRE_EQUAL (buffer[0 * 3 + 2], buffer[2 * 3 + 2]); + + BOOST_REQUIRE_EQUAL (buffer[1 * 3 + 0], buffer[3 * 3 + 0]); + BOOST_REQUIRE_EQUAL (buffer[1 * 3 + 1], buffer[3 * 3 + 1]); + BOOST_REQUIRE_EQUAL (buffer[1 * 3 + 2], buffer[3 * 3 + 2]); +} + +/** Convert an image from RGB to XYZ and back again */ +BOOST_AUTO_TEST_CASE (rgb_xyz_round_trip_test) +{ + srand (0); + dcp::Size const size (640, 480); + + scoped_array rgb (new uint8_t[size.width * size.height * 6]); + for (int y = 0; y < size.height; ++y) { + uint16_t* p = reinterpret_cast (rgb.get() + y * size.width * 6); + for (int x = 0; x < size.width; ++x) { + /* Write a 12-bit random number for each component */ + for (int c = 0; c < 3; ++c) { + *p = (rand () & 0xfff) << 4; + ++p; + } + } + } + + shared_ptr xyz = dcp::rgb_to_xyz (rgb.get(), size, size.width * 6, dcp::ColourConversion::srgb_to_xyz ()); + scoped_array back (new uint8_t[size.width * size.height * 6]); + dcp::xyz_to_rgb (xyz, dcp::ColourConversion::srgb_to_xyz (), back.get(), size.width * 6); + +#if 0 + uint16_t* p = reinterpret_cast (rgb.get ()); + uint16_t* q = reinterpret_cast (back.get ()); + for (int i = 0; i < (size.width * size.height); ++i) { + /* XXX: doesn't quite work */ + // BOOST_REQUIRE_EQUAL (*p++, *q++); + } +#endif +}