Browse Source

AnyImageConverter: add conversion of 3D and multi-level 2D/3D images.

Now that OpenExrImageConverter has cubemap and multi-level support we
can finally add and test these code paths.
pull/537/head
Vladimír Vondruš 5 years ago
parent
commit
a130f26797
  1. 2
      doc/changelog.dox
  2. 126
      src/MagnumPlugins/AnyImageConverter/AnyImageConverter.cpp
  3. 454
      src/MagnumPlugins/AnyImageConverter/Test/AnyImageConverterTest.cpp
  4. 14
      src/MagnumPlugins/AnyImageConverter/Test/CMakeLists.txt
  5. 1
      src/MagnumPlugins/AnyImageConverter/Test/configure.h.cmake
  6. BIN
      src/MagnumPlugins/AnyImageImporter/Test/cube.exr

2
doc/changelog.dox

@ -361,6 +361,8 @@ See also:
plugin to apply the option to with `-I` / `-C`. For better usability, the
plugins also warn if the user specifies and option that is not present in
the target implementation.
- @relativeref{Trade,AnyImageConverter} now implements also conversion of 3D
and multi-level 2D/3D images for formats that support it (such as OpenEXR)
- Added @ref Trade::PhongMaterialData::hasCommonTextureTransformation(),
@ref Trade::PhongMaterialData::ambientTextureMatrix(),
@ref Trade::PhongMaterialData::diffuseTextureMatrix(),

126
src/MagnumPlugins/AnyImageConverter/AnyImageConverter.cpp

@ -133,13 +133,47 @@ bool AnyImageConverter::doConvertToFile(const ImageView2D& image, const Containe
return converter->convertToFile(image, filename);
}
bool AnyImageConverter::doConvertToFile(const ImageView3D&, const Containers::StringView filename) {
bool AnyImageConverter::doConvertToFile(const ImageView3D& image, const Containers::StringView filename) {
CORRADE_INTERNAL_ASSERT(manager());
/* No file formats to store 3D data yet */
/** @todo once Directory is std::string-free, use splitExtension(), but
only if we don't detect more than one extension yet */
const Containers::String normalized = Utility::String::lowercase(filename);
Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a 3D image";
return false;
/* Detect the plugin from extension */
Containers::StringView plugin;
if(normalized.hasSuffix(".exr"_s))
plugin = "OpenExrImageConverter"_s;
else {
Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a 3D image";
return false;
}
/* Try to load the plugin */
if(!(manager()->load(plugin) & PluginManager::LoadState::Loaded)) {
Error{} << "Trade::AnyImageConverter::convertToFile(): cannot load the" << plugin << "plugin";
return false;
}
const PluginManager::PluginMetadata* const metadata = manager()->metadata(plugin);
CORRADE_INTERNAL_ASSERT(metadata);
if(flags() & ImageConverterFlag::Verbose) {
Debug d;
d << "Trade::AnyImageConverter::convertToFile(): using" << plugin;
if(plugin != metadata->name())
d << "(provided by" << metadata->name() << Debug::nospace << ")";
}
/* Instantiate the plugin, propagate flags */
Containers::Pointer<AbstractImageConverter> converter = static_cast<PluginManager::Manager<AbstractImageConverter>*>(manager())->instantiate(plugin);
converter->setFlags(flags());
/* Propagate configuration */
Magnum::Implementation::propagateConfiguration("Trade::AnyImageConverter::convertToFile():", {}, metadata->name(), configuration(), converter->configuration());
/* Try to convert the file (error output should be printed by the plugin
itself) */
return converter->convertToFile(image, filename);
}
bool AnyImageConverter::doConvertToFile(const CompressedImageView1D&, const Containers::StringView filename) {
@ -178,22 +212,90 @@ bool AnyImageConverter::doConvertToFile(Containers::ArrayView<const ImageView1D>
return false;
}
bool AnyImageConverter::doConvertToFile(Containers::ArrayView<const ImageView2D>, const Containers::StringView filename) {
bool AnyImageConverter::doConvertToFile(const Containers::ArrayView<const ImageView2D> imageLevels, const Containers::StringView filename) {
CORRADE_INTERNAL_ASSERT(manager());
/* No file formats to store multi-level 2D data yet */
/** @todo once Directory is std::string-free, use splitExtension(), but
only if we don't detect more than one extension yet */
const Containers::String normalized = Utility::String::lowercase(filename);
Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a multi-level 2D image";
return false;
/* Detect the plugin from extension */
Containers::StringView plugin;
if(normalized.hasSuffix(".exr"_s))
plugin = "OpenExrImageConverter"_s;
else {
Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a multi-level 2D image";
return false;
}
/* Try to load the plugin */
if(!(manager()->load(plugin) & PluginManager::LoadState::Loaded)) {
Error{} << "Trade::AnyImageConverter::convertToFile(): cannot load the" << plugin << "plugin";
return false;
}
const PluginManager::PluginMetadata* const metadata = manager()->metadata(plugin);
CORRADE_INTERNAL_ASSERT(metadata);
if(flags() & ImageConverterFlag::Verbose) {
Debug d;
d << "Trade::AnyImageConverter::convertToFile(): using" << plugin;
if(plugin != metadata->name())
d << "(provided by" << metadata->name() << Debug::nospace << ")";
}
/* Instantiate the plugin, propagate flags */
Containers::Pointer<AbstractImageConverter> converter = static_cast<PluginManager::Manager<AbstractImageConverter>*>(manager())->instantiate(plugin);
converter->setFlags(flags());
/* Propagate configuration */
Magnum::Implementation::propagateConfiguration("Trade::AnyImageConverter::convertToFile():", {}, metadata->name(), configuration(), converter->configuration());
/* Try to convert the file (error output should be printed by the plugin
itself) */
return converter->convertToFile(imageLevels, filename);
}
bool AnyImageConverter::doConvertToFile(Containers::ArrayView<const ImageView3D>, const Containers::StringView filename) {
bool AnyImageConverter::doConvertToFile(const Containers::ArrayView<const ImageView3D> imageLevels, const Containers::StringView filename) {
CORRADE_INTERNAL_ASSERT(manager());
/* No file formats to store multi-level 3D data yet */
/** @todo once Directory is std::string-free, use splitExtension(), but
only if we don't detect more than one extension yet */
const Containers::String normalized = Utility::String::lowercase(filename);
Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a multi-level 3D image";
return false;
/* Detect the plugin from extension */
Containers::StringView plugin;
if(normalized.hasSuffix(".exr"_s))
plugin = "OpenExrImageConverter"_s;
else {
Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a multi-level 3D image";
return false;
}
/* Try to load the plugin */
if(!(manager()->load(plugin) & PluginManager::LoadState::Loaded)) {
Error{} << "Trade::AnyImageConverter::convertToFile(): cannot load the" << plugin << "plugin";
return false;
}
const PluginManager::PluginMetadata* const metadata = manager()->metadata(plugin);
CORRADE_INTERNAL_ASSERT(metadata);
if(flags() & ImageConverterFlag::Verbose) {
Debug d;
d << "Trade::AnyImageConverter::convertToFile(): using" << plugin;
if(plugin != metadata->name())
d << "(provided by" << metadata->name() << Debug::nospace << ")";
}
/* Instantiate the plugin, propagate flags */
Containers::Pointer<AbstractImageConverter> converter = static_cast<PluginManager::Manager<AbstractImageConverter>*>(manager())->instantiate(plugin);
converter->setFlags(flags());
/* Propagate configuration */
Magnum::Implementation::propagateConfiguration("Trade::AnyImageConverter::convertToFile():", {}, metadata->name(), configuration(), converter->configuration());
/* Try to convert the file (error output should be printed by the plugin
itself) */
return converter->convertToFile(imageLevels, filename);
}
bool AnyImageConverter::doConvertToFile(Containers::ArrayView<const CompressedImageView1D>, const Containers::StringView filename) {

454
src/MagnumPlugins/AnyImageConverter/Test/AnyImageConverterTest.cpp

@ -24,6 +24,7 @@
*/
#include <sstream>
#include <thread> /* std::thread::hardware_concurrency(), sigh */
#include <Corrade/Containers/StringStl.h>
#include <Corrade/PluginManager/Manager.h>
#include <Corrade/TestSuite/Tester.h>
@ -150,6 +151,36 @@ constexpr struct {
{"PNG", "file.png", "PngImageConverter"}
};
constexpr struct {
const char* name;
const char* filename;
const char* plugin;
} Detect3DData[]{
{"EXR", "file.exr", "OpenExrImageConverter"},
/* Have at least one test case with uppercase */
{"EXR uppercase", "FIL~1.EXR", "OpenExrImageConverter"}
};
constexpr struct {
const char* name;
const char* filename;
const char* plugin;
} DetectLevels2DData[]{
{"EXR", "file.exr", "OpenExrImageConverter"},
/* Have at least one test case with uppercase */
{"EXR uppercase", "FIL~1.EXR", "OpenExrImageConverter"}
};
constexpr struct {
const char* name;
const char* filename;
const char* plugin;
} DetectLevels3DData[]{
{"EXR", "file.exr", "OpenExrImageConverter"},
/* Have at least one test case with uppercase */
{"EXR uppercase", "FIL~1.EXR", "OpenExrImageConverter"}
};
AnyImageConverterTest::AnyImageConverterTest() {
addTests({&AnyImageConverterTest::convert1D,
&AnyImageConverterTest::convert2D,
@ -170,15 +201,22 @@ AnyImageConverterTest::AnyImageConverterTest() {
addInstancedTests({&AnyImageConverterTest::detect2D},
Containers::arraySize(Detect2DData));
addTests({&AnyImageConverterTest::detect3D,
&AnyImageConverterTest::detectCompressed1D,
addInstancedTests({&AnyImageConverterTest::detect3D},
Containers::arraySize(Detect3DData));
addTests({&AnyImageConverterTest::detectCompressed1D,
&AnyImageConverterTest::detectCompressed2D,
&AnyImageConverterTest::detectCompressed3D,
&AnyImageConverterTest::detectLevels1D,
&AnyImageConverterTest::detectLevels2D,
&AnyImageConverterTest::detectLevels3D,
&AnyImageConverterTest::detectCompressedLevels1D,
&AnyImageConverterTest::detectLevels1D});
addInstancedTests({&AnyImageConverterTest::detectLevels2D},
Containers::arraySize(DetectLevels2DData));
addInstancedTests({&AnyImageConverterTest::detectLevels3D},
Containers::arraySize(DetectLevels3DData));
addTests({&AnyImageConverterTest::detectCompressedLevels1D,
&AnyImageConverterTest::detectCompressedLevels2D,
&AnyImageConverterTest::detectCompressedLevels3D,
@ -260,9 +298,25 @@ constexpr const char Data[] = {
1, 2, 3, 2, 3, 4, 0, 0
};
constexpr Float CubeData[] = {
0.125f,
0.250f,
0.375f,
0.500f,
0.625f,
0.750f
};
constexpr Float FloatData[] = {
0.125f, 0.250f, 0.375f,
0.500f, 0.625f, 0.750f
};
const ImageView1D Image1D{PixelFormat::RGB8Unorm, 2, Data};
const ImageView2D Image2D{PixelFormat::RGB8Unorm, {2, 3}, Data};
const ImageView2D Image2DFloat{PixelFormat::Depth32F, {3, 2}, FloatData};
const ImageView3D Image3D{PixelFormat::RGB8Unorm, {2, 3, 2}, Data};
const ImageView3D ImageCube{PixelFormat::Depth32F, {1, 1, 6}, CubeData};
const CompressedImageView1D CompressedImage1D{CompressedPixelFormat::Bc1RGBAUnorm, 3, Data};
const CompressedImageView2D CompressedImage2D{CompressedPixelFormat::Bc1RGBAUnorm, {1, 3}, Data};
const CompressedImageView3D CompressedImage3D{CompressedPixelFormat::Bc1RGBAUnorm, {1, 1, 3}, Data};
@ -287,7 +341,25 @@ void AnyImageConverterTest::convert2D() {
}
void AnyImageConverterTest::convert3D() {
CORRADE_SKIP("No file formats to store 3D data yet.");
PluginManager::Manager<AbstractImageConverter> manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR};
#ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
if(manager.loadState("OpenExrImageConverter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("OpenExrImageConverter plugin can't be loaded.");
const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "cube.exr");
if(Utility::Directory::exists(filename))
CORRADE_VERIFY(Utility::Directory::rm(filename));
Containers::Pointer<AbstractImageConverter> converter = manager.instantiate("AnyImageConverter");
/* Well, this is in fact the same as propagateConfiguration3D() but we
can't really do much else. */
converter->configuration().setValue("envmap", "cube");
CORRADE_VERIFY(converter->convertToFile(ImageCube, filename));
CORRADE_VERIFY(Utility::Directory::exists(filename));
}
void AnyImageConverterTest::convertCompressed1D() {
@ -307,11 +379,49 @@ void AnyImageConverterTest::convertLevels1D() {
}
void AnyImageConverterTest::convertLevels2D() {
CORRADE_SKIP("No file formats to store multi-level 2D data yet.");
PluginManager::Manager<AbstractImageConverter> manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR};
#ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
if(manager.loadState("OpenExrImageConverter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("OpenExrImageConverter plugin can't be loaded.");
const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "output.exr");
if(Utility::Directory::exists(filename))
CORRADE_VERIFY(Utility::Directory::rm(filename));
/* Just test that the exported file exists */
Containers::Pointer<AbstractImageConverter> converter = manager.instantiate("AnyImageConverter");
/* Using the list API even though there's just one image, which should
still trigger the correct code path for AnyImageConverter. */
CORRADE_VERIFY(converter->convertToFile({Image2DFloat}, filename));
CORRADE_VERIFY(Utility::Directory::exists(filename));
}
void AnyImageConverterTest::convertLevels3D() {
CORRADE_SKIP("No file formats to store multi-level 3D data yet.");
PluginManager::Manager<AbstractImageConverter> manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR};
#ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
if(manager.loadState("OpenExrImageConverter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("OpenExrImageConverter plugin can't be loaded.");
const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "cube.exr");
if(Utility::Directory::exists(filename))
CORRADE_VERIFY(Utility::Directory::rm(filename));
Containers::Pointer<AbstractImageConverter> converter = manager.instantiate("AnyImageConverter");
/* Well, this is in fact the same as propagateConfigurationLevels3D() but
we can't really do much else. */
converter->configuration().setValue("envmap", "cube");
/* Using the list API even though there's just one image, which should
still trigger the correct code path for AnyImageConverter. */
CORRADE_VERIFY(converter->convertToFile({ImageCube}, filename));
CORRADE_VERIFY(Utility::Directory::exists(filename));
}
void AnyImageConverterTest::convertCompressedLevels1D() {
@ -352,7 +462,25 @@ void AnyImageConverterTest::detect2D() {
}
void AnyImageConverterTest::detect3D() {
CORRADE_SKIP("No file formats to store 3D data yet.");
auto&& data = Detect3DData[testCaseInstanceId()];
setTestCaseDescription(data.name);
Containers::Pointer<AbstractImageConverter> converter = _manager.instantiate("AnyImageConverter");
std::ostringstream out;
Error redirectError{&out};
CORRADE_VERIFY(!converter->convertToFile(Image2D, data.filename));
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
CORRADE_COMPARE(out.str(), Utility::formatString(
"PluginManager::Manager::load(): plugin {0} is not static and was not found in nonexistent\n"
"Trade::AnyImageConverter::convertToFile(): cannot load the {0} plugin\n",
data.plugin));
#else
CORRADE_COMPARE(out.str(), Utility::formatString(
"PluginManager::Manager::load(): plugin {0} was not found\n"
"Trade::AnyImageConverter::convertToFile(): cannot load the {0} plugin\n",
data.plugin));
#endif
}
void AnyImageConverterTest::detectCompressed1D() {
@ -372,11 +500,53 @@ void AnyImageConverterTest::detectLevels1D() {
}
void AnyImageConverterTest::detectLevels2D() {
CORRADE_SKIP("No file formats to store multi-level 2D data yet.");
auto&& data = DetectLevels2DData[testCaseInstanceId()];
setTestCaseDescription(data.name);
Containers::Pointer<AbstractImageConverter> converter = _manager.instantiate("AnyImageConverter");
std::ostringstream out;
Error redirectError{&out};
/* Using the list API even though there's just one image, which should
still trigger the correct code path for AnyImageConverter. */
CORRADE_VERIFY(!converter->convertToFile({Image2D}, data.filename));
/* Can't use raw string literals in macros on GCC 4.8 */
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
CORRADE_COMPARE(out.str(), Utility::formatString(
"PluginManager::Manager::load(): plugin {0} is not static and was not found in nonexistent\n"
"Trade::AnyImageConverter::convertToFile(): cannot load the {0} plugin\n",
data.plugin));
#else
CORRADE_COMPARE(out.str(), Utility::formatString(
"PluginManager::Manager::load(): plugin {0} was not found\n"
"Trade::AnyImageConverter::convertToFile(): cannot load the {0} plugin\n",
data.plugin));
#endif
}
void AnyImageConverterTest::detectLevels3D() {
CORRADE_SKIP("No file formats to store multi-level 3D data yet.");
auto&& data = DetectLevels3DData[testCaseInstanceId()];
setTestCaseDescription(data.name);
Containers::Pointer<AbstractImageConverter> converter = _manager.instantiate("AnyImageConverter");
std::ostringstream out;
Error redirectError{&out};
/* Using the list API even though there's just one image, which should
still trigger the correct code path for AnyImageConverter. */
CORRADE_VERIFY(!converter->convertToFile({Image3D}, data.filename));
/* Can't use raw string literals in macros on GCC 4.8 */
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
CORRADE_COMPARE(out.str(), Utility::formatString(
"PluginManager::Manager::load(): plugin {0} is not static and was not found in nonexistent\n"
"Trade::AnyImageConverter::convertToFile(): cannot load the {0} plugin\n",
data.plugin));
#else
CORRADE_COMPARE(out.str(), Utility::formatString(
"PluginManager::Manager::load(): plugin {0} was not found\n"
"Trade::AnyImageConverter::convertToFile(): cannot load the {0} plugin\n",
data.plugin));
#endif
}
void AnyImageConverterTest::detectCompressedLevels1D() {
@ -527,7 +697,43 @@ void AnyImageConverterTest::propagateFlags2D() {
}
void AnyImageConverterTest::propagateFlags3D() {
CORRADE_SKIP("No file formats to store 3D data yet.");
PluginManager::Manager<AbstractImageConverter> manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR};
#ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
if(manager.loadState("OpenExrImageConverter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("OpenExrImageConverter plugin can't be loaded.");
const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "cube.exr");
if(Utility::Directory::exists(filename))
CORRADE_VERIFY(Utility::Directory::rm(filename));
Containers::Pointer<AbstractImageConverter> converter = manager.instantiate("AnyImageConverter");
converter->configuration().setValue("envmap", "cube");
/* This will make the verbose output print the detected hardware thread
count, but also the info about updating global thread count for the
first time. Thus run it once w/o a verbose flag and then again with to
filter out the other message. */
/** @todo switch to testing something else when there is */
converter->configuration().setValue("threads", 0);
CORRADE_VERIFY(converter->convertToFile(ImageCube, filename));
if(Utility::Directory::exists(filename))
CORRADE_VERIFY(Utility::Directory::rm(filename));
converter->setFlags(ImageConverterFlag::Verbose);
std::ostringstream out;
{
Debug redirectOutput{&out};
CORRADE_VERIFY(converter->convertToFile(ImageCube, filename));
}
CORRADE_VERIFY(Utility::Directory::exists(filename));
CORRADE_COMPARE(out.str(), Utility::formatString(
"Trade::AnyImageConverter::convertToFile(): using OpenExrImageConverter\n"
"Trade::OpenExrImageConverter::convertToData(): autodetected hardware concurrency to {} threads\n",
std::thread::hardware_concurrency()));
}
void AnyImageConverterTest::propagateFlagsCompressed1D() {
@ -547,11 +753,86 @@ void AnyImageConverterTest::propagateFlagsLevels1D() {
}
void AnyImageConverterTest::propagateFlagsLevels2D() {
CORRADE_SKIP("No file formats to store multi-level 2D data yet.");
PluginManager::Manager<AbstractImageConverter> manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR};
#ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
if(manager.loadState("OpenExrImageConverter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("OpenExrImageConverter plugin can't be loaded.");
const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "output.exr");
if(Utility::Directory::exists(filename))
CORRADE_VERIFY(Utility::Directory::rm(filename));
Containers::Pointer<AbstractImageConverter> converter = manager.instantiate("AnyImageConverter");
/* This will make the verbose output print the detected hardware thread
count, but also the info about updating global thread count for the
first time. Thus run it once w/o a verbose flag and then again with to
filter out the other message. */
/** @todo switch to testing something else when there is */
converter->configuration().setValue("threads", 0);
CORRADE_VERIFY(converter->convertToFile({Image2DFloat}, filename));
if(Utility::Directory::exists(filename))
CORRADE_VERIFY(Utility::Directory::rm(filename));
converter->setFlags(ImageConverterFlag::Verbose);
std::ostringstream out;
{
Debug redirectOutput{&out};
/* Using the list API even though there's just one image, which should
still trigger the correct code path for AnyImageConverter. */
CORRADE_VERIFY(converter->convertToFile({Image2DFloat}, filename));
}
CORRADE_VERIFY(Utility::Directory::exists(filename));
CORRADE_COMPARE(out.str(), Utility::formatString(
"Trade::AnyImageConverter::convertToFile(): using OpenExrImageConverter\n"
"Trade::OpenExrImageConverter::convertToData(): autodetected hardware concurrency to {} threads\n",
std::thread::hardware_concurrency()));
}
void AnyImageConverterTest::propagateFlagsLevels3D() {
CORRADE_SKIP("No file formats to store multi-level 3D data yet.");
PluginManager::Manager<AbstractImageConverter> manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR};
#ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
if(manager.loadState("OpenExrImageConverter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("OpenExrImageConverter plugin can't be loaded.");
const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "cube.exr");
if(Utility::Directory::exists(filename))
CORRADE_VERIFY(Utility::Directory::rm(filename));
Containers::Pointer<AbstractImageConverter> converter = manager.instantiate("AnyImageConverter");
converter->configuration().setValue("envmap", "cube");
/* This will make the verbose output print the detected hardware thread
count, but also the info about updating global thread count for the
first time. Thus run it once w/o a verbose flag and then again with to
filter out the other message. */
/** @todo switch to testing something else when there is */
converter->configuration().setValue("threads", 0);
CORRADE_VERIFY(converter->convertToFile({ImageCube}, filename));
if(Utility::Directory::exists(filename))
CORRADE_VERIFY(Utility::Directory::rm(filename));
converter->setFlags(ImageConverterFlag::Verbose);
std::ostringstream out;
{
Debug redirectOutput{&out};
/* Using the list API even though there's just one image, which should
still trigger the correct code path for AnyImageConverter. */
CORRADE_VERIFY(converter->convertToFile({ImageCube}, filename));
}
CORRADE_VERIFY(Utility::Directory::exists(filename));
CORRADE_COMPARE(out.str(), Utility::formatString(
"Trade::AnyImageConverter::convertToFile(): using OpenExrImageConverter\n"
"Trade::OpenExrImageConverter::convertToData(): autodetected hardware concurrency to {} threads\n",
std::thread::hardware_concurrency()));
}
void AnyImageConverterTest::propagateFlagsCompressedLevels1D() {
@ -584,24 +865,38 @@ void AnyImageConverterTest::propagateConfiguration2D() {
if(Utility::Directory::exists(filename))
CORRADE_VERIFY(Utility::Directory::rm(filename));
const Float depth32fData[] = {
0.125f, 0.250f, 0.375f,
0.500f, 0.625f, 0.750f
};
const ImageView2D depth32f{PixelFormat::Depth32F, {3, 2}, depth32fData};
Containers::Pointer<AbstractImageConverter> converter = manager.instantiate("AnyImageConverter");
converter->configuration().setValue("layer", "left");
converter->configuration().setValue("depth", "height");
CORRADE_VERIFY(converter->convertToFile(depth32f, filename));
CORRADE_VERIFY(converter->convertToFile(Image2DFloat, filename));
/* Compare to an expected output to ensure the custom channels names were
used */
CORRADE_COMPARE_AS(filename, EXR_FILE, TestSuite::Compare::File);
}
void AnyImageConverterTest::propagateConfiguration3D() {
CORRADE_SKIP("No file formats to store 3D data yet.");
PluginManager::Manager<AbstractImageConverter> manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR};
#ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
if(manager.loadState("OpenExrImageConverter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("OpenExrImageConverter plugin can't be loaded.");
const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "cube.exr");
if(Utility::Directory::exists(filename))
CORRADE_VERIFY(Utility::Directory::rm(filename));
Containers::Pointer<AbstractImageConverter> converter = manager.instantiate("AnyImageConverter");
/* This should be enough to test -- 3D images can be saved only if this
option is set */
converter->configuration().setValue("envmap", "cube");
CORRADE_VERIFY(converter->convertToFile(ImageCube, filename));
/* Compare to an expected output to ensure we actually saved the file
including the metadata. This also doubles as a generator for the
cube.exr file that AnyImageImporterTest uses. */
CORRADE_COMPARE_AS(filename, EXR_CUBE_FILE, TestSuite::Compare::File);
}
void AnyImageConverterTest::propagateConfigurationUnknown1D() {
@ -623,7 +918,23 @@ void AnyImageConverterTest::propagateConfigurationUnknown2D() {
}
void AnyImageConverterTest::propagateConfigurationUnknown3D() {
CORRADE_SKIP("No file formats to store 3D data yet.");
PluginManager::Manager<AbstractImageConverter> manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR};
#ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
if(manager.loadState("OpenExrImageConverter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("OpenExrImageConverter plugin can't be loaded.");
/* Just test that the exported file exists */
Containers::Pointer<AbstractImageConverter> converter = manager.instantiate("AnyImageConverter");
converter->configuration().setValue("envmap", "cube");
converter->configuration().setValue("noSuchOption", "isHere");
std::ostringstream out;
Warning redirectWarning{&out};
CORRADE_VERIFY(converter->convertToFile(ImageCube, Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "output.exr")));
CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): option noSuchOption not recognized by OpenExrImageConverter\n");
}
void AnyImageConverterTest::propagateConfigurationCompressed1D() {
@ -655,11 +966,57 @@ void AnyImageConverterTest::propagateConfigurationLevels1D() {
}
void AnyImageConverterTest::propagateConfigurationLevels2D() {
CORRADE_SKIP("No file formats to store multi-level 2D data yet.");
PluginManager::Manager<AbstractImageConverter> manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR};
#ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
if(manager.loadState("OpenExrImageConverter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("OpenExrImageConverter plugin can't be loaded.");
const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "depth32f-custom-channels.exr");
if(Utility::Directory::exists(filename))
CORRADE_VERIFY(Utility::Directory::rm(filename));
Containers::Pointer<AbstractImageConverter> converter = manager.instantiate("AnyImageConverter");
converter->configuration().setValue("layer", "left");
converter->configuration().setValue("depth", "height");
/* Using the list API even though there's just one image, which should
still trigger the correct code path for AnyImageConverter. For
OpenExrImageConverter both single and list are the same code path so we
can reuse the same expected file. */
CORRADE_VERIFY(converter->convertToFile({Image2DFloat}, filename));
/* Compare to an expected output to ensure the custom channels names were
used */
CORRADE_COMPARE_AS(filename, EXR_FILE, TestSuite::Compare::File);
}
void AnyImageConverterTest::propagateConfigurationLevels3D() {
CORRADE_SKIP("No file formats to store multi-level 3D data yet.");
PluginManager::Manager<AbstractImageConverter> manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR};
#ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
if(manager.loadState("OpenExrImageConverter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("OpenExrImageConverter plugin can't be loaded.");
const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "cube.exr");
if(Utility::Directory::exists(filename))
CORRADE_VERIFY(Utility::Directory::rm(filename));
Containers::Pointer<AbstractImageConverter> converter = manager.instantiate("AnyImageConverter");
/* This should be enough to test -- 3D images can be saved only if this
option is set */
converter->configuration().setValue("envmap", "cube");
/* Using the list API even though there's just one image, which should
still trigger the correct code path for AnyImageConverter. For
OpenExrImageConverter both single and list are the same code path so we
can reuse the same expected file. */
CORRADE_VERIFY(converter->convertToFile({ImageCube}, filename));
/* Compare to an expected output to ensure we actually saved the file */
CORRADE_COMPARE_AS(filename, EXR_CUBE_FILE, TestSuite::Compare::File);
}
void AnyImageConverterTest::propagateConfigurationUnknownLevels1D() {
@ -667,11 +1024,50 @@ void AnyImageConverterTest::propagateConfigurationUnknownLevels1D() {
}
void AnyImageConverterTest::propagateConfigurationUnknownLevels2D() {
CORRADE_SKIP("No file formats to store multi-level 2D data yet.");
PluginManager::Manager<AbstractImageConverter> manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR};
#ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
if(manager.loadState("OpenExrImageConverter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("OpenExrImageConverter plugin can't be loaded.");
const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "depth32f-custom-channels.exr");
if(Utility::Directory::exists(filename))
CORRADE_VERIFY(Utility::Directory::rm(filename));
Containers::Pointer<AbstractImageConverter> converter = manager.instantiate("AnyImageConverter");
converter->configuration().setValue("noSuchOption", "isHere");
std::ostringstream out;
Warning redirectWarning{&out};
/* Using the list API even though there's just one image, which should
still trigger the correct code path for AnyImageConverter. */
CORRADE_VERIFY(converter->convertToFile({Image2DFloat}, Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "output.exr")));
CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): option noSuchOption not recognized by OpenExrImageConverter\n");
}
void AnyImageConverterTest::propagateConfigurationUnknownLevels3D() {
CORRADE_SKIP("No file formats to store multi-level 3D data yet.");
PluginManager::Manager<AbstractImageConverter> manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR};
#ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME
CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
if(manager.loadState("OpenExrImageConverter") < PluginManager::LoadState::Loaded)
CORRADE_SKIP("OpenExrImageConverter plugin can't be loaded.");
/* Just test that the exported file exists */
Containers::Pointer<AbstractImageConverter> converter = manager.instantiate("AnyImageConverter");
converter->configuration().setValue("envmap", "cube");
converter->configuration().setValue("noSuchOption", "isHere");
std::ostringstream out;
Warning redirectWarning{&out};
/* Using the list API even though there's just one image, which should
still trigger the correct code path for AnyImageConverter. */
CORRADE_VERIFY(converter->convertToFile({ImageCube}, Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "output.exr")));
CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): option noSuchOption not recognized by OpenExrImageConverter\n");
}
void AnyImageConverterTest::propagateConfigurationCompressedLevels1D() {

14
src/MagnumPlugins/AnyImageConverter/Test/CMakeLists.txt

@ -23,12 +23,18 @@
# DEALINGS IN THE SOFTWARE.
#
# Needed to test verbose output from OpenExrImageConverter (detected thread
# count), unfortunately no better option for testing flags right now
find_package(Threads REQUIRED)
if(CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID)
set(ANYIMAGECONVERTER_TEST_OUTPUT_DIR "write")
set(EXR_FILE depth32f-custom-channels.exr)
set(EXR_CUBE_FILE cube.exr)
else()
set(ANYIMAGECONVERTER_TEST_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
set(EXR_FILE ${PROJECT_SOURCE_DIR}/src/MagnumPlugins/AnyImageImporter/Test/depth32f-custom-channels.exr)
set(EXR_CUBE_FILE ${PROJECT_SOURCE_DIR}/src/MagnumPlugins/AnyImageImporter/Test/cube.exr)
endif()
# CMake before 3.8 has broken $<TARGET_FILE*> expressions for iOS (see
@ -49,8 +55,14 @@ file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/configure.h
INPUT ${CMAKE_CURRENT_BINARY_DIR}/configure.h.in)
corrade_add_test(AnyImageConverterTest AnyImageConverterTest.cpp
LIBRARIES MagnumTrade
LIBRARIES
MagnumTrade
# Needed to test verbose output from OpenExrImageConverter (detected
# thread count), unfortunately no better option for testing flags right
# now
Threads::Threads
FILES
../../AnyImageImporter/Test/cube.exr
../../AnyImageImporter/Test/depth32f-custom-channels.exr)
target_include_directories(AnyImageConverterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>)
if(MAGNUM_ANYIMAGECONVERTER_BUILD_STATIC)

1
src/MagnumPlugins/AnyImageConverter/Test/configure.h.cmake

@ -27,6 +27,7 @@
#cmakedefine TGAIMAGECONVERTER_PLUGIN_FILENAME "${TGAIMAGECONVERTER_PLUGIN_FILENAME}"
#define ANYIMAGECONVERTER_TEST_OUTPUT_DIR "${ANYIMAGECONVERTER_TEST_OUTPUT_DIR}"
#define EXR_FILE "${EXR_FILE}"
#define EXR_CUBE_FILE "${EXR_CUBE_FILE}"
#ifdef CORRADE_TARGET_WINDOWS
#ifdef CORRADE_IS_DEBUG_BUILD

BIN
src/MagnumPlugins/AnyImageImporter/Test/cube.exr

Binary file not shown.
Loading…
Cancel
Save