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