Visual Servoing Platform  version 3.6.1 under development (2024-05-05)
testIoEXR.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
5  *
6  * This software 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  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See https://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Test image I/O for EXR file format.
33  *
34 *****************************************************************************/
35 
42 #include <visp3/core/vpConfig.h>
43 
44 // EXR format is only supported when OpenCV or TinyEXR 3rd parties are available
45 #if defined(VISP_HAVE_CATCH2) && (VISP_HAVE_DATASET_VERSION >= 0x030600) && \
46  defined(HAVE_OPENCV_IMGCODECS) && defined(VISP_HAVE_TINYEXR)
47 #define CATCH_CONFIG_RUNNER
48 #include <catch.hpp>
49 
50 #include <iostream>
51 #include <limits>
52 #include <visp3/core/vpEndian.h>
53 #include <visp3/core/vpIoTools.h>
54 #include <visp3/io/vpImageIo.h>
55 
56 namespace
57 {
58 #ifdef VISP_LITTLE_ENDIAN
59 void checkColorImages(const vpImage<vpRGBf> &I1, const vpImage<vpRGBf> &I2,
60  float epsilon = std::numeric_limits<float>::epsilon())
61 {
62  for (unsigned int i = 0; i < I1.getHeight(); i++) {
63  for (unsigned int j = 0; j < I1.getWidth(); j++) {
64  REQUIRE(vpMath::equal(I1[i][j].R, I2[i][j].R, epsilon));
65  REQUIRE(vpMath::equal(I1[i][j].G, I2[i][j].G, epsilon));
66  REQUIRE(vpMath::equal(I1[i][j].B, I2[i][j].B, epsilon));
67  }
68  }
69 }
70 
71 void checkGrayImages(const vpImage<float> &I1, const vpImage<float> &I2,
72  float epsilon = std::numeric_limits<float>::epsilon())
73 {
74  for (unsigned int i = 0; i < I1.getHeight(); i++) {
75  for (unsigned int j = 0; j < I1.getWidth(); j++) {
76  REQUIRE(vpMath::equal(I1[i][j], I2[i][j], epsilon));
77  }
78  }
79 }
80 #endif
81 } // namespace
82 
83 TEST_CASE("EXR image read", "[exr_image_io]")
84 {
85 // Disable the tests if big endian for now.
86 // See: https://github.com/syoyo/tinyexr/issues/189#issuecomment-1465174904
87 #ifdef VISP_LITTLE_ENDIAN
88  SECTION("Color")
89  {
90  const std::string imgPathRef = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "memorial/memorial_color_LSB.pfm");
91  REQUIRE(vpIoTools::checkFilename(imgPathRef));
92 
93  vpImage<vpRGBf> I_ref;
94  vpImageIo::readPFM_HDR(I_ref, imgPathRef);
95  CHECK(I_ref.getSize() > 0);
96 
97  SECTION("32-bits")
98  {
99  const std::string imgPath =
100  vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "memorial/memorial_color_32bits.exr");
101  REQUIRE(vpIoTools::checkFilename(imgPath));
102 
103  vpImage<vpRGBf> I;
104  vpImageIo::readEXR(I, imgPath);
105  CHECK(I.getSize() > 0);
106  checkColorImages(I_ref, I);
107  }
108 
109  SECTION("16-bits")
110  {
111  const std::string imgPath =
112  vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "memorial/memorial_color_16bits.exr");
113  REQUIRE(vpIoTools::checkFilename(imgPath));
114 
115  vpImage<vpRGBf> I;
116  vpImageIo::readEXR(I, imgPath);
117  CHECK(I.getSize() > 0);
118  checkColorImages(I_ref, I, 0.00097656f);
119  }
120  }
121 
122  SECTION("Gray")
123  {
124  const std::string imgPathRef =
125  vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "memorial/memorial_gray_LSB.pfm");
126  REQUIRE(vpIoTools::checkFilename(imgPathRef));
127 
128  vpImage<float> I_ref;
129  vpImageIo::readPFM_HDR(I_ref, imgPathRef);
130  CHECK(I_ref.getSize() > 0);
131 
132  SECTION("32-bits")
133  {
134  const std::string imgPath =
135  vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "memorial/memorial_gray_32bits.exr");
136  REQUIRE(vpIoTools::checkFilename(imgPath));
137 
138  vpImage<float> I;
139  vpImageIo::readEXR(I, imgPath);
140  CHECK(I.getSize() > 0);
141  checkGrayImages(I_ref, I);
142  }
143 
144  SECTION("16-bits")
145  {
146  const std::string imgPath =
147  vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "memorial/memorial_gray_16bits.exr");
148  REQUIRE(vpIoTools::checkFilename(imgPath));
149 
150  vpImage<float> I;
151  vpImageIo::readEXR(I, imgPath);
152  CHECK(I.getSize() > 0);
153  checkGrayImages(I_ref, I, 0.00097656f);
154  }
155  }
156 #endif
157 }
158 
159 TEST_CASE("EXR image write", "[exr_image_io]")
160 {
161 #ifdef VISP_LITTLE_ENDIAN
162  std::string tmp_dir = vpIoTools::makeTempDirectory(vpIoTools::getTempPath());
163  std::string directory_filename_tmp = tmp_dir + "/testIoEXR_" + vpTime::getDateTime("%Y-%m-%d_%H.%M.%S");
164  vpIoTools::makeDirectory(directory_filename_tmp);
165  REQUIRE(vpIoTools::checkDirectory(directory_filename_tmp));
166 
167  SECTION("Color")
168  {
169  const std::string imgPath =
170  vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "memorial/memorial_color_32bits.exr");
171  REQUIRE(vpIoTools::checkFilename(imgPath));
172 
173  vpImage<vpRGBf> I;
174  vpImageIo::readEXR(I, imgPath);
175  REQUIRE(I.getSize() > 0);
176 
177  vpImageIo::writeEXR(I, vpIoTools::createFilePath(directory_filename_tmp, "write_color_exr.exr"));
178  vpImage<vpRGBf> I_write;
179  vpImageIo::readEXR(I_write, vpIoTools::createFilePath(directory_filename_tmp, "write_color_exr.exr"));
180 
181  REQUIRE(I.getHeight() == I_write.getHeight());
182  REQUIRE(I.getWidth() == I_write.getWidth());
183 
184  checkColorImages(I, I_write);
185  }
186 
187  SECTION("Gray")
188  {
189  const std::string imgPath =
190  vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "memorial/memorial_gray_32bits.exr");
191  REQUIRE(vpIoTools::checkFilename(imgPath));
192 
193  vpImage<float> I;
194  vpImageIo::readEXR(I, imgPath);
195  REQUIRE(I.getSize() > 0);
196 
197  vpImageIo::writeEXR(I, vpIoTools::createFilePath(directory_filename_tmp, "write_gray_exr.exr"));
198  vpImage<float> I_write;
199  vpImageIo::readEXR(I_write, vpIoTools::createFilePath(directory_filename_tmp, "write_gray_exr.exr"));
200 
201  REQUIRE(I.getHeight() == I_write.getHeight());
202  REQUIRE(I.getWidth() == I_write.getWidth());
203 
204  checkGrayImages(I, I_write);
205  }
206 
207  CHECK(vpIoTools::remove(directory_filename_tmp));
208  CHECK(vpIoTools::remove(tmp_dir));
209 #endif
210 }
211 
212 int main(int argc, char *argv[])
213 {
214  Catch::Session session; // There must be exactly one instance
215 
216  // Let Catch (using Clara) parse the command line
217  session.applyCommandLine(argc, argv);
218 
219  int numFailed = session.run();
220 
221  // numFailed is clamped to 255 as some unices only use the lower 8 bits.
222  // This clamping has already been applied, so just return it here
223  // You can also do any post run clean-up here
224  return numFailed;
225 }
226 #else
227 int main() { return EXIT_SUCCESS; }
228 #endif
static void readPFM_HDR(vpImage< float > &I, const std::string &filename)
Definition: vpImageIo.cpp:1347
static void readEXR(vpImage< float > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:723
static void writeEXR(const vpImage< float > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:1200
Definition of the vpImage class member functions.
Definition: vpImage.h:69
unsigned int getWidth() const
Definition: vpImage.h:245
unsigned int getSize() const
Definition: vpImage.h:224
unsigned int getHeight() const
Definition: vpImage.h:184
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1832
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:1213
static std::string getTempPath()
Definition: vpIoTools.cpp:601
static bool checkDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:832
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:2195
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:981
static bool remove(const std::string &filename)
Definition: vpIoTools.cpp:1348
static std::string makeTempDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:1135
static bool equal(double x, double y, double threshold=0.001)
Definition: vpMath.h:449
VISP_EXPORT std::string getDateTime(const std::string &format="%Y/%m/%d %H:%M:%S")