diff --git a/doc/changelog.dox b/doc/changelog.dox index 4b0d67a972..d0a558d8c8 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -402,6 +402,8 @@ See also: - Recognizing KTX2 files and data in @relativeref{Trade,AnyImageImporter} and @relativeref{Trade,AnyImageConverter} (see also [mosra/magnum#529](https://github.com/mosra/magnum/pull/529)) +- Recognizing KTX2 for (compressed) 1D/2D/3D and multi-level 1D/2D/3D images + in @relativeref{Trade,AnyImageConverter} - @ref Audio::AnyImporter "AnyAudioImporter", @relativeref{Trade,AnyImageImporter}, @relativeref{Trade,AnyImageConverter}, @relativeref{Trade,AnySceneImporter}, @relativeref{Trade,AnySceneConverter} diff --git a/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.cpp b/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.cpp index 2325647a61..8dfda9fa5c 100644 --- a/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.cpp +++ b/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.cpp @@ -62,13 +62,47 @@ ImageConverterFeatures AnyImageConverter::doFeatures() const { ImageConverterFeature::ConvertCompressedLevels3DToFile; } -bool AnyImageConverter::doConvertToFile(const ImageView1D&, const Containers::StringView filename) { +bool AnyImageConverter::doConvertToFile(const ImageView1D& image, const Containers::StringView filename) { CORRADE_INTERNAL_ASSERT(manager()); - /* No file formats to store 1D 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); + + /* Detect the plugin from extension */ + Containers::StringView plugin; + if(normalized.hasSuffix(".ktx2"_s)) + plugin = "KtxImageConverter"_s; + else { + Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a 1D image"; + return false; + } - Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a 1D 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 converter = static_cast*>(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 ImageView2D& image, const Containers::StringView filename) { @@ -178,40 +212,176 @@ bool AnyImageConverter::doConvertToFile(const ImageView3D& image, const Containe return converter->convertToFile(image, filename); } -bool AnyImageConverter::doConvertToFile(const CompressedImageView1D&, const Containers::StringView filename) { +bool AnyImageConverter::doConvertToFile(const CompressedImageView1D& image, const Containers::StringView filename) { CORRADE_INTERNAL_ASSERT(manager()); - /* No file formats to store compressed 1D 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); + + /* Detect the plugin from extension */ + Containers::StringView plugin; + if(normalized.hasSuffix(".ktx2"_s)) + plugin = "KtxImageConverter"_s; + else { + Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a compressed 1D image"; + return false; + } - Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a compressed 1D 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 converter = static_cast*>(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 CompressedImageView2D&, const Containers::StringView filename) { +bool AnyImageConverter::doConvertToFile(const CompressedImageView2D& image, const Containers::StringView filename) { CORRADE_INTERNAL_ASSERT(manager()); - /* No file formats to store compressed 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); + + /* Detect the plugin from extension */ + Containers::StringView plugin; + if(normalized.hasSuffix(".ktx2"_s)) + plugin = "KtxImageConverter"_s; + else { + Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a compressed 2D image"; + return false; + } - Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a compressed 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 converter = static_cast*>(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 CompressedImageView3D&, const Containers::StringView filename) { +bool AnyImageConverter::doConvertToFile(const CompressedImageView3D& image, const Containers::StringView filename) { CORRADE_INTERNAL_ASSERT(manager()); - /* No file formats to store compressed 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); + + /* Detect the plugin from extension */ + Containers::StringView plugin; + if(normalized.hasSuffix(".ktx2"_s)) + plugin = "KtxImageConverter"_s; + else { + Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a compressed 3D image"; + return false; + } - Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a compressed 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 converter = static_cast*>(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(Containers::ArrayView, const Containers::StringView filename) { +bool AnyImageConverter::doConvertToFile(const Containers::ArrayView imageLevels, const Containers::StringView filename) { CORRADE_INTERNAL_ASSERT(manager()); - /* No file formats to store multi-level 1D 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); + + /* Detect the plugin from extension */ + Containers::StringView plugin; + if(normalized.hasSuffix(".ktx2"_s)) + plugin = "KtxImageConverter"_s; + else { + Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a multi-level 1D image"; + return false; + } - Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a multi-level 1D 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 converter = static_cast*>(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(const Containers::ArrayView imageLevels, const Containers::StringView filename) { @@ -306,31 +476,133 @@ bool AnyImageConverter::doConvertToFile(const Containers::ArrayViewconvertToFile(imageLevels, filename); } -bool AnyImageConverter::doConvertToFile(Containers::ArrayView, const Containers::StringView filename) { +bool AnyImageConverter::doConvertToFile(const Containers::ArrayView imageLevels, const Containers::StringView filename) { CORRADE_INTERNAL_ASSERT(manager()); - /* No file formats to store multi-level compressed 1D 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); + + /* Detect the plugin from extension */ + Containers::StringView plugin; + if(normalized.hasSuffix(".ktx2"_s)) + plugin = "KtxImageConverter"_s; + else { + Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a multi-level compressed 1D image"; + return false; + } - Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a multi-level compressed 1D 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 converter = static_cast*>(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 Containers::StringView filename) { +bool AnyImageConverter::doConvertToFile(const Containers::ArrayView imageLevels, const Containers::StringView filename) { CORRADE_INTERNAL_ASSERT(manager()); - /* No file formats to store multi-level compressed 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); + + /* Detect the plugin from extension */ + Containers::StringView plugin; + if(normalized.hasSuffix(".ktx2"_s)) + plugin = "KtxImageConverter"_s; + else { + Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a multi-level compressed 2D image"; + return false; + } - Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a multi-level compressed 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 converter = static_cast*>(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 Containers::StringView filename) { +bool AnyImageConverter::doConvertToFile(const Containers::ArrayView imageLevels, const Containers::StringView filename) { CORRADE_INTERNAL_ASSERT(manager()); - /* No file formats to store multi-level compressed 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); + + /* Detect the plugin from extension */ + Containers::StringView plugin; + if(normalized.hasSuffix(".ktx2"_s)) + plugin = "KtxImageConverter"_s; + else { + Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a multi-level compressed 3D image"; + return false; + } - Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "for a multi-level compressed 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 converter = static_cast*>(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); } }} diff --git a/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.h b/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.h index 0c8863a8ce..f03af49ad0 100644 --- a/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.h +++ b/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.h @@ -57,24 +57,28 @@ Detects file type based on file extension, loads corresponding plugin and then tries to convert the file with it. Supported formats for uncompressed data: - Basis Universal (`*.basis`), converted with @ref BasisImageConverter or any - other plugin that provides it + other plugin that provides it. Only uncompressed 2D and multi-level 2D + images. - Windows Bitmap (`*.bmp`), converted with any plugin that provides - `BmpImageConverter` + `BmpImageConverter`. Only uncompressed 2D images. - OpenEXR (`*.exr`), converted with any plugin that provides - `OpenExrImageConverter` + `OpenExrImageConverter`. Only uncompressed 2D/3D and multi-level 2D/3D + images. - Radiance HDR (`*.hdr`), converted with any plugin that provides - `HdrImageConverter` + `HdrImageConverter`. Only uncompressed 2D images. - JPEG (`*.jpg`, `*.jpe`, `*.jpeg`), converted with @ref JpegImageConverter - or any other plugin that provides it + or any other plugin that provides it. Only uncompressed 2D images. - KTX2 (`*.ktx2`), converted with @ref KtxImageConverter or any other plugin - that provides it + that provides it. Uncompressed, compressed, 1D/2D/3D and multi-level + 1D/2D/3D images. - Portable Network Graphics (`*.png`), converted with @ref PngImageConverter - or any other plugin that provides it + or any other plugin that provides it. Only uncompressed 2D images. - Truevision TGA (`*.tga`, `*.vda`, `*.icb`, `*.vst`), converted with - @ref TgaImageConverter or any other plugin that provides it + @ref TgaImageConverter or any other plugin that provides it. Only + uncompressed 2D images. -No supported formats for compressed data yet. Only exporting to files is -supported. +As the converter plugin is picked based on file extension, only saving to files +is supported. @section Trade-AnyImageConverter-usage Usage diff --git a/src/MagnumPlugins/AnyImageConverter/Test/AnyImageConverterTest.cpp b/src/MagnumPlugins/AnyImageConverter/Test/AnyImageConverterTest.cpp index a002c57fae..29c063b80e 100644 --- a/src/MagnumPlugins/AnyImageConverter/Test/AnyImageConverterTest.cpp +++ b/src/MagnumPlugins/AnyImageConverter/Test/AnyImageConverterTest.cpp @@ -135,6 +135,16 @@ struct AnyImageConverterTest: TestSuite::Tester { PluginManager::Manager _manager{"nonexistent"}; }; +constexpr struct { + const char* name; + const char* filename; + const char* plugin; +} Detect1DData[]{ + {"KTX2", "file.ktx2", "KtxImageConverter"}, + /* Have at least one test case with uppercase */ + {"KTX2 uppercase", "FIL~1.KTX2", "KtxImageConverter"} +}; + constexpr struct { const char* name; const char* filename; @@ -163,6 +173,16 @@ constexpr struct { {"EXR uppercase", "FIL~1.EXR", "OpenExrImageConverter"} }; +constexpr struct { + const char* name; + const char* filename; + const char* plugin; +} DetectLevels1DData[]{ + {"KTX2", "file.ktx2", "KtxImageConverter"}, + /* Have at least one test case with uppercase */ + {"KTX2 uppercase", "FIL~1.KTX2", "KtxImageConverter"} +}; + constexpr struct { const char* name; const char* filename; @@ -186,6 +206,69 @@ constexpr struct { {"EXR uppercase", "FIL~1.EXR", "OpenExrImageConverter"} }; +/* It's all duplicated, yes, but I expect at least the 2D compressed cases to + grow a bit */ + +constexpr struct { + const char* name; + const char* filename; + const char* plugin; +} DetectCompressed1DData[]{ + {"KTX2", "file.ktx2", "KtxImageConverter"}, + /* Have at least one test case with uppercase */ + {"KTX2 uppercase", "FIL~1.KTX2", "KtxImageConverter"} +}; + +constexpr struct { + const char* name; + const char* filename; + const char* plugin; +} DetectCompressed2DData[]{ + {"KTX2", "file.ktx2", "KtxImageConverter"}, + /* Have at least one test case with uppercase */ + {"KTX2 uppercase", "FIL~1.KTX2", "KtxImageConverter"} +}; + +constexpr struct { + const char* name; + const char* filename; + const char* plugin; +} DetectCompressed3DData[]{ + {"KTX2", "file.ktx2", "KtxImageConverter"}, + /* Have at least one test case with uppercase */ + {"KTX2 uppercase", "FIL~1.KTX2", "KtxImageConverter"} +}; + +constexpr struct { + const char* name; + const char* filename; + const char* plugin; +} DetectCompressedLevels1DData[]{ + {"KTX2", "file.ktx2", "KtxImageConverter"}, + /* Have at least one test case with uppercase */ + {"KTX2 uppercase", "FIL~1.KTX2", "KtxImageConverter"} +}; + +constexpr struct { + const char* name; + const char* filename; + const char* plugin; +} DetectCompressedLevels2DData[]{ + {"KTX2", "file.ktx2", "KtxImageConverter"}, + /* Have at least one test case with uppercase */ + {"KTX2 uppercase", "FIL~1.KTX2", "KtxImageConverter"} +}; + +constexpr struct { + const char* name; + const char* filename; + const char* plugin; +} DetectCompressedLevels3DData[]{ + {"KTX2", "file.ktx2", "KtxImageConverter"}, + /* Have at least one test case with uppercase */ + {"KTX2 uppercase", "FIL~1.KTX2", "KtxImageConverter"} +}; + AnyImageConverterTest::AnyImageConverterTest() { addTests({&AnyImageConverterTest::convert1D, &AnyImageConverterTest::convert2D, @@ -199,9 +282,10 @@ AnyImageConverterTest::AnyImageConverterTest() { &AnyImageConverterTest::convertLevels3D, &AnyImageConverterTest::convertCompressedLevels1D, &AnyImageConverterTest::convertCompressedLevels2D, - &AnyImageConverterTest::convertCompressedLevels3D, + &AnyImageConverterTest::convertCompressedLevels3D}); - &AnyImageConverterTest::detect1D}); + addInstancedTests({&AnyImageConverterTest::detect1D}, + Containers::arraySize(Detect1DData)); addInstancedTests({&AnyImageConverterTest::detect2D}, Containers::arraySize(Detect2DData)); @@ -209,11 +293,17 @@ AnyImageConverterTest::AnyImageConverterTest() { addInstancedTests({&AnyImageConverterTest::detect3D}, Containers::arraySize(Detect3DData)); - addTests({&AnyImageConverterTest::detectCompressed1D, - &AnyImageConverterTest::detectCompressed2D, - &AnyImageConverterTest::detectCompressed3D, + addInstancedTests({&AnyImageConverterTest::detectCompressed1D}, + Containers::arraySize(DetectCompressed1DData)); + + addInstancedTests({&AnyImageConverterTest::detectCompressed2D}, + Containers::arraySize(DetectCompressed2DData)); - &AnyImageConverterTest::detectLevels1D}); + addInstancedTests({&AnyImageConverterTest::detectCompressed3D}, + Containers::arraySize(DetectCompressed3DData)); + + addInstancedTests({&AnyImageConverterTest::detectLevels1D}, + Containers::arraySize(DetectLevels1DData)); addInstancedTests({&AnyImageConverterTest::detectLevels2D}, Containers::arraySize(DetectLevels2DData)); @@ -221,11 +311,16 @@ AnyImageConverterTest::AnyImageConverterTest() { addInstancedTests({&AnyImageConverterTest::detectLevels3D}, Containers::arraySize(DetectLevels3DData)); - addTests({&AnyImageConverterTest::detectCompressedLevels1D, - &AnyImageConverterTest::detectCompressedLevels2D, - &AnyImageConverterTest::detectCompressedLevels3D, + addInstancedTests({&AnyImageConverterTest::detectCompressedLevels1D}, + Containers::arraySize(DetectCompressedLevels1DData)); + + addInstancedTests({&AnyImageConverterTest::detectCompressedLevels2D}, + Containers::arraySize(DetectCompressedLevels2DData)); - &AnyImageConverterTest::unknown1D, + addInstancedTests({&AnyImageConverterTest::detectCompressedLevels3D}, + Containers::arraySize(DetectCompressedLevels3DData)); + + addTests({&AnyImageConverterTest::unknown1D, &AnyImageConverterTest::unknown2D, &AnyImageConverterTest::unknown3D, &AnyImageConverterTest::unknownCompressed1D, @@ -327,7 +422,25 @@ const CompressedImageView2D CompressedImage2D{CompressedPixelFormat::Bc1RGBAUnor const CompressedImageView3D CompressedImage3D{CompressedPixelFormat::Bc1RGBAUnorm, {1, 1, 3}, Data}; void AnyImageConverterTest::convert1D() { - CORRADE_SKIP("No file formats to store 1D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "1d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + CORRADE_VERIFY(converter->convertToFile(Image1D, filename)); + /* Compare to an expected output to ensure we actually saved the file + including the metadata. This also doubles as a generator for the 1d.ktx2 + file that AnyImageImporterTest uses. */ + CORRADE_COMPARE_AS(filename, KTX_1D_FILE, TestSuite::Compare::File); } void AnyImageConverterTest::convert2D() { @@ -368,19 +481,85 @@ void AnyImageConverterTest::convert3D() { } void AnyImageConverterTest::convertCompressed1D() { - CORRADE_SKIP("No file formats to store compressed 1D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-1d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + /* Just test that the exported file exists */ + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + CORRADE_VERIFY(converter->convertToFile(CompressedImage1D, filename)); + CORRADE_VERIFY(Utility::Directory::exists(filename)); } void AnyImageConverterTest::convertCompressed2D() { - CORRADE_SKIP("No file formats to store compressed 2D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-2d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + /* Just test that the exported file exists */ + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + CORRADE_VERIFY(converter->convertToFile(CompressedImage2D, filename)); + CORRADE_VERIFY(Utility::Directory::exists(filename)); } void AnyImageConverterTest::convertCompressed3D() { - CORRADE_SKIP("No file formats to store compressed 3D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-3d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + /* Just test that the exported file exists */ + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + CORRADE_VERIFY(converter->convertToFile(CompressedImage3D, filename)); + CORRADE_VERIFY(Utility::Directory::exists(filename)); } void AnyImageConverterTest::convertLevels1D() { - CORRADE_SKIP("No file formats to store multi-level 1D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "levels-1d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + /* Just test that the exported file exists */ + Containers::Pointer 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({Image1D}, filename)); + CORRADE_VERIFY(Utility::Directory::exists(filename)); } void AnyImageConverterTest::convertLevels2D() { @@ -428,19 +607,90 @@ void AnyImageConverterTest::convertLevels3D() { } void AnyImageConverterTest::convertCompressedLevels1D() { - CORRADE_SKIP("No file formats to store multi-level compressed 1D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-levels-1d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + /* Just test that the exported file exists */ + Containers::Pointer 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({CompressedImage1D}, filename)); + CORRADE_VERIFY(Utility::Directory::exists(filename)); } void AnyImageConverterTest::convertCompressedLevels2D() { - CORRADE_SKIP("No file formats to store multi-level compressed 2D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-levels-2d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + /* Just test that the exported file exists */ + Containers::Pointer 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({CompressedImage2D}, filename)); + CORRADE_VERIFY(Utility::Directory::exists(filename)); } void AnyImageConverterTest::convertCompressedLevels3D() { - CORRADE_SKIP("No file formats to store multi-level compressed 3D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-levels-3d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + /* Just test that the exported file exists */ + Containers::Pointer 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({CompressedImage3D}, filename)); + CORRADE_VERIFY(Utility::Directory::exists(filename)); } void AnyImageConverterTest::detect1D() { - CORRADE_SKIP("No file formats to store 1D data yet."); + auto&& data = Detect1DData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + Containers::Pointer converter = _manager.instantiate("AnyImageConverter"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertToFile(Image1D, 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::detect2D() { @@ -487,32 +737,14 @@ void AnyImageConverterTest::detect3D() { } void AnyImageConverterTest::detectCompressed1D() { - CORRADE_SKIP("No file formats to store compressed 1D data yet."); -} - -void AnyImageConverterTest::detectCompressed2D() { - CORRADE_SKIP("No file formats to store compressed 2D data yet."); -} - -void AnyImageConverterTest::detectCompressed3D() { - CORRADE_SKIP("No file formats to store compressed 3D data yet."); -} - -void AnyImageConverterTest::detectLevels1D() { - CORRADE_SKIP("No file formats to store multi-level 1D data yet."); -} - -void AnyImageConverterTest::detectLevels2D() { - auto&& data = DetectLevels2DData[testCaseInstanceId()]; + auto&& data = DetectCompressed1DData[testCaseInstanceId()]; setTestCaseDescription(data.name); Containers::Pointer 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)); + CORRADE_VERIFY(!converter->convertToFile(CompressedImage1D, 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" @@ -521,22 +753,19 @@ void AnyImageConverterTest::detectLevels2D() { #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)); + "Trade::AnyImageConverter::convertToFile(): cannot load the {0} plugin\n", data.plugin)); #endif } -void AnyImageConverterTest::detectLevels3D() { - auto&& data = DetectLevels3DData[testCaseInstanceId()]; +void AnyImageConverterTest::detectCompressed2D() { + auto&& data = DetectCompressed1DData[testCaseInstanceId()]; setTestCaseDescription(data.name); Containers::Pointer 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)); + CORRADE_VERIFY(!converter->convertToFile(CompressedImage2D, 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" @@ -545,35 +774,184 @@ void AnyImageConverterTest::detectLevels3D() { #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)); + "Trade::AnyImageConverter::convertToFile(): cannot load the {0} plugin\n", data.plugin)); #endif } -void AnyImageConverterTest::detectCompressedLevels1D() { - CORRADE_SKIP("No file formats to store multi-level compressed 1D data yet."); -} - -void AnyImageConverterTest::detectCompressedLevels2D() { - CORRADE_SKIP("No file formats to store multi-level compressed 2D data yet."); -} - -void AnyImageConverterTest::detectCompressedLevels3D() { - CORRADE_SKIP("No file formats to store multi-level compressed 3D data yet."); -} +void AnyImageConverterTest::detectCompressed3D() { + auto&& data = DetectCompressed1DData[testCaseInstanceId()]; + setTestCaseDescription(data.name); -void AnyImageConverterTest::unknown1D() { Containers::Pointer converter = _manager.instantiate("AnyImageConverter"); std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter->convertToFile(Image1D, "image.ktx2")); - CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.ktx2 for a 1D image\n"); -} - -void AnyImageConverterTest::unknown2D() { - Containers::Pointer converter = _manager.instantiate("AnyImageConverter"); - + CORRADE_VERIFY(!converter->convertToFile(CompressedImage3D, 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::detectLevels1D() { + auto&& data = DetectCompressed1DData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + Containers::Pointer converter = _manager.instantiate("AnyImageConverter"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertToFile(CompressedImage1D, 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::detectLevels2D() { + auto&& data = DetectLevels2DData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + Containers::Pointer 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)); + #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() { + auto&& data = DetectLevels3DData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + Containers::Pointer 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)); + #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() { + auto&& data = DetectCompressedLevels1DData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + Containers::Pointer 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({CompressedImage1D}, 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::detectCompressedLevels2D() { + auto&& data = DetectCompressedLevels2DData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + Containers::Pointer 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({CompressedImage2D}, 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::detectCompressedLevels3D() { + auto&& data = DetectCompressedLevels3DData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + Containers::Pointer 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({CompressedImage3D}, 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::unknown1D() { + Containers::Pointer converter = _manager.instantiate("AnyImageConverter"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertToFile(Image1D, "image.jpg")); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.jpg for a 1D image\n"); +} + +void AnyImageConverterTest::unknown2D() { + Containers::Pointer converter = _manager.instantiate("AnyImageConverter"); + std::ostringstream out; Error redirectError{&out}; CORRADE_VERIFY(!converter->convertToFile(Image2D, "image.xcf")); @@ -594,8 +972,8 @@ void AnyImageConverterTest::unknownCompressed1D() { std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter->convertToFile(CompressedImage1D, "image.ktx2")); - CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.ktx2 for a compressed 1D image\n"); + CORRADE_VERIFY(!converter->convertToFile(CompressedImage1D, "image.exr")); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.exr for a compressed 1D image\n"); } void AnyImageConverterTest::unknownCompressed2D() { @@ -603,8 +981,8 @@ void AnyImageConverterTest::unknownCompressed2D() { std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter->convertToFile(CompressedImage2D, "image.ktx2")); - CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.ktx2 for a compressed 2D image\n"); + CORRADE_VERIFY(!converter->convertToFile(CompressedImage2D, "image.png")); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.png for a compressed 2D image\n"); } void AnyImageConverterTest::unknownCompressed3D() { @@ -612,8 +990,8 @@ void AnyImageConverterTest::unknownCompressed3D() { std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter->convertToFile(CompressedImage3D, "image.ktx2")); - CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.ktx2 for a compressed 3D image\n"); + CORRADE_VERIFY(!converter->convertToFile(CompressedImage3D, "image.exr")); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.exr for a compressed 3D image\n"); } void AnyImageConverterTest::unknownLevels1D() { @@ -621,8 +999,8 @@ void AnyImageConverterTest::unknownLevels1D() { std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter->convertToFile({Image1D}, "image.ktx2")); - CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.ktx2 for a multi-level 1D image\n"); + CORRADE_VERIFY(!converter->convertToFile({Image1D}, "image.tga")); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.tga for a multi-level 1D image\n"); } void AnyImageConverterTest::unknownLevels2D() { @@ -630,8 +1008,8 @@ void AnyImageConverterTest::unknownLevels2D() { std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter->convertToFile({Image2D}, "image.dds")); - CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.dds for a multi-level 2D image\n"); + CORRADE_VERIFY(!converter->convertToFile({Image2D}, "image.png")); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.png for a multi-level 2D image\n"); } void AnyImageConverterTest::unknownLevels3D() { @@ -639,8 +1017,8 @@ void AnyImageConverterTest::unknownLevels3D() { std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter->convertToFile({Image3D}, "image.dds")); - CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.dds for a multi-level 3D image\n"); + CORRADE_VERIFY(!converter->convertToFile({Image3D}, "image.jpg")); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.jpg for a multi-level 3D image\n"); } void AnyImageConverterTest::unknownCompressedLevels1D() { @@ -648,8 +1026,8 @@ void AnyImageConverterTest::unknownCompressedLevels1D() { std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter->convertToFile({CompressedImage1D}, "image.ktx2")); - CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.ktx2 for a multi-level compressed 1D image\n"); + CORRADE_VERIFY(!converter->convertToFile({CompressedImage1D}, "image.bmp")); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.bmp for a multi-level compressed 1D image\n"); } void AnyImageConverterTest::unknownCompressedLevels2D() { @@ -657,8 +1035,8 @@ void AnyImageConverterTest::unknownCompressedLevels2D() { std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter->convertToFile({CompressedImage2D}, "image.ktx2")); - CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.ktx2 for a multi-level compressed 2D image\n"); + CORRADE_VERIFY(!converter->convertToFile({CompressedImage2D}, "image.exr")); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.exr for a multi-level compressed 2D image\n"); } void AnyImageConverterTest::unknownCompressedLevels3D() { @@ -666,12 +1044,12 @@ void AnyImageConverterTest::unknownCompressedLevels3D() { std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter->convertToFile({CompressedImage3D}, "image.ktx2")); - CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.ktx2 for a multi-level compressed 3D image\n"); + CORRADE_VERIFY(!converter->convertToFile({CompressedImage3D}, "image.exr")); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.exr for a multi-level compressed 3D image\n"); } void AnyImageConverterTest::propagateFlags1D() { - CORRADE_SKIP("No file formats to store 1D data yet."); + CORRADE_SKIP("No plugins with flag-dependent behavior for 1D data yet."); } void AnyImageConverterTest::propagateFlags2D() { @@ -738,19 +1116,19 @@ void AnyImageConverterTest::propagateFlags3D() { } void AnyImageConverterTest::propagateFlagsCompressed1D() { - CORRADE_SKIP("No file formats to store compressed 1D data yet."); + CORRADE_SKIP("No plugins with flag-dependent behavior for compressed 1D data yet."); } void AnyImageConverterTest::propagateFlagsCompressed2D() { - CORRADE_SKIP("No file formats to store compressed 2D data yet."); + CORRADE_SKIP("No plugins with flag-dependent behavior for compressed 2D data yet."); } void AnyImageConverterTest::propagateFlagsCompressed3D() { - CORRADE_SKIP("No file formats to store compressed 3D data yet."); + CORRADE_SKIP("No plugins with flag-dependent behavior for compressed 3D data yet."); } void AnyImageConverterTest::propagateFlagsLevels1D() { - CORRADE_SKIP("No file formats to store multi-level 1D data yet."); + CORRADE_SKIP("No plugins with flag-dependent behavior for multi-level 1D data yet."); } void AnyImageConverterTest::propagateFlagsLevels2D() { @@ -837,19 +1215,37 @@ void AnyImageConverterTest::propagateFlagsLevels3D() { } void AnyImageConverterTest::propagateFlagsCompressedLevels1D() { - CORRADE_SKIP("No file formats to store multi-level compressed 1D data yet."); + CORRADE_SKIP("No plugins with flag-dependent behavior for multi-level compressed 1D data yet."); } void AnyImageConverterTest::propagateFlagsCompressedLevels2D() { - CORRADE_SKIP("No file formats to store multi-level compressed 2D data yet."); + CORRADE_SKIP("No plugins with flag-dependent behavior for multi-level compressed 2D data yet."); } void AnyImageConverterTest::propagateFlagsCompressedLevels3D() { - CORRADE_SKIP("No file formats to store multi-level compressed 3D data yet."); + CORRADE_SKIP("No plugins with flag-dependent behavior for multi-level compressed 3D data yet."); } void AnyImageConverterTest::propagateConfiguration1D() { - CORRADE_SKIP("No file formats to store 1D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "custom-writer-1d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + converter->configuration().setValue("writerName", "Yello this did Magnum!"); + CORRADE_VERIFY(converter->convertToFile(Image1D, filename)); + CORRADE_VERIFY(Utility::Directory::exists(filename)); + /** @todo clean up once Directory::readString() returns our String */ + CORRADE_VERIFY(Containers::StringView{Containers::ArrayView(Utility::Directory::read(filename))}.contains("KTXwriter\0Yello this did Magnum!")); } void AnyImageConverterTest::propagateConfiguration2D() { @@ -899,7 +1295,21 @@ void AnyImageConverterTest::propagateConfiguration3D() { } void AnyImageConverterTest::propagateConfigurationUnknown1D() { - CORRADE_SKIP("No file formats to store 1D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + converter->configuration().setValue("noSuchOption", "isHere"); + + std::ostringstream out; + Warning redirectWarning{&out}; + CORRADE_VERIFY(converter->convertToFile(Image1D, Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "1d.ktx2"))); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): option noSuchOption not recognized by KtxImageConverter\n"); } void AnyImageConverterTest::propagateConfigurationUnknown2D() { @@ -934,31 +1344,147 @@ void AnyImageConverterTest::propagateConfigurationUnknown3D() { } void AnyImageConverterTest::propagateConfigurationCompressed1D() { - CORRADE_SKIP("No file formats to store compressed 1D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-custom-writer-1d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + converter->configuration().setValue("writerName", "Yello this did Magnum!"); + CORRADE_VERIFY(converter->convertToFile(CompressedImage1D, filename)); + CORRADE_VERIFY(Utility::Directory::exists(filename)); + /** @todo clean up once Directory::readString() returns our String */ + CORRADE_VERIFY(Containers::StringView{Containers::ArrayView(Utility::Directory::read(filename))}.contains("KTXwriter\0Yello this did Magnum!")); } void AnyImageConverterTest::propagateConfigurationCompressed2D() { - CORRADE_SKIP("No file formats to store compressed 2D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-custom-writer-2d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + converter->configuration().setValue("writerName", "Yello this did Magnum!"); + CORRADE_VERIFY(converter->convertToFile(CompressedImage2D, filename)); + CORRADE_VERIFY(Utility::Directory::exists(filename)); + /** @todo clean up once Directory::readString() returns our String */ + CORRADE_VERIFY(Containers::StringView{Containers::ArrayView(Utility::Directory::read(filename))}.contains("KTXwriter\0Yello this did Magnum!")); } void AnyImageConverterTest::propagateConfigurationCompressed3D() { - CORRADE_SKIP("No file formats to store compressed 3D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-custom-writer-3d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + converter->configuration().setValue("writerName", "Yello this did Magnum!"); + CORRADE_VERIFY(converter->convertToFile(CompressedImage3D, filename)); + CORRADE_VERIFY(Utility::Directory::exists(filename)); + /** @todo clean up once Directory::readString() returns our String */ + CORRADE_VERIFY(Containers::StringView{Containers::ArrayView(Utility::Directory::read(filename))}.contains("KTXwriter\0Yello this did Magnum!")); } void AnyImageConverterTest::propagateConfigurationCompressedUnknown1D() { - CORRADE_SKIP("No file formats to store compressed 1D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + converter->configuration().setValue("noSuchOption", "isHere"); + + std::ostringstream out; + Warning redirectWarning{&out}; + CORRADE_VERIFY(converter->convertToFile(CompressedImage1D, Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-1d.ktx2"))); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): option noSuchOption not recognized by KtxImageConverter\n"); } void AnyImageConverterTest::propagateConfigurationCompressedUnknown2D() { - CORRADE_SKIP("No file formats to store compressed 2D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + converter->configuration().setValue("noSuchOption", "isHere"); + + std::ostringstream out; + Warning redirectWarning{&out}; + CORRADE_VERIFY(converter->convertToFile(CompressedImage2D, Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-2d.ktx2"))); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): option noSuchOption not recognized by KtxImageConverter\n"); } void AnyImageConverterTest::propagateConfigurationCompressedUnknown3D() { - CORRADE_SKIP("No file formats to store compressed 3D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + converter->configuration().setValue("noSuchOption", "isHere"); + + std::ostringstream out; + Warning redirectWarning{&out}; + CORRADE_VERIFY(converter->convertToFile(CompressedImage3D, Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-3d.ktx2"))); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): option noSuchOption not recognized by KtxImageConverter\n"); } void AnyImageConverterTest::propagateConfigurationLevels1D() { - CORRADE_SKIP("No file formats to store multi-level 1D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "custom-writer-1d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + converter->configuration().setValue("writerName", "Yello this did Magnum!"); + /* 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({Image1D}, filename)); + CORRADE_VERIFY(Utility::Directory::exists(filename)); + /** @todo clean up once Directory::readString() returns our String */ + CORRADE_VERIFY(Containers::StringView{Containers::ArrayView(Utility::Directory::read(filename))}.contains("KTXwriter\0Yello this did Magnum!")); } void AnyImageConverterTest::propagateConfigurationLevels2D() { @@ -1010,7 +1536,23 @@ void AnyImageConverterTest::propagateConfigurationLevels3D() { } void AnyImageConverterTest::propagateConfigurationUnknownLevels1D() { - CORRADE_SKIP("No file formats to store multi-level 1D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + Containers::Pointer 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({Image1D}, Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "1d.ktx2"))); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): option noSuchOption not recognized by KtxImageConverter\n"); } void AnyImageConverterTest::propagateConfigurationUnknownLevels2D() { @@ -1054,27 +1596,135 @@ void AnyImageConverterTest::propagateConfigurationUnknownLevels3D() { } void AnyImageConverterTest::propagateConfigurationCompressedLevels1D() { - CORRADE_SKIP("No file formats to store multi-level compressed 1D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-custom-writer-1d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + converter->configuration().setValue("writerName", "Yello this did Magnum!"); + /* 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({CompressedImage1D}, filename)); + CORRADE_VERIFY(Utility::Directory::exists(filename)); + /** @todo clean up once Directory::readString() returns our String */ + CORRADE_VERIFY(Containers::StringView{Containers::ArrayView(Utility::Directory::read(filename))}.contains("KTXwriter\0Yello this did Magnum!")); } void AnyImageConverterTest::propagateConfigurationCompressedLevels2D() { - CORRADE_SKIP("No file formats to store multi-level compressed 2D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-custom-writer-2d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + converter->configuration().setValue("writerName", "Yello this did Magnum!"); + /* 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({CompressedImage2D}, filename)); + CORRADE_VERIFY(Utility::Directory::exists(filename)); + /** @todo clean up once Directory::readString() returns our String */ + CORRADE_VERIFY(Containers::StringView{Containers::ArrayView(Utility::Directory::read(filename))}.contains("KTXwriter\0Yello this did Magnum!")); } void AnyImageConverterTest::propagateConfigurationCompressedLevels3D() { - CORRADE_SKIP("No file formats to store multi-level compressed 3D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + const std::string filename = Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compresed-custom-writer-3d.ktx2"); + + if(Utility::Directory::exists(filename)) + CORRADE_VERIFY(Utility::Directory::rm(filename)); + + Containers::Pointer converter = manager.instantiate("AnyImageConverter"); + converter->configuration().setValue("writerName", "Yello this did Magnum!"); + /* 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({CompressedImage3D}, filename)); + CORRADE_VERIFY(Utility::Directory::exists(filename)); + /** @todo clean up once Directory::readString() returns our String */ + CORRADE_VERIFY(Containers::StringView{Containers::ArrayView(Utility::Directory::read(filename))}.contains("KTXwriter\0Yello this did Magnum!")); } void AnyImageConverterTest::propagateConfigurationCompressedUnknownLevels1D() { - CORRADE_SKIP("No file formats to store multi-level compressed 1D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + Containers::Pointer 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({CompressedImage1D}, Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-1d.ktx2"))); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): option noSuchOption not recognized by KtxImageConverter\n"); } void AnyImageConverterTest::propagateConfigurationCompressedUnknownLevels2D() { - CORRADE_SKIP("No file formats to store multi-level compressed 2D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + Containers::Pointer 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({CompressedImage2D}, Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-2d.ktx2"))); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): option noSuchOption not recognized by KtxImageConverter\n"); } void AnyImageConverterTest::propagateConfigurationCompressedUnknownLevels3D() { - CORRADE_SKIP("No file formats to store multi-level compressed 3D data yet."); + PluginManager::Manager manager{MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR}; + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImageConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImageConverter plugin can't be loaded."); + + Containers::Pointer 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({CompressedImage3D}, Utility::Directory::join(ANYIMAGECONVERTER_TEST_OUTPUT_DIR, "compressed-3d.ktx2"))); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): option noSuchOption not recognized by KtxImageConverter\n"); } }}}} diff --git a/src/MagnumPlugins/AnyImageConverter/Test/CMakeLists.txt b/src/MagnumPlugins/AnyImageConverter/Test/CMakeLists.txt index ca7eaaa827..2e2952d680 100644 --- a/src/MagnumPlugins/AnyImageConverter/Test/CMakeLists.txt +++ b/src/MagnumPlugins/AnyImageConverter/Test/CMakeLists.txt @@ -29,10 +29,12 @@ find_package(Threads REQUIRED) if(CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID) set(ANYIMAGECONVERTER_TEST_OUTPUT_DIR "write") + set(KTX_1D_FILE 1d.ktx2) set(KTX_3D_FILE 3d.ktx2) set(EXR_FILE depth32f-custom-channels.exr) else() set(ANYIMAGECONVERTER_TEST_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) + set(KTX_1D_FILE ${PROJECT_SOURCE_DIR}/src/MagnumPlugins/AnyImageImporter/Test/1d.ktx2) set(KTX_3D_FILE ${PROJECT_SOURCE_DIR}/src/MagnumPlugins/AnyImageImporter/Test/3d.ktx2) set(EXR_FILE ${PROJECT_SOURCE_DIR}/src/MagnumPlugins/AnyImageImporter/Test/depth32f-custom-channels.exr) endif() @@ -62,6 +64,7 @@ corrade_add_test(AnyImageConverterTest AnyImageConverterTest.cpp # now Threads::Threads FILES + ../../AnyImageImporter/Test/1d.ktx2 ../../AnyImageImporter/Test/3d.ktx2 ../../AnyImageImporter/Test/depth32f-custom-channels.exr) target_include_directories(AnyImageConverterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/$) diff --git a/src/MagnumPlugins/AnyImageConverter/Test/configure.h.cmake b/src/MagnumPlugins/AnyImageConverter/Test/configure.h.cmake index 7b544fd61e..0d7bbf7725 100644 --- a/src/MagnumPlugins/AnyImageConverter/Test/configure.h.cmake +++ b/src/MagnumPlugins/AnyImageConverter/Test/configure.h.cmake @@ -26,6 +26,7 @@ #cmakedefine ANYIMAGECONVERTER_PLUGIN_FILENAME "${ANYIMAGECONVERTER_PLUGIN_FILENAME}" #cmakedefine TGAIMAGECONVERTER_PLUGIN_FILENAME "${TGAIMAGECONVERTER_PLUGIN_FILENAME}" #define ANYIMAGECONVERTER_TEST_OUTPUT_DIR "${ANYIMAGECONVERTER_TEST_OUTPUT_DIR}" +#define KTX_1D_FILE "${KTX_1D_FILE}" #define KTX_3D_FILE "${KTX_3D_FILE}" #define EXR_FILE "${EXR_FILE}" diff --git a/src/MagnumPlugins/AnyImageImporter/Test/1d.ktx2 b/src/MagnumPlugins/AnyImageImporter/Test/1d.ktx2 new file mode 100644 index 0000000000..915dd190a9 Binary files /dev/null and b/src/MagnumPlugins/AnyImageImporter/Test/1d.ktx2 differ diff --git a/src/MagnumPlugins/AnyImageImporter/Test/AnyImageImporterTest.cpp b/src/MagnumPlugins/AnyImageImporter/Test/AnyImageImporterTest.cpp index 2de69e3ccf..2c7188d8ae 100644 --- a/src/MagnumPlugins/AnyImageImporter/Test/AnyImageImporterTest.cpp +++ b/src/MagnumPlugins/AnyImageImporter/Test/AnyImageImporterTest.cpp @@ -70,6 +70,16 @@ Containers::Optional> fileCallback(const std:: return Containers::ArrayView{storage}; } +constexpr struct { + const char* name; + const char* filename; + Containers::Optional>(*callback)(const std::string&, InputFileCallbackPolicy, Containers::Array&); + const char* messageFunctionName; +} Load1DData[]{ + {"KTX2", KTX_1D_FILE, nullptr, "KtxImporter"}, + {"KTX2 data", KTX_1D_FILE, fileCallback, "KtxImporter"}, +}; + constexpr struct { const char* name; const char* filename; @@ -149,7 +159,8 @@ constexpr struct { }; AnyImageImporterTest::AnyImageImporterTest() { - addTests({&AnyImageImporterTest::load1D}); + addInstancedTests({&AnyImageImporterTest::load1D}, + Containers::arraySize(Load1DData)); addInstancedTests({&AnyImageImporterTest::load2D}, Containers::arraySize(Load2DData)); @@ -188,7 +199,29 @@ AnyImageImporterTest::AnyImageImporterTest() { } void AnyImageImporterTest::load1D() { - CORRADE_SKIP("No file formats supporting 1D images yet."); + auto&& data = Load1DData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + PluginManager::Manager manager{MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR}; + #ifdef ANYIMAGEIMPORTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGEIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.loadState("KtxImporter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("KtxImporter plugin can't be loaded."); + + Containers::Pointer importer = manager.instantiate("AnyImageImporter"); + + Containers::Array storage; + importer->setFileCallback(data.callback, storage); + + CORRADE_VERIFY(importer->openFile(data.filename)); + CORRADE_COMPARE(importer->image1DCount(), 1); + + /* Check only size, as it is good enough proof that it is working */ + Containers::Optional image = importer->image1D(0); + CORRADE_VERIFY(image); + CORRADE_COMPARE(image->size(), 2); } void AnyImageImporterTest::load2D() { diff --git a/src/MagnumPlugins/AnyImageImporter/Test/CMakeLists.txt b/src/MagnumPlugins/AnyImageImporter/Test/CMakeLists.txt index 1e918ad8a1..0bef5ecd27 100644 --- a/src/MagnumPlugins/AnyImageImporter/Test/CMakeLists.txt +++ b/src/MagnumPlugins/AnyImageImporter/Test/CMakeLists.txt @@ -26,11 +26,13 @@ if(CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID) set(TEST_FILE_DIR .) set(TGA_FILE rgb.tga) + set(KTX_1D_FILE 1d.ktx2) set(KTX_3D_FILE 3d.ktx2) set(EXR_FILE depth32f-custom-channels.exr) else() set(TEST_FILE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(TGA_FILE ${CMAKE_CURRENT_SOURCE_DIR}/rgb.tga) + set(KTX_1D_FILE ${CMAKE_CURRENT_SOURCE_DIR}/1d.ktx2) set(KTX_3D_FILE ${CMAKE_CURRENT_SOURCE_DIR}/3d.ktx2) set(EXR_FILE ${CMAKE_CURRENT_SOURCE_DIR}/depth32f-custom-channels.exr) endif() @@ -57,7 +59,8 @@ corrade_add_test(AnyImageImporterTest AnyImageImporterTest.cpp FILES # Generated by AnyImageConverterTest::propagateConfiguration2D() depth32f-custom-channels.exr - # Generated by AnyImageConverterTest::convert3D() + # Generated by AnyImageConverterTest::convert{1D,3D}() + 1d.ktx2 3d.ktx2 gray.jpg image.exr diff --git a/src/MagnumPlugins/AnyImageImporter/Test/configure.h.cmake b/src/MagnumPlugins/AnyImageImporter/Test/configure.h.cmake index f1277c9f51..33b5018daa 100644 --- a/src/MagnumPlugins/AnyImageImporter/Test/configure.h.cmake +++ b/src/MagnumPlugins/AnyImageImporter/Test/configure.h.cmake @@ -27,6 +27,7 @@ #cmakedefine TGAIMPORTER_PLUGIN_FILENAME "${TGAIMPORTER_PLUGIN_FILENAME}" #define TGA_FILE "${TGA_FILE}" #define TEST_FILE_DIR "${TEST_FILE_DIR}" +#define KTX_1D_FILE "${KTX_1D_FILE}" #define KTX_3D_FILE "${KTX_3D_FILE}" #define EXR_FILE "${EXR_FILE}"