From 2df2a4700704b0d4ed4aa9ebe0e0b16705e4ff35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 8 Apr 2021 20:50:52 +0200 Subject: [PATCH] Trade: support 1D and 3D images in AbstractImageConverter. I wanted just 3D at first, but then thought why not do 1D as well. Lots of dry copypasted code, nothing interesting to see here. --- doc/changelog.dox | 1 + src/Magnum/Trade/AbstractImageConverter.cpp | 242 +++- src/Magnum/Trade/AbstractImageConverter.h | 422 ++++++- .../Trade/Test/AbstractImageConverterTest.cpp | 1102 ++++++++++++++++- 4 files changed, 1723 insertions(+), 44 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index a797692ca..80f29afce 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -179,6 +179,7 @@ See also: - New @ref Trade::SkinData class and @ref Trade::AbstractImporter::skin2D() / @ref Trade::AbstractImporter::skin3D() family of APIs for skin import, as well as support in @ref Trade::AnySceneImporter "AnySceneImporter" +- 1D and 3D image support in @ref Trade::AbstractImageConverter - @ref Trade::LightData got extended to support light attenuation and range parameters as well and spot light inner and outer angle - @ref Trade::AbstractImporter, @ref Trade::AbstractImageConverter and diff --git a/src/Magnum/Trade/AbstractImageConverter.cpp b/src/Magnum/Trade/AbstractImageConverter.cpp index fc01a90b3..b1bf51373 100644 --- a/src/Magnum/Trade/AbstractImageConverter.cpp +++ b/src/Magnum/Trade/AbstractImageConverter.cpp @@ -95,6 +95,19 @@ void AbstractImageConverter::clearFlags(ImageConverterFlags flags) { setFlags(_flags & ~flags); } +Containers::Optional AbstractImageConverter::convert(const ImageView1D& image) { + CORRADE_ASSERT(features() & ImageConverterFeature::Convert1D, + "Trade::AbstractImageConverter::convert(): 1D image conversion not supported", {}); + + Containers::Optional out = doConvert(image); + CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Optional AbstractImageConverter::doConvert(const ImageView1D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convert(): 1D image conversion advertised but not implemented", {}); +} + Containers::Optional AbstractImageConverter::convert(const ImageView2D& image) { CORRADE_ASSERT(features() & ImageConverterFeature::Convert2D, "Trade::AbstractImageConverter::convert(): 2D image conversion not supported", {}); @@ -140,6 +153,32 @@ Containers::Optional AbstractImageConverter::exportToCompress } #endif +Containers::Optional AbstractImageConverter::convert(const ImageView3D& image) { + CORRADE_ASSERT(features() & ImageConverterFeature::Convert3D, + "Trade::AbstractImageConverter::convert(): 3D image conversion not supported", {}); + + Containers::Optional out = doConvert(image); + CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Optional AbstractImageConverter::doConvert(const ImageView3D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convert(): 3D image conversion advertised but not implemented", {}); +} + +Containers::Optional AbstractImageConverter::convert(const CompressedImageView1D& image) { + CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed1D, + "Trade::AbstractImageConverter::convert(): compressed 1D image conversion not supported", {}); + + Containers::Optional out = doConvert(image); + CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Optional AbstractImageConverter::doConvert(const CompressedImageView1D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convert(): compressed 1D image conversion advertised but not implemented", {}); +} + Containers::Optional AbstractImageConverter::convert(const CompressedImageView2D& image) { CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed2D, "Trade::AbstractImageConverter::convert(): compressed 2D image conversion not supported", {}); @@ -153,10 +192,44 @@ Containers::Optional AbstractImageConverter::doConvert(const Compre CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convert(): compressed 2D image conversion advertised but not implemented", {}); } +Containers::Optional AbstractImageConverter::convert(const CompressedImageView3D& image) { + CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed3D, + "Trade::AbstractImageConverter::convert(): compressed 3D image conversion not supported", {}); + + Containers::Optional out = doConvert(image); + CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Optional AbstractImageConverter::doConvert(const CompressedImageView3D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convert(): compressed 3D image conversion advertised but not implemented", {}); +} + +Containers::Optional AbstractImageConverter::convert(const ImageData1D& image) { + return image.isCompressed() ? convert(CompressedImageView1D(image)) : convert(ImageView1D(image)); +} + Containers::Optional AbstractImageConverter::convert(const ImageData2D& image) { return image.isCompressed() ? convert(CompressedImageView2D(image)) : convert(ImageView2D(image)); } +Containers::Optional AbstractImageConverter::convert(const ImageData3D& image) { + return image.isCompressed() ? convert(CompressedImageView3D(image)) : convert(ImageView3D(image)); +} + +Containers::Array AbstractImageConverter::convertToData(const ImageView1D& image) { + CORRADE_ASSERT(features() >= ImageConverterFeature::Convert1DToData, + "Trade::AbstractImageConverter::convertToData(): 1D image conversion not supported", nullptr); + + Containers::Array out = doConvertToData(image); + CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Array AbstractImageConverter::doConvertToData(const ImageView1D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convertToData(): 1D image conversion advertised but not implemented", nullptr); +} + Containers::Array AbstractImageConverter::convertToData(const ImageView2D& image) { CORRADE_ASSERT(features() >= ImageConverterFeature::Convert2DToData, "Trade::AbstractImageConverter::convertToData(): 2D image conversion not supported", nullptr); @@ -176,6 +249,32 @@ Containers::Array AbstractImageConverter::exportToData(const ImageView2D& } #endif +Containers::Array AbstractImageConverter::convertToData(const ImageView3D& image) { + CORRADE_ASSERT(features() >= ImageConverterFeature::Convert3DToData, + "Trade::AbstractImageConverter::convertToData(): 3D image conversion not supported", nullptr); + + Containers::Array out = doConvertToData(image); + CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Array AbstractImageConverter::doConvertToData(const ImageView3D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convertToData(): 3D image conversion advertised but not implemented", nullptr); +} + +Containers::Array AbstractImageConverter::convertToData(const CompressedImageView1D& image) { + CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed1DToData, + "Trade::AbstractImageConverter::convertToData(): compressed 1D image conversion not supported", nullptr); + + Containers::Array out = doConvertToData(image); + CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Array AbstractImageConverter::doConvertToData(const CompressedImageView1D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convertToData(): compressed 1D image conversion advertised but not implemented", nullptr); +} + Containers::Array AbstractImageConverter::convertToData(const CompressedImageView2D& image) { CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed2DToData, "Trade::AbstractImageConverter::convertToData(): compressed 2D image conversion not supported", nullptr); @@ -195,6 +294,23 @@ Containers::Array AbstractImageConverter::exportToData(const CompressedIma } #endif +Containers::Array AbstractImageConverter::convertToData(const CompressedImageView3D& image) { + CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed3DToData, + "Trade::AbstractImageConverter::convertToData(): compressed 3D image conversion not supported", nullptr); + + Containers::Array out = doConvertToData(image); + CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Array AbstractImageConverter::doConvertToData(const CompressedImageView3D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convertToData(): compressed 3D image conversion advertised but not implemented", nullptr); +} + +Containers::Array AbstractImageConverter::convertToData(const ImageData1D& image) { + return image.isCompressed() ? convertToData(CompressedImageView1D(image)) : convertToData(ImageView1D(image)); +} + Containers::Array AbstractImageConverter::convertToData(const ImageData2D& image) { return image.isCompressed() ? convertToData(CompressedImageView2D(image)) : convertToData(ImageView2D(image)); } @@ -205,6 +321,32 @@ Containers::Array AbstractImageConverter::exportToData(const ImageData2D& } #endif +Containers::Array AbstractImageConverter::convertToData(const ImageData3D& image) { + return image.isCompressed() ? convertToData(CompressedImageView3D(image)) : convertToData(ImageView3D(image)); +} + +bool AbstractImageConverter::convertToFile(const ImageView1D& image, const Containers::StringView filename) { + CORRADE_ASSERT(features() & ImageConverterFeature::Convert1DToFile, + "Trade::AbstractImageConverter::convertToFile(): 1D image conversion not supported", {}); + + return doConvertToFile(image, filename); +} + +bool AbstractImageConverter::doConvertToFile(const ImageView1D& image, const Containers::StringView filename) { + CORRADE_ASSERT(features() >= ImageConverterFeature::Convert1DToData, "Trade::AbstractImageConverter::convertToFile(): 1D image conversion advertised but not implemented", false); + + const auto data = doConvertToData(image); + /* No deleter checks as it doesn't matter here */ + if(!data) return false; + + if(!Utility::Directory::write(filename, data)) { + Error() << "Trade::AbstractImageConverter::convertToFile(): cannot write to file" << filename; + return false; + } + + return true; +} + bool AbstractImageConverter::convertToFile(const ImageView2D& image, const Containers::StringView filename) { CORRADE_ASSERT(features() & ImageConverterFeature::Convert2DToFile, "Trade::AbstractImageConverter::convertToFile(): 2D image conversion not supported", {}); @@ -233,6 +375,50 @@ bool AbstractImageConverter::exportToFile(const ImageView2D& image, const std::s } #endif +bool AbstractImageConverter::convertToFile(const ImageView3D& image, const Containers::StringView filename) { + CORRADE_ASSERT(features() & ImageConverterFeature::Convert3DToFile, + "Trade::AbstractImageConverter::convertToFile(): 3D image conversion not supported", {}); + + return doConvertToFile(image, filename); +} + +bool AbstractImageConverter::doConvertToFile(const ImageView3D& image, const Containers::StringView filename) { + CORRADE_ASSERT(features() >= ImageConverterFeature::Convert3DToData, "Trade::AbstractImageConverter::convertToFile(): 3D image conversion advertised but not implemented", false); + + const auto data = doConvertToData(image); + /* No deleter checks as it doesn't matter here */ + if(!data) return false; + + if(!Utility::Directory::write(filename, data)) { + Error() << "Trade::AbstractImageConverter::convertToFile(): cannot write to file" << filename; + return false; + } + + return true; +} + +bool AbstractImageConverter::convertToFile(const CompressedImageView1D& image, const Containers::StringView filename) { + CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed1DToFile, + "Trade::AbstractImageConverter::convertToFile(): compressed 1D image conversion not supported", {}); + + return doConvertToFile(image, filename); +} + +bool AbstractImageConverter::doConvertToFile(const CompressedImageView1D& image, Containers::StringView filename) { + CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed1DToData, "Trade::AbstractImageConverter::convertToFile(): compressed 1D image conversion advertised but not implemented", false); + + const auto data = doConvertToData(image); + /* No deleter checks as it doesn't matter here */ + if(!data) return false; + + if(!Utility::Directory::write(filename, data)) { + Error() << "Trade::AbstractImageConverter::convertToFile(): cannot write to file" << filename; + return false; + } + + return true; +} + bool AbstractImageConverter::convertToFile(const CompressedImageView2D& image, const Containers::StringView filename) { CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed2DToFile, "Trade::AbstractImageConverter::convertToFile(): compressed 2D image conversion not supported", {}); @@ -261,6 +447,32 @@ bool AbstractImageConverter::exportToFile(const CompressedImageView2D& image, co } #endif +bool AbstractImageConverter::convertToFile(const CompressedImageView3D& image, const Containers::StringView filename) { + CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed3DToFile, + "Trade::AbstractImageConverter::convertToFile(): compressed 3D image conversion not supported", {}); + + return doConvertToFile(image, filename); +} + +bool AbstractImageConverter::doConvertToFile(const CompressedImageView3D& image, Containers::StringView filename) { + CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed3DToData, "Trade::AbstractImageConverter::convertToFile(): compressed 3D image conversion advertised but not implemented", false); + + const auto data = doConvertToData(image); + /* No deleter checks as it doesn't matter here */ + if(!data) return false; + + if(!Utility::Directory::write(filename, data)) { + Error() << "Trade::AbstractImageConverter::convertToFile(): cannot write to file" << filename; + return false; + } + + return true; +} + +bool AbstractImageConverter::convertToFile(const ImageData1D& image, const Containers::StringView filename) { + return image.isCompressed() ? convertToFile(CompressedImageView1D(image), filename) : convertToFile(ImageView1D(image), filename); +} + bool AbstractImageConverter::convertToFile(const ImageData2D& image, const Containers::StringView filename) { return image.isCompressed() ? convertToFile(CompressedImageView2D(image), filename) : convertToFile(ImageView2D(image), filename); } @@ -271,18 +483,34 @@ bool AbstractImageConverter::exportToFile(const ImageData2D& image, const std::s } #endif +bool AbstractImageConverter::convertToFile(const ImageData3D& image, const Containers::StringView filename) { + return image.isCompressed() ? convertToFile(CompressedImageView3D(image), filename) : convertToFile(ImageView3D(image), filename); +} + Debug& operator<<(Debug& debug, const ImageConverterFeature value) { debug << "Trade::ImageConverterFeature" << Debug::nospace; switch(value) { /* LCOV_EXCL_START */ #define _c(v) case ImageConverterFeature::v: return debug << "::" #v; + _c(Convert1D) _c(Convert2D) + _c(Convert3D) + _c(ConvertCompressed1D) _c(ConvertCompressed2D) + _c(ConvertCompressed3D) + _c(Convert1DToFile) _c(Convert2DToFile) + _c(Convert3DToFile) + _c(ConvertCompressed1DToFile) _c(ConvertCompressed2DToFile) + _c(ConvertCompressed3DToFile) + _c(Convert1DToData) _c(Convert2DToData) + _c(Convert3DToData) + _c(ConvertCompressed1DToData) _c(ConvertCompressed2DToData) + _c(ConvertCompressed3DToData) #undef _c /* LCOV_EXCL_STOP */ } @@ -292,13 +520,25 @@ Debug& operator<<(Debug& debug, const ImageConverterFeature value) { Debug& operator<<(Debug& debug, const ImageConverterFeatures value) { return Containers::enumSetDebugOutput(debug, value, "Trade::ImageConverterFeatures{}", { + ImageConverterFeature::Convert1D, ImageConverterFeature::Convert2D, + ImageConverterFeature::Convert3D, + ImageConverterFeature::ConvertCompressed1D, ImageConverterFeature::ConvertCompressed2D, + ImageConverterFeature::ConvertCompressed3D, + ImageConverterFeature::Convert1DToData, ImageConverterFeature::Convert2DToData, + ImageConverterFeature::Convert3DToData, + ImageConverterFeature::ConvertCompressed1DToData, ImageConverterFeature::ConvertCompressed2DToData, + ImageConverterFeature::ConvertCompressed3DToData, /* These are implied by Convert[Compressed]ToData, so have to be last */ + ImageConverterFeature::Convert1DToFile, ImageConverterFeature::Convert2DToFile, - ImageConverterFeature::ConvertCompressed2DToFile}); + ImageConverterFeature::Convert3DToFile, + ImageConverterFeature::ConvertCompressed1DToFile, + ImageConverterFeature::ConvertCompressed2DToFile, + ImageConverterFeature::ConvertCompressed3DToFile}); } Debug& operator<<(Debug& debug, const ImageConverterFlag value) { diff --git a/src/Magnum/Trade/AbstractImageConverter.h b/src/Magnum/Trade/AbstractImageConverter.h index a49ed123c..02a147d6a 100644 --- a/src/Magnum/Trade/AbstractImageConverter.h +++ b/src/Magnum/Trade/AbstractImageConverter.h @@ -44,12 +44,19 @@ namespace Magnum { namespace Trade { @see @ref ImageConverterFeatures, @ref AbstractImageConverter::features() */ enum class ImageConverterFeature: UnsignedInt { + /** + * Convert a 1D image with + * @ref AbstractImageConverter::convert(const ImageView1D&) + * @m_since_latest + */ + Convert1D = 1 << 0, + /** * Convert a 2D image with * @ref AbstractImageConverter::convert(const ImageView2D&) * @m_since_latest */ - Convert2D = 1 << 0, + Convert2D = 1 << 1, #ifdef MAGNUM_BUILD_DEPRECATED /** @@ -71,19 +78,47 @@ enum class ImageConverterFeature: UnsignedInt { ConvertCompressedImage CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::Convert2D instead") = Convert2D, #endif + /** + * Convert a 3D image with + * @ref AbstractImageConverter::convert(const ImageView3D&) + * @m_since_latest + */ + Convert3D = 1 << 3, + + /** + * Convert a compressed 1D image with + * @ref AbstractImageConverter::convert(const CompressedImageView1D&) + * @m_since_latest + */ + ConvertCompressed1D = 1 << 4, + /** * Convert a compressed 2D image with * @ref AbstractImageConverter::convert(const CompressedImageView2D&) * @m_since_latest */ - ConvertCompressed2D = 1 << 1, + ConvertCompressed2D = 1 << 5, + + /** + * Convert a compressed 3D image with + * @ref AbstractImageConverter::convert(const CompressedImageView3D&) + * @m_since_latest + */ + ConvertCompressed3D = 1 << 6, + + /** + * Convert a 1D image to a file with + * @ref AbstractImageConverter::convertToFile(const ImageView1D&, Containers::StringView) + * @m_since_latest + */ + Convert1DToFile = 1 << 7, /** * Convert a 2D image to a file with * @ref AbstractImageConverter::convertToFile(const ImageView2D&, Containers::StringView) * @m_since_latest */ - Convert2DToFile = 1 << 2, + Convert2DToFile = 1 << 8, #ifdef MAGNUM_BUILD_DEPRECATED /** @@ -94,12 +129,26 @@ enum class ImageConverterFeature: UnsignedInt { ConvertFile CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::Convert2DToFile instead") = Convert2DToFile, #endif + /** + * Convert a 3D image to a file with + * @ref AbstractImageConverter::convertToFile(const ImageView3D&, Containers::StringView) + * @m_since_latest + */ + Convert3DToFile = 1 << 9, + + /** + * Convert a compressed 1D image to a file with + * @ref AbstractImageConverter::convertToFile(const CompressedImageView1D&, Containers::StringView) + * @m_since_latest + */ + ConvertCompressed1DToFile = 1 << 10, + /** * Convert a compressed 2D image to a file with * @ref AbstractImageConverter::convertToFile(const CompressedImageView2D&, Containers::StringView) * @m_since_latest */ - ConvertCompressed2DToFile = 1 << 3, + ConvertCompressed2DToFile = 1 << 11, #ifdef MAGNUM_BUILD_DEPRECATED /** @@ -110,13 +159,28 @@ enum class ImageConverterFeature: UnsignedInt { ConvertCompressedFile CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::ConvertCompressed2DToFile instead") = ConvertCompressed2DToFile, #endif + /** + * Convert a compressed 3D image to a file with + * @ref AbstractImageConverter::convertToFile(const CompressedImageView3D&, Containers::StringView) + * @m_since_latest + */ + ConvertCompressed3DToFile = 1 << 12, + + /** + * Convert a 1D image to raw data with + * @ref AbstractImageConverter::convertToData(const ImageView1D&). + * Implies @ref ImageConverterFeature::Convert1DToFile. + * @m_since_latest + */ + Convert1DToData = Convert1DToFile|(1 << 13), + /** * Convert a 2D image to raw data with * @ref AbstractImageConverter::convertToData(const ImageView2D&). * Implies @ref ImageConverterFeature::Convert2DToFile. * @m_since_latest */ - Convert2DToData = Convert2DToFile|(1 << 4), + Convert2DToData = Convert2DToFile|(1 << 13), #ifdef MAGNUM_BUILD_DEPRECATED /** @@ -127,13 +191,29 @@ enum class ImageConverterFeature: UnsignedInt { ConvertData CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::Convert2DToData instead") = Convert2DToData, #endif + /** + * Convert a 3D image to raw data with + * @ref AbstractImageConverter::convertToData(const ImageView3D&). + * Implies @ref ImageConverterFeature::Convert3DToFile. + * @m_since_latest + */ + Convert3DToData = Convert3DToFile|(1 << 13), + + /** + * Convert a compressed 1D image to raw data with + * @ref AbstractImageConverter::convertToData(const CompressedImageView1D&). + * Implies @ref ImageConverterFeature::ConvertCompressed1DToFile. + * @m_since_latest + */ + ConvertCompressed1DToData = ConvertCompressed1DToFile|(1 << 13), + /** * Convert a compressed 2D image to raw data with * @ref AbstractImageConverter::convertToData(const CompressedImageView2D&). * Implies @ref ImageConverterFeature::ConvertCompressed2DToFile. * @m_since_latest */ - ConvertCompressed2DToData = ConvertCompressed2DToFile|(1 << 4), + ConvertCompressed2DToData = ConvertCompressed2DToFile|(1 << 13), #ifdef MAGNUM_BUILD_DEPRECATED /** @@ -143,6 +223,14 @@ enum class ImageConverterFeature: UnsignedInt { */ ConvertCompressedData CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::ConvertCompressed2DToData instead") = ConvertCompressed2DToData, #endif + + /** + * Convert a compressed 3D image to raw data with + * @ref AbstractImageConverter::convertToData(const CompressedImageView3D&). + * Implies @ref ImageConverterFeature::ConvertCompressed3DToFile. + * @m_since_latest + */ + ConvertCompressed3DToData = ConvertCompressed3DToFile|(1 << 13) }; /** @@ -353,6 +441,21 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract */ void clearFlags(ImageConverterFlags flags); + /** + * @brief Convert a 1D image + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::Convert1D is + * supported. Returns converted image on success, + * @ref Containers::NullOpt otherwise. The implementation is allowed to + * return both a compressed an an uncompressed image, see documentation + * of a particular converter for more information. + * @see @ref features(), @ref convert(const CompressedImageView1D&), + * @ref convert(const ImageData1D&), @ref convertToData(), + * @ref convertToFile(), @ref ImageData::isCompressed() + */ + Containers::Optional convert(const ImageView1D& image); + /** * @brief Convert a 2D image * @m_since_latest @@ -384,6 +487,36 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract CORRADE_DEPRECATED("use convert(const ImageView2D&) instead") Containers::Optional exportToCompressedImage(const ImageView2D& image); #endif + /** + * @brief Convert a 3D image + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::Convert3D is + * supported. Returns converted image on success, + * @ref Containers::NullOpt otherwise. The implementation is allowed to + * return both a compressed an an uncompressed image, see documentation + * of a particular converter for more information. + * @see @ref features(), @ref convert(const CompressedImageView3D&), + * @ref convert(const ImageData3D&), @ref convertToData(), + * @ref convertToFile(), @ref ImageData::isCompressed() + */ + Containers::Optional convert(const ImageView3D& image); + + /** + * @brief Convert a compressed 1D image + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::ConvertCompressed1D is + * supported. Returns converted image on success, + * @ref Containers::NullOpt otherwise. The implementation is allowed to + * return both a compressed an an uncompressed image, see documentation + * of a particular converter for more information. + * @see @ref features(), @ref convert(const ImageView1D&), + * @ref convert(const ImageData1D&), @ref convertToData(), + * @ref convertToFile(), @ref ImageData::isCompressed() + */ + Containers::Optional convert(const CompressedImageView1D& image); + /** * @brief Convert a compressed 2D image * @m_since_latest @@ -399,6 +532,33 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract */ Containers::Optional convert(const CompressedImageView2D& image); + /** + * @brief Convert a compressed 3D image + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::ConvertCompressed3D is + * supported. Returns converted image on success, + * @ref Containers::NullOpt otherwise. The implementation is allowed to + * return both a compressed an an uncompressed image, see documentation + * of a particular converter for more information. + * @see @ref features(), @ref convert(const ImageView3D&), + * @ref convert(const ImageData3D&), @ref convertToData(), + * @ref convertToFile(), @ref ImageData::isCompressed() + */ + Containers::Optional convert(const CompressedImageView3D& image); + + /** + * @brief Convert a 1D image data + * @m_since_latest + * + * Based on whether the image is compressed or not, calls either + * @ref convert(const ImageView1D&) or + * @ref convert(const CompressedImageView1D&). See documentation of + * these two functions for details. + * @see @ref ImageData::isCompressed() + */ + Containers::Optional convert(const ImageData1D& image); + /** * @brief Convert a 2D image data * @m_since_latest @@ -411,6 +571,30 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract */ Containers::Optional convert(const ImageData2D& image); + /** + * @brief Convert a 3D image data + * @m_since_latest + * + * Based on whether the image is compressed or not, calls either + * @ref convert(const ImageView3D&) or + * @ref convert(const CompressedImageView3D&). See documentation of + * these two functions for details. + * @see @ref ImageData::isCompressed() + */ + Containers::Optional convert(const ImageData3D& image); + + /** + * @brief Convert a 1D image to a raw data + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::Convert1DToData is + * supported. Returns data on success, @cpp nullptr @ce otherwise. + * @see @ref features(), @ref convertToData(const CompressedImageView1D&), + * @ref convertToData(const ImageData1D&), @ref convert(), + * @ref convertToFile() + */ + Containers::Array convertToData(const ImageView1D& image); + /** * @brief Convert a 2D image to a raw data * @m_since_latest @@ -432,6 +616,30 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract CORRADE_DEPRECATED("use convertToData(const ImageView2D&) instead") Containers::Array exportToData(const ImageView2D& image); #endif + /** + * @brief Convert a 3D image to a raw data + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::Convert3DToData is + * supported. Returns data on success, @cpp nullptr @ce otherwise. + * @see @ref features(), @ref convertToData(const CompressedImageView3D&), + * @ref convertToData(const ImageData3D&), @ref convert(), + * @ref convertToFile() + */ + Containers::Array convertToData(const ImageView3D& image); + + /** + * @brief Convert a compressed 1D image to a raw data + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::ConvertCompressed1DToData + * is supported. Returns data on success, @cpp nullptr @ce otherwise. + * @see @ref features(), @ref convertToData(const ImageView1D&), + * @ref convertToData(const ImageData1D&), @ref convert(), + * @ref convertToFile() + */ + Containers::Array convertToData(const CompressedImageView1D& image); + /** * @brief Convert a compressed 2D image to a raw data * @m_since_latest @@ -453,6 +661,30 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract CORRADE_DEPRECATED("use convertToData(const CompressedImageView2D&) instead") Containers::Array exportToData(const CompressedImageView2D& image); #endif + /** + * @brief Convert a compressed 3D image to a raw data + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::ConvertCompressed3DToData + * is supported. Returns data on success, @cpp nullptr @ce otherwise. + * @see @ref features(), @ref convertToData(const ImageView3D&), + * @ref convertToData(const ImageData3D&), @ref convert() + * @ref convertToFile() + */ + Containers::Array convertToData(const CompressedImageView3D& image); + + /** + * @brief Convert a 1D image data to a raw data + * @m_since_latest + * + * Based on whether the image is compressed or not, calls either + * @ref convertToData(const ImageView1D&) or + * @ref convertToData(const CompressedImageView1D&). See documentation + * of these two functions for details. + * @see @ref ImageData::isCompressed() + */ + Containers::Array convertToData(const ImageData1D& image); + /** * @brief Convert a 2D image data to a raw data * @m_since_latest @@ -474,6 +706,31 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract CORRADE_DEPRECATED("use convertToData(const ImageView2D&) instead") Containers::Array exportToData(const ImageData2D& image); #endif + /** + * @brief Convert a 3D image data to a raw data + * @m_since_latest + * + * Based on whether the image is compressed or not, calls either + * @ref convertToData(const ImageView3D&) or + * @ref convertToData(const CompressedImageView3D&). See documentation + * of these two functions for details. + * @see @ref ImageData::isCompressed() + */ + Containers::Array convertToData(const ImageData3D& image); + + /** + * @brief Convert a 1D image to a file + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::Convert1DToFile or + * @ref ImageConverterFeature::Convert1DToData is supported. Returns + * @cpp true @ce on success, @cpp false @ce otherwise. + * @see @ref features(), @ref convertToFile(const CompressedImageView1D&, Containers::StringView), + * @ref convertToFile(const ImageData1D&, Containers::StringView), + * @ref convert(), @ref convertToData() + */ + bool convertToFile(const ImageView1D& image, Containers::StringView filename); + /** * @brief Convert a 2D image to a file * @m_since_latest @@ -497,6 +754,33 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract CORRADE_DEPRECATED("use convertToFile(const ImageView2D&, Containers::StringView) instead") bool exportToFile(const ImageView2D& image, const std::string& filename); #endif + /** + * @brief Convert a 3D image to a file + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::Convert3DToFile or + * @ref ImageConverterFeature::Convert3DToData is supported. Returns + * @cpp true @ce on success, @cpp false @ce otherwise. + * @see @ref features(), @ref convertToFile(const CompressedImageView3D&, Containers::StringView), + * @ref convertToFile(const ImageData3D&, Containers::StringView), + * @ref convert(), @ref convertToData() + */ + bool convertToFile(const ImageView3D& image, Containers::StringView filename); + + /** + * @brief Convert a compressed 1D image to a file + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::ConvertCompressed1DToFile + * or @ref ImageConverterFeature::ConvertCompressed1DToData is + * supported. Returns @cpp true @ce on success, @cpp false @ce + * otherwise. + * @see @ref features(), @ref convertToFile(const ImageView1D&, Containers::StringView), + * @ref convertToFile(const ImageData1D&, Containers::StringView), + * @ref convert(), @ref convertToData() + */ + bool convertToFile(const CompressedImageView1D& image, Containers::StringView filename); + /** * @brief Convert a compressed 2D image to a file * @m_since_latest @@ -521,6 +805,32 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract CORRADE_DEPRECATED("use convertToFile(const CompressedImageView2D&, Containers::StringView) instead") bool exportToFile(const CompressedImageView2D& image, const std::string& filename); #endif + /** + * @brief Convert a compressed 3D image to a file + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::ConvertCompressed3DToFile + * or @ref ImageConverterFeature::ConvertCompressed3DToData is + * supported. Returns @cpp true @ce on success, @cpp false @ce + * otherwise. + * @see @ref features(), @ref convertToFile(const ImageView3D&, Containers::StringView), + * @ref convertToFile(const ImageData3D&, Containers::StringView), + * @ref convert(), @ref convertToData() + */ + bool convertToFile(const CompressedImageView3D& image, Containers::StringView filename); + + /** + * @brief Convert a 1D image data to a file + * @m_since_latest + * + * Based on whether the image is compressed or not, calls either + * @ref convertToFile(const ImageView1D&, Containers::StringView) or + * @ref convertToFile(const CompressedImageView1D&, Containers::StringView). + * See documentation of these two functions for details. + * @see @ref ImageData::isCompressed() + */ + bool convertToFile(const ImageData1D& image, Containers::StringView filename); + /** * @brief Convert a 2D image data to a file * @m_since_latest @@ -543,6 +853,18 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract CORRADE_DEPRECATED("use convertToFile(const ImageData2D&, Containers::StringView) instead") bool exportToFile(const ImageData2D& image, const std::string& filename); #endif + /** + * @brief Convert a 3D image data to a file + * @m_since_latest + * + * Based on whether the image is compressed or not, calls either + * @ref convertToFile(const ImageView3D&, Containers::StringView) or + * @ref convertToFile(const CompressedImageView3D&, Containers::StringView). + * See documentation of these two functions for details. + * @see @ref ImageData::isCompressed() + */ + bool convertToFile(const ImageData3D& image, Containers::StringView filename); + private: /** @brief Implementation for @ref features() */ virtual ImageConverterFeatures doFeatures() const = 0; @@ -563,30 +885,88 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract */ virtual void doSetFlags(ImageConverterFlags flags); + /** + * @brief Implementation for @ref convert(const ImageView1D&) + * @m_since_latest + */ + virtual Containers::Optional doConvert(const ImageView1D& image); + /** * @brief Implementation for @ref convert(const ImageView2D&) * @m_since_latest */ virtual Containers::Optional doConvert(const ImageView2D& image); + /** + * @brief Implementation for @ref convert(const ImageView3D&) + * @m_since_latest + */ + virtual Containers::Optional doConvert(const ImageView3D& image); + + /** + * @brief Implementation for @ref convert(const CompressedImageView1D&) + * @m_since_latest + */ + virtual Containers::Optional doConvert(const CompressedImageView1D& image); + /** * @brief Implementation for @ref convert(const CompressedImageView2D&) * @m_since_latest */ virtual Containers::Optional doConvert(const CompressedImageView2D& image); + /** + * @brief Implementation for @ref convert(const CompressedImageView3D&) + * @m_since_latest + */ + virtual Containers::Optional doConvert(const CompressedImageView3D& image); + + /** + * @brief Implementation for @ref convertToData(const ImageView1D&) + * @m_since_latest + */ + virtual Containers::Array doConvertToData(const ImageView1D& image); + /** * @brief Implementation for @ref convertToData(const ImageView2D&) * @m_since_latest */ virtual Containers::Array doConvertToData(const ImageView2D& image); + /** + * @brief Implementation for @ref convertToData(const ImageView3D&) + * @m_since_latest + */ + virtual Containers::Array doConvertToData(const ImageView3D& image); + + /** + * @brief Implementation for @ref convertToData(const CompressedImageView1D&) + * @m_since_latest + */ + virtual Containers::Array doConvertToData(const CompressedImageView1D& image); + /** * @brief Implementation for @ref convertToData(const CompressedImageView2D&) * @m_since_latest */ virtual Containers::Array doConvertToData(const CompressedImageView2D& image); + /** + * @brief Implementation for @ref convertToData(const CompressedImageView3D&) + * @m_since_latest + */ + virtual Containers::Array doConvertToData(const CompressedImageView3D& image); + + /** + * @brief Implementation for @ref convertToFile(const ImageView1D&, Containers::StringView) + * @m_since_latest + * + * If @ref ImageConverterFeature::Convert1DToData is supported, default + * implementation calls @ref doConvertToData(const ImageView1D&) and + * saves the result to given file. + */ + virtual bool doConvertToFile(const ImageView1D& image, Containers::StringView filename); + /** * @brief Implementation for @ref convertToFile(const ImageView2D&, Containers::StringView) * @m_since_latest @@ -597,6 +977,26 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract */ virtual bool doConvertToFile(const ImageView2D& image, Containers::StringView filename); + /** + * @brief Implementation for @ref convertToFile(const ImageView3D&, Containers::StringView) + * @m_since_latest + * + * If @ref ImageConverterFeature::Convert3DToData is supported, default + * implementation calls @ref doConvertToData(const ImageView3D&) and + * saves the result to given file. + */ + virtual bool doConvertToFile(const ImageView3D& image, Containers::StringView filename); + + /** + * @brief Implementation for @ref convertToFile(const CompressedImageView1D&, Containers::StringView) + * @m_since_latest + * + * If @ref ImageConverterFeature::ConvertCompressed1DToData is + * supported, default implementation calls @ref doConvertToData(const CompressedImageView1D&) + * and saves the result to given file. + */ + virtual bool doConvertToFile(const CompressedImageView1D& image, Containers::StringView filename); + /** * @brief Implementation for @ref convertToFile(const CompressedImageView2D&, Containers::StringView) * @m_since_latest @@ -607,6 +1007,16 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract */ virtual bool doConvertToFile(const CompressedImageView2D& image, Containers::StringView filename); + /** + * @brief Implementation for @ref convertToFile(const CompressedImageView3D&, Containers::StringView) + * @m_since_latest + * + * If @ref ImageConverterFeature::ConvertCompressed3DToData is + * supported, default implementation calls @ref doConvertToData(const CompressedImageView3D&) + * and saves the result to given file. + */ + virtual bool doConvertToFile(const CompressedImageView3D& image, Containers::StringView filename); + ImageConverterFlags _flags; }; diff --git a/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp b/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp index bc1eb317e..ce066f722 100644 --- a/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp +++ b/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp @@ -55,39 +55,89 @@ struct AbstractImageConverterTest: TestSuite::Tester { void thingNotSupported(); + void convert1D(); void convert2D(); + void convert3D(); + void convert1DNotImplemented(); void convert2DNotImplemented(); + void convert3DNotImplemented(); + void convert1DCustomDeleter(); void convert2DCustomDeleter(); + void convert3DCustomDeleter(); + void convertCompressed1D(); void convertCompressed2D(); + void convertCompressed3D(); + void convertCompressed1DNotImplemented(); void convertCompressed2DNotImplemented(); + void convertCompressed3DNotImplemented(); + void convertCompressed1DCustomDeleter(); void convertCompressed2DCustomDeleter(); + void convertCompressed3DCustomDeleter(); + void convertImageData1D(); void convertImageData2D(); + void convertImageData3D(); + void convert1DToData(); void convert2DToData(); + void convert3DToData(); + void convert1DToDataNotImplemented(); void convert2DToDataNotImplemented(); + void convert3DToDataNotImplemented(); + void convert1DToDataCustomDeleter(); void convert2DToDataCustomDeleter(); + void convert3DToDataCustomDeleter(); + void convertCompressed1DToData(); void convertCompressed2DToData(); + void convertCompressed3DToData(); + void convertCompressed1DToDataNotImplemented(); void convertCompressed2DToDataNotImplemented(); + void convertCompressed3DToDataNotImplemented(); + void convertCompressed1DToDataCustomDeleter(); void convertCompressed2DToDataCustomDeleter(); + void convertCompressed3DToDataCustomDeleter(); + void convertImageData1DToData(); void convertImageData2DToData(); + void convertImageData3DToData(); + void convert1DToFile(); void convert2DToFile(); + void convert3DToFile(); + void convert1DToFileThroughData(); void convert2DToFileThroughData(); + void convert3DToFileThroughData(); + void convert1DToFileThroughDataFailed(); void convert2DToFileThroughDataFailed(); + void convert3DToFileThroughDataFailed(); + void convert1DToFileThroughDataNotWritable(); void convert2DToFileThroughDataNotWritable(); + void convert3DToFileThroughDataNotWritable(); + void convert1DToFileNotImplemented(); void convert2DToFileNotImplemented(); + void convert3DToFileNotImplemented(); + void convertCompressed1DToFile(); void convertCompressed2DToFile(); + void convertCompressed3DToFile(); + void convertCompressed1DToFileThroughData(); void convertCompressed2DToFileThroughData(); + void convertCompressed3DToFileThroughData(); + void convertCompressed1DToFileThroughDataFailed(); void convertCompressed2DToFileThroughDataFailed(); + void convertCompressed3DToFileThroughDataFailed(); + void convertCompressed1DToFileThroughDataNotWritable(); void convertCompressed2DToFileThroughDataNotWritable(); + void convertCompressed3DToFileThroughDataNotWritable(); + void convertCompressed1DToFileNotImplemented(); void convertCompressed2DToFileNotImplemented(); + void convertCompressed3DToFileNotImplemented(); + void convertImageData1DToFile(); void convertImageData2DToFile(); + void convertImageData3DToFile(); void debugFeature(); void debugFeatures(); @@ -104,39 +154,89 @@ AbstractImageConverterTest::AbstractImageConverterTest() { &AbstractImageConverterTest::thingNotSupported, + &AbstractImageConverterTest::convert1D, &AbstractImageConverterTest::convert2D, + &AbstractImageConverterTest::convert3D, + &AbstractImageConverterTest::convert1DNotImplemented, &AbstractImageConverterTest::convert2DNotImplemented, + &AbstractImageConverterTest::convert3DNotImplemented, + &AbstractImageConverterTest::convert1DCustomDeleter, &AbstractImageConverterTest::convert2DCustomDeleter, + &AbstractImageConverterTest::convert3DCustomDeleter, + &AbstractImageConverterTest::convertCompressed1D, &AbstractImageConverterTest::convertCompressed2D, + &AbstractImageConverterTest::convertCompressed3D, + &AbstractImageConverterTest::convertCompressed1DNotImplemented, &AbstractImageConverterTest::convertCompressed2DNotImplemented, + &AbstractImageConverterTest::convertCompressed3DNotImplemented, + &AbstractImageConverterTest::convertCompressed1DCustomDeleter, &AbstractImageConverterTest::convertCompressed2DCustomDeleter, + &AbstractImageConverterTest::convertCompressed3DCustomDeleter, + &AbstractImageConverterTest::convertImageData1D, &AbstractImageConverterTest::convertImageData2D, + &AbstractImageConverterTest::convertImageData3D, + &AbstractImageConverterTest::convert1DToData, &AbstractImageConverterTest::convert2DToData, + &AbstractImageConverterTest::convert3DToData, + &AbstractImageConverterTest::convert1DToDataNotImplemented, &AbstractImageConverterTest::convert2DToDataNotImplemented, + &AbstractImageConverterTest::convert3DToDataNotImplemented, + &AbstractImageConverterTest::convert1DToDataCustomDeleter, &AbstractImageConverterTest::convert2DToDataCustomDeleter, + &AbstractImageConverterTest::convert3DToDataCustomDeleter, + &AbstractImageConverterTest::convertCompressed1DToData, &AbstractImageConverterTest::convertCompressed2DToData, + &AbstractImageConverterTest::convertCompressed3DToData, + &AbstractImageConverterTest::convertCompressed1DToDataNotImplemented, &AbstractImageConverterTest::convertCompressed2DToDataNotImplemented, + &AbstractImageConverterTest::convertCompressed3DToDataNotImplemented, + &AbstractImageConverterTest::convertCompressed1DToDataCustomDeleter, &AbstractImageConverterTest::convertCompressed2DToDataCustomDeleter, + &AbstractImageConverterTest::convertCompressed3DToDataCustomDeleter, + &AbstractImageConverterTest::convertImageData1DToData, &AbstractImageConverterTest::convertImageData2DToData, + &AbstractImageConverterTest::convertImageData3DToData, + &AbstractImageConverterTest::convert1DToFile, &AbstractImageConverterTest::convert2DToFile, + &AbstractImageConverterTest::convert3DToFile, + &AbstractImageConverterTest::convert1DToFileThroughData, &AbstractImageConverterTest::convert2DToFileThroughData, + &AbstractImageConverterTest::convert3DToFileThroughData, + &AbstractImageConverterTest::convert1DToFileThroughDataFailed, &AbstractImageConverterTest::convert2DToFileThroughDataFailed, + &AbstractImageConverterTest::convert3DToFileThroughDataFailed, + &AbstractImageConverterTest::convert1DToFileThroughDataNotWritable, &AbstractImageConverterTest::convert2DToFileThroughDataNotWritable, + &AbstractImageConverterTest::convert3DToFileThroughDataNotWritable, + &AbstractImageConverterTest::convert1DToFileNotImplemented, &AbstractImageConverterTest::convert2DToFileNotImplemented, + &AbstractImageConverterTest::convert3DToFileNotImplemented, + &AbstractImageConverterTest::convertCompressed1DToFile, &AbstractImageConverterTest::convertCompressed2DToFile, + &AbstractImageConverterTest::convertCompressed3DToFile, + &AbstractImageConverterTest::convertCompressed1DToFileThroughData, &AbstractImageConverterTest::convertCompressed2DToFileThroughData, + &AbstractImageConverterTest::convertCompressed3DToFileThroughData, + &AbstractImageConverterTest::convertCompressed1DToFileThroughDataFailed, &AbstractImageConverterTest::convertCompressed2DToFileThroughDataFailed, + &AbstractImageConverterTest::convertCompressed3DToFileThroughDataFailed, + &AbstractImageConverterTest::convertCompressed1DToFileThroughDataNotWritable, &AbstractImageConverterTest::convertCompressed2DToFileThroughDataNotWritable, + &AbstractImageConverterTest::convertCompressed3DToFileThroughDataNotWritable, + &AbstractImageConverterTest::convertCompressed1DToFileNotImplemented, &AbstractImageConverterTest::convertCompressed2DToFileNotImplemented, + &AbstractImageConverterTest::convertCompressed3DToFileNotImplemented, + &AbstractImageConverterTest::convertImageData1DToFile, &AbstractImageConverterTest::convertImageData2DToFile, + &AbstractImageConverterTest::convertImageData3DToFile, &AbstractImageConverterTest::debugFeature, &AbstractImageConverterTest::debugFeatures, @@ -215,19 +315,58 @@ void AbstractImageConverterTest::thingNotSupported() { std::ostringstream out; Error redirectError{&out}; + converter.convert(ImageView1D{PixelFormat::R8Unorm, 4, Containers::ArrayView{nullptr, 24}}); converter.convert(ImageView2D{PixelFormat::R8Unorm, {4, 6}, Containers::ArrayView{nullptr, 24}}); + converter.convert(ImageView3D{PixelFormat::R8Unorm, {4, 6, 1}, Containers::ArrayView{nullptr, 24}}); + converter.convert(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, {nullptr, 64}}); converter.convert(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, {nullptr, 64}}); + converter.convert(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, {nullptr, 64}}); + converter.convertToData(ImageView1D{PixelFormat::RGBA8Unorm, 4, Containers::ArrayView{nullptr, 96}}); converter.convertToData(ImageView2D{PixelFormat::RGBA8Unorm, {4, 6}, Containers::ArrayView{nullptr, 96}}); + converter.convertToData(ImageView3D{PixelFormat::RGBA8Unorm, {4, 6, 1}, Containers::ArrayView{nullptr, 96}}); + converter.convertToData(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, Containers::ArrayView{nullptr, 64}}); converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); + converter.convertToData(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, Containers::ArrayView{nullptr, 64}}); + converter.convertToFile(ImageView1D{PixelFormat::RGBA8Unorm, 4, {nullptr, 96}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); converter.convertToFile(ImageView2D{PixelFormat::RGBA8Unorm, {4, 6}, {nullptr, 96}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + converter.convertToFile(ImageView3D{PixelFormat::RGBA8Unorm, {4, 6, 1}, {nullptr, 96}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + converter.convertToFile(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, {nullptr, 64}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); converter.convertToFile(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, {nullptr, 64}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + converter.convertToFile(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, {nullptr, 64}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); CORRADE_COMPARE(out.str(), + "Trade::AbstractImageConverter::convert(): 1D image conversion not supported\n" "Trade::AbstractImageConverter::convert(): 2D image conversion not supported\n" + "Trade::AbstractImageConverter::convert(): 3D image conversion not supported\n" + "Trade::AbstractImageConverter::convert(): compressed 1D image conversion not supported\n" "Trade::AbstractImageConverter::convert(): compressed 2D image conversion not supported\n" + "Trade::AbstractImageConverter::convert(): compressed 3D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToData(): 1D image conversion not supported\n" "Trade::AbstractImageConverter::convertToData(): 2D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToData(): 3D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToData(): compressed 1D image conversion not supported\n" "Trade::AbstractImageConverter::convertToData(): compressed 2D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToData(): compressed 3D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToFile(): 1D image conversion not supported\n" "Trade::AbstractImageConverter::convertToFile(): 2D image conversion not supported\n" - "Trade::AbstractImageConverter::convertToFile(): compressed 2D image conversion not supported\n"); + "Trade::AbstractImageConverter::convertToFile(): 3D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToFile(): compressed 1D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToFile(): compressed 2D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToFile(): compressed 3D image conversion not supported\n"); +} + +void AbstractImageConverterTest::convert1D() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1D; } + Containers::Optional doConvert(const ImageView1D& image) override { + return ImageData1D{PixelFormat::RGBA8Unorm, image.size(), Containers::Array{16}}; + } + } converter; + + Containers::Optional actual = converter.convert(ImageView1D{PixelFormat::R8Unorm, 4, Containers::ArrayView{nullptr, 24}}); + CORRADE_VERIFY(actual); + CORRADE_VERIFY(!actual->isCompressed()); + CORRADE_COMPARE(actual->data().size(), 16); + CORRADE_COMPARE(actual->size(), 4); } void AbstractImageConverterTest::convert2D() { @@ -245,6 +384,36 @@ void AbstractImageConverterTest::convert2D() { CORRADE_COMPARE(actual->size(), (Vector2i{4, 6})); } +void AbstractImageConverterTest::convert3D() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3D; } + Containers::Optional doConvert(const ImageView3D& image) override { + return ImageData3D{PixelFormat::RGBA8Unorm, image.size(), Containers::Array{96}}; + } + } converter; + + Containers::Optional actual = converter.convert(ImageView3D{PixelFormat::R8Unorm, {4, 6, 1}, Containers::ArrayView{nullptr, 24}}); + CORRADE_VERIFY(actual); + CORRADE_VERIFY(!actual->isCompressed()); + CORRADE_COMPARE(actual->data().size(), 96); + CORRADE_COMPARE(actual->size(), (Vector3i{4, 6, 1})); +} + +void AbstractImageConverterTest::convert1DNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1D; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(ImageView1D{PixelFormat::R8Unorm, 4, Containers::ArrayView{nullptr, 128}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): 1D image conversion advertised but not implemented\n"); +} + void AbstractImageConverterTest::convert2DNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); @@ -260,6 +429,39 @@ void AbstractImageConverterTest::convert2DNotImplemented() { CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): 2D image conversion advertised but not implemented\n"); } +void AbstractImageConverterTest::convert3DNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3D; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(ImageView3D{PixelFormat::R8Unorm, {4, 6, 1}, Containers::ArrayView{nullptr, 128}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): 3D image conversion advertised but not implemented\n"); +} + +void AbstractImageConverterTest::convert1DCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1D; } + Containers::Optional doConvert(const ImageView1D&) override { + return ImageData1D{PixelFormat::RGBA8Unorm, {}, Containers::Array{nullptr, 0, [](char*, std::size_t) {}}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(ImageView1D{PixelFormat::R8Unorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter\n"); +} + void AbstractImageConverterTest::convert2DCustomDeleter() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); @@ -278,6 +480,39 @@ void AbstractImageConverterTest::convert2DCustomDeleter() { CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter\n"); } +void AbstractImageConverterTest::convert3DCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3D; } + Containers::Optional doConvert(const ImageView3D&) override { + return ImageData3D{PixelFormat::RGBA8Unorm, {}, Containers::Array{nullptr, 0, [](char*, std::size_t) {}}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(ImageView3D{PixelFormat::R8Unorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter\n"); +} + +void AbstractImageConverterTest::convertCompressed1D() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1D; } + Containers::Optional doConvert(const CompressedImageView1D& image) override { + return ImageData1D{image.format(), image.size(), Containers::Array{64}}; + } + } converter; + + Containers::Optional actual = converter.convert(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, Containers::ArrayView{nullptr, 128}}); + CORRADE_VERIFY(actual); + CORRADE_VERIFY(actual->isCompressed()); + CORRADE_COMPARE(actual->data().size(), 64); + CORRADE_COMPARE(actual->size(), 16); +} + void AbstractImageConverterTest::convertCompressed2D() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2D; } @@ -293,6 +528,36 @@ void AbstractImageConverterTest::convertCompressed2D() { CORRADE_COMPARE(actual->size(), (Vector2i{16, 8})); } +void AbstractImageConverterTest::convertCompressed3D() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3D; } + Containers::Optional doConvert(const CompressedImageView3D& image) override { + return ImageData3D{image.format(), image.size(), Containers::Array{64}}; + } + } converter; + + Containers::Optional actual = converter.convert(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, Containers::ArrayView{nullptr, 128}}); + CORRADE_VERIFY(actual); + CORRADE_VERIFY(actual->isCompressed()); + CORRADE_COMPARE(actual->data().size(), 64); + CORRADE_COMPARE(actual->size(), (Vector3i{16, 8, 1})); +} + +void AbstractImageConverterTest::convertCompressed1DNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1D; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, Containers::ArrayView{nullptr, 128}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): compressed 1D image conversion advertised but not implemented\n"); +} + void AbstractImageConverterTest::convertCompressed2DNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); @@ -308,6 +573,39 @@ void AbstractImageConverterTest::convertCompressed2DNotImplemented() { CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): compressed 2D image conversion advertised but not implemented\n"); } +void AbstractImageConverterTest::convertCompressed3DNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3D; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, Containers::ArrayView{nullptr, 128}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): compressed 3D image conversion advertised but not implemented\n"); +} + +void AbstractImageConverterTest::convertCompressed1DCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1D; } + Containers::Optional doConvert(const CompressedImageView1D&) override { + return ImageData1D{CompressedPixelFormat::Bc1RGBAUnorm, {}, Containers::Array{nullptr, 0, [](char*, std::size_t) {}}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter\n"); +} + void AbstractImageConverterTest::convertCompressed2DCustomDeleter() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); @@ -326,6 +624,56 @@ void AbstractImageConverterTest::convertCompressed2DCustomDeleter() { CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter\n"); } +void AbstractImageConverterTest::convertCompressed3DCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3D; } + Containers::Optional doConvert(const CompressedImageView3D&) override { + return ImageData3D{CompressedPixelFormat::Bc1RGBAUnorm, {}, Containers::Array{nullptr, 0, [](char*, std::size_t) {}}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter\n"); +} + +void AbstractImageConverterTest::convertImageData1D() { + struct: Trade::AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1D|ImageConverterFeature::ConvertCompressed1D; } + + Containers::Optional doConvert(const ImageView1D&) override { + return ImageData1D{PixelFormat::R8Unorm, {}, Containers::array({'B'})}; + }; + + Containers::Optional doConvert(const CompressedImageView1D&) override { + return ImageData1D{PixelFormat::R8Unorm, {}, Containers::array({'C'})}; + }; + } converter; + + { + /* Should get "B" when converting uncompressed */ + ImageData1D image{PixelFormat::RGBA8Unorm, {}, nullptr}; + Containers::Optional out = converter.convert(image); + CORRADE_VERIFY(out); + CORRADE_COMPARE_AS(out->data(), + Containers::arrayView({'B'}), + TestSuite::Compare::Container); + } { + /* Should get "C" when converting compressed */ + ImageData1D image{CompressedPixelFormat::Bc1RGBUnorm, {}, nullptr}; + Containers::Optional out = converter.convert(image); + CORRADE_VERIFY(out); + CORRADE_COMPARE_AS(out->data(), + Containers::arrayView({'C'}), + TestSuite::Compare::Container); + } +} + void AbstractImageConverterTest::convertImageData2D() { struct: Trade::AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2D|ImageConverterFeature::ConvertCompressed2D; } @@ -358,6 +706,50 @@ void AbstractImageConverterTest::convertImageData2D() { } } +void AbstractImageConverterTest::convertImageData3D() { + struct: Trade::AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3D|ImageConverterFeature::ConvertCompressed3D; } + + Containers::Optional doConvert(const ImageView3D&) override { + return ImageData3D{PixelFormat::R8Unorm, {}, Containers::array({'B'})}; + }; + + Containers::Optional doConvert(const CompressedImageView3D&) override { + return ImageData3D{PixelFormat::R8Unorm, {}, Containers::array({'C'})}; + }; + } converter; + + { + /* Should get "B" when converting uncompressed */ + ImageData3D image{PixelFormat::RGBA8Unorm, {}, nullptr}; + Containers::Optional out = converter.convert(image); + CORRADE_VERIFY(out); + CORRADE_COMPARE_AS(out->data(), + Containers::arrayView({'B'}), + TestSuite::Compare::Container); + } { + /* Should get "C" when converting compressed */ + ImageData3D image{CompressedPixelFormat::Bc1RGBUnorm, {}, nullptr}; + Containers::Optional out = converter.convert(image); + CORRADE_VERIFY(out); + CORRADE_COMPARE_AS(out->data(), + Containers::arrayView({'C'}), + TestSuite::Compare::Container); + } +} + +void AbstractImageConverterTest::convert1DToData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToData; } + Containers::Array doConvertToData(const ImageView1D& image) override { + return Containers::Array{nullptr, std::size_t(image.size().product())}; + } + } converter; + + Containers::Array actual = converter.convertToData(ImageView1D{PixelFormat::RGBA8Unorm, 4, Containers::ArrayView{nullptr, 96}}); + CORRADE_COMPARE(actual.size(), 4); +} + void AbstractImageConverterTest::convert2DToData() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } @@ -370,6 +762,33 @@ void AbstractImageConverterTest::convert2DToData() { CORRADE_COMPARE(actual.size(), 24); } +void AbstractImageConverterTest::convert3DToData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToData; } + Containers::Array doConvertToData(const ImageView3D& image) override { + return Containers::Array{nullptr, std::size_t(image.size().product())}; + } + } converter; + + Containers::Array actual = converter.convertToData(ImageView3D{PixelFormat::RGBA8Unorm, {4, 6, 2}, Containers::ArrayView{nullptr, 96}}); + CORRADE_COMPARE(actual.size(), 48); +} + +void AbstractImageConverterTest::convert1DToDataNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToData; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(ImageView1D{PixelFormat::RGBA8Unorm, 4, Containers::ArrayView{nullptr, 96}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): 1D image conversion advertised but not implemented\n"); +} + void AbstractImageConverterTest::convert2DToDataNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); @@ -385,85 +804,264 @@ void AbstractImageConverterTest::convert2DToDataNotImplemented() { CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): 2D image conversion advertised but not implemented\n"); } -void AbstractImageConverterTest::convert2DToDataCustomDeleter() { +void AbstractImageConverterTest::convert3DToDataNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } - Containers::Array doConvertToData(const ImageView2D&) override { - return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; - } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToData; } } converter; std::ostringstream out; Error redirectError{&out}; - converter.convertToData(ImageView2D{PixelFormat::RGBA8Unorm, {}}); - CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); + converter.convertToData(ImageView3D{PixelFormat::RGBA8Unorm, {4, 6, 1}, Containers::ArrayView{nullptr, 96}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): 3D image conversion advertised but not implemented\n"); } -void AbstractImageConverterTest::convertCompressed2DToData() { +void AbstractImageConverterTest::convert1DToDataCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } - Containers::Array doConvertToData(const CompressedImageView2D& image) override { - return Containers::Array{nullptr, std::size_t(image.size().product())}; + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToData; } + Containers::Array doConvertToData(const ImageView1D&) override { + return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; } } converter; - Containers::Array actual = converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); - CORRADE_COMPARE(actual.size(), 128); + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(ImageView1D{PixelFormat::RGBA8Unorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); } -void AbstractImageConverterTest::convertCompressed2DToDataNotImplemented() { +void AbstractImageConverterTest::convert2DToDataCustomDeleter() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } + Containers::Array doConvertToData(const ImageView2D&) override { + return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; + } } converter; std::ostringstream out; Error redirectError{&out}; - converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); - CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): compressed 2D image conversion advertised but not implemented\n"); + converter.convertToData(ImageView2D{PixelFormat::RGBA8Unorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); } -void AbstractImageConverterTest::convertCompressed2DToDataCustomDeleter() { +void AbstractImageConverterTest::convert3DToDataCustomDeleter() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } - Containers::Array doConvertToData(const CompressedImageView2D&) override { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToData; } + Containers::Array doConvertToData(const ImageView3D&) override { return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; } } converter; std::ostringstream out; Error redirectError{&out}; - converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {}}); + converter.convertToData(ImageView3D{PixelFormat::RGBA8Unorm, {}}); CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); } -/* Used by convertImageDataToData() and convertImageDataToFile() */ -class ImageData2DConverter: public Trade::AbstractImageConverter { - private: - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData|ImageConverterFeature::ConvertCompressed2DToData; } - - Containers::Array doConvertToData(const ImageView2D&) override { - return Containers::array({'B'}); - }; - - Containers::Array doConvertToData(const CompressedImageView2D&) override { - return Containers::array({'C'}); - }; -}; +void AbstractImageConverterTest::convertCompressed1DToData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToData; } + Containers::Array doConvertToData(const CompressedImageView1D& image) override { + return Containers::Array{nullptr, std::size_t(image.size().product())}; + } + } converter; -void AbstractImageConverterTest::convertImageData2DToData() { - ImageData2DConverter converter; + Containers::Array actual = converter.convertToData(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, Containers::ArrayView{nullptr, 64}}); + CORRADE_COMPARE(actual.size(), 16); +} + +void AbstractImageConverterTest::convertCompressed2DToData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } + Containers::Array doConvertToData(const CompressedImageView2D& image) override { + return Containers::Array{nullptr, std::size_t(image.size().product())}; + } + } converter; + + Containers::Array actual = converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); + CORRADE_COMPARE(actual.size(), 128); +} + +void AbstractImageConverterTest::convertCompressed3DToData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToData; } + Containers::Array doConvertToData(const CompressedImageView3D& image) override { + return Containers::Array{nullptr, std::size_t(image.size().product())}; + } + } converter; + + Containers::Array actual = converter.convertToData(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 2}, Containers::ArrayView{nullptr, 64}}); + CORRADE_COMPARE(actual.size(), 256); +} + +void AbstractImageConverterTest::convertCompressed1DToDataNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToData; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, Containers::ArrayView{nullptr, 64}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): compressed 1D image conversion advertised but not implemented\n"); +} + +void AbstractImageConverterTest::convertCompressed2DToDataNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): compressed 2D image conversion advertised but not implemented\n"); +} + +void AbstractImageConverterTest::convertCompressed3DToDataNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToData; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, Containers::ArrayView{nullptr, 64}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): compressed 3D image conversion advertised but not implemented\n"); +} + +void AbstractImageConverterTest::convertCompressed1DToDataCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToData; } + Containers::Array doConvertToData(const CompressedImageView1D&) override { + return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); +} + +void AbstractImageConverterTest::convertCompressed2DToDataCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } + Containers::Array doConvertToData(const CompressedImageView2D&) override { + return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); +} + +void AbstractImageConverterTest::convertCompressed3DToDataCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToData; } + Containers::Array doConvertToData(const CompressedImageView3D&) override { + return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); +} + +/* Used by convertImageDataToData() and convertImageDataToFile() */ +class ImageData1DConverter: public Trade::AbstractImageConverter { + private: + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToData|ImageConverterFeature::ConvertCompressed1DToData; } + + Containers::Array doConvertToData(const ImageView1D&) override { + return Containers::array({'B'}); + }; + + Containers::Array doConvertToData(const CompressedImageView1D&) override { + return Containers::array({'C'}); + }; +}; +class ImageData2DConverter: public Trade::AbstractImageConverter { + private: + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData|ImageConverterFeature::ConvertCompressed2DToData; } + + Containers::Array doConvertToData(const ImageView2D&) override { + return Containers::array({'B'}); + }; + + Containers::Array doConvertToData(const CompressedImageView2D&) override { + return Containers::array({'C'}); + }; +}; +class ImageData3DConverter: public Trade::AbstractImageConverter { + private: + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToData|ImageConverterFeature::ConvertCompressed3DToData; } + + Containers::Array doConvertToData(const ImageView3D&) override { + return Containers::array({'B'}); + }; + + Containers::Array doConvertToData(const CompressedImageView3D&) override { + return Containers::array({'C'}); + }; +}; + +void AbstractImageConverterTest::convertImageData1DToData() { + ImageData1DConverter converter; + + /* Should get "B" when converting uncompressed */ + CORRADE_COMPARE_AS(converter.convertToData(ImageData1D{PixelFormat::RGBA8Unorm, {}, nullptr}), + Containers::arrayView({'B'}), + TestSuite::Compare::Container); + + /* Should get "C" when converting compressed */ + CORRADE_COMPARE_AS(converter.convertToData(ImageData1D{CompressedPixelFormat::Bc1RGBUnorm, {}, nullptr}), + Containers::arrayView({'C'}), + TestSuite::Compare::Container); +} + +void AbstractImageConverterTest::convertImageData2DToData() { + ImageData2DConverter converter; /* Should get "B" when converting uncompressed */ CORRADE_COMPARE_AS(converter.convertToData(ImageData2D{PixelFormat::RGBA8Unorm, {}, nullptr}), @@ -476,6 +1074,40 @@ void AbstractImageConverterTest::convertImageData2DToData() { TestSuite::Compare::Container); } +void AbstractImageConverterTest::convertImageData3DToData() { + ImageData3DConverter converter; + + /* Should get "B" when converting uncompressed */ + CORRADE_COMPARE_AS(converter.convertToData(ImageData3D{PixelFormat::RGBA8Unorm, {}, nullptr}), + Containers::arrayView({'B'}), + TestSuite::Compare::Container); + + /* Should get "C" when converting compressed */ + CORRADE_COMPARE_AS(converter.convertToData(ImageData3D{CompressedPixelFormat::Bc1RGBUnorm, {}, nullptr}), + Containers::arrayView({'C'}), + TestSuite::Compare::Container); +} + +void AbstractImageConverterTest::convert1DToFile() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToFile; } + bool doConvertToFile(const ImageView1D& image, Containers::StringView filename) override { + return Utility::Directory::write(filename, Containers::arrayView( + {char(image.size()[0])})); + } + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + CORRADE_VERIFY(converter.convertToFile(ImageView1D{PixelFormat::RGBA8Unorm, 0xf0, {nullptr, 0xf0*4}}, filename)); + CORRADE_COMPARE_AS(filename, + "\xf0", TestSuite::Compare::FileToString); +} + void AbstractImageConverterTest::convert2DToFile() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToFile; } @@ -496,6 +1128,47 @@ void AbstractImageConverterTest::convert2DToFile() { "\xf0\x0d", TestSuite::Compare::FileToString); } +void AbstractImageConverterTest::convert3DToFile() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToFile; } + bool doConvertToFile(const ImageView3D& image, Containers::StringView filename) override { + return Utility::Directory::write(filename, Containers::arrayView( + {char(image.size().x()), char(image.size().y()), char(image.size().z())})); + } + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + CORRADE_VERIFY(converter.convertToFile(ImageView3D{PixelFormat::RGBA8Unorm, {0xf0, 0x0d, 0x1e}, {nullptr, 0xf0*0x0d*0x1e*4}}, filename)); + CORRADE_COMPARE_AS(filename, + "\xf0\x0d\x1e", TestSuite::Compare::FileToString); +} + +void AbstractImageConverterTest::convert1DToFileThroughData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToData; } + + Containers::Array doConvertToData(const ImageView1D& image) override { + return Containers::array({char(image.size()[0])}); + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* doConvertToFile() should call doConvertToData() */ + CORRADE_VERIFY(converter.convertToFile(ImageView1D(PixelFormat::RGBA8Unorm, 0xfe, {nullptr, 0xfe*4}), filename)); + CORRADE_COMPARE_AS(filename, + "\xfe", TestSuite::Compare::FileToString); +} + void AbstractImageConverterTest::convert2DToFileThroughData() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } @@ -517,6 +1190,51 @@ void AbstractImageConverterTest::convert2DToFileThroughData() { "\xfe\xed", TestSuite::Compare::FileToString); } +void AbstractImageConverterTest::convert3DToFileThroughData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToData; } + + Containers::Array doConvertToData(const ImageView3D& image) override { + return Containers::array({char(image.size().x()), char(image.size().y()), char(image.size().z())}); + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* doConvertToFile() should call doConvertToData() */ + CORRADE_VERIFY(converter.convertToFile(ImageView3D(PixelFormat::RGBA8Unorm, {0xfe, 0xed, 0xe9}, {nullptr, 0xfe*0xed*0xe9*4}), filename)); + CORRADE_COMPARE_AS(filename, + "\xfe\xed\xe9", TestSuite::Compare::FileToString); +} + +void AbstractImageConverterTest::convert1DToFileThroughDataFailed() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToData; } + + Containers::Array doConvertToData(const ImageView1D&) override { + return {}; + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* Function should fail, no file should get written and no error output + should be printed (the base implementation assumes the plugin does it) */ + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.convertToFile(ImageView1D(PixelFormat::RGBA8Unorm, 0xfe, {nullptr, 0xfe*4}), filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_COMPARE(out.str(), ""); +} + void AbstractImageConverterTest::convert2DToFileThroughDataFailed() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } @@ -541,6 +1259,47 @@ void AbstractImageConverterTest::convert2DToFileThroughDataFailed() { CORRADE_COMPARE(out.str(), ""); } +void AbstractImageConverterTest::convert3DToFileThroughDataFailed() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToData; } + + Containers::Array doConvertToData(const ImageView3D&) override { + return {}; + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* Function should fail, no file should get written and no error output + should be printed (the base implementation assumes the plugin does it) */ + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.convertToFile(ImageView3D(PixelFormat::RGBA8Unorm, {0xfe, 0xed, 0xe9}, {nullptr, 0xfe*0xed*0xe9*4}), filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_COMPARE(out.str(), ""); +} + +void AbstractImageConverterTest::convert1DToFileThroughDataNotWritable() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToData; } + + Containers::Array doConvertToData(const ImageView1D& image) override { + return Containers::array({char(image.size()[0])}); + }; + } converter; + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.convertToFile(ImageView1D{PixelFormat::RGBA8Unorm, 0xfe, {nullptr, 0xfe*4}}, "/some/path/that/does/not/exist")); + CORRADE_COMPARE(out.str(), + "Utility::Directory::write(): can't open /some/path/that/does/not/exist\n" + "Trade::AbstractImageConverter::convertToFile(): cannot write to file /some/path/that/does/not/exist\n"); +} + void AbstractImageConverterTest::convert2DToFileThroughDataNotWritable() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } @@ -558,6 +1317,38 @@ void AbstractImageConverterTest::convert2DToFileThroughDataNotWritable() { "Trade::AbstractImageConverter::convertToFile(): cannot write to file /some/path/that/does/not/exist\n"); } +void AbstractImageConverterTest::convert3DToFileThroughDataNotWritable() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToData; } + + Containers::Array doConvertToData(const ImageView3D& image) override { + return Containers::array({char(image.size().x()), char(image.size().y()), char(image.size().z())}); + }; + } converter; + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.convertToFile(ImageView3D{PixelFormat::RGBA8Unorm, {0xfe, 0xed, 0xe9}, {nullptr, 0xfe*0xed*0xe9*4}}, "/some/path/that/does/not/exist")); + CORRADE_COMPARE(out.str(), + "Utility::Directory::write(): can't open /some/path/that/does/not/exist\n" + "Trade::AbstractImageConverter::convertToFile(): cannot write to file /some/path/that/does/not/exist\n"); +} + +void AbstractImageConverterTest::convert1DToFileNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToFile; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToFile(ImageView1D{PixelFormat::RGBA8Unorm, 4, {nullptr, 96}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToFile(): 1D image conversion advertised but not implemented\n"); +} + void AbstractImageConverterTest::convert2DToFileNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); @@ -573,6 +1364,41 @@ void AbstractImageConverterTest::convert2DToFileNotImplemented() { CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToFile(): 2D image conversion advertised but not implemented\n"); } +void AbstractImageConverterTest::convert3DToFileNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToFile; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToFile(ImageView3D{PixelFormat::RGBA8Unorm, {4, 6, 1}, {nullptr, 96}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToFile(): 3D image conversion advertised but not implemented\n"); +} + +void AbstractImageConverterTest::convertCompressed1DToFile() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToFile; } + bool doConvertToFile(const CompressedImageView1D& image, Containers::StringView filename) override { + return Utility::Directory::write(filename, Containers::arrayView( + {char(image.size()[0])})); + } + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + CORRADE_VERIFY(converter.convertToFile(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 0xd0, {nullptr, 64}}, filename)); + CORRADE_COMPARE_AS(filename, + "\xd0", TestSuite::Compare::FileToString); +} + void AbstractImageConverterTest::convertCompressed2DToFile() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToFile; } @@ -593,6 +1419,47 @@ void AbstractImageConverterTest::convertCompressed2DToFile() { "\xd0\x0d", TestSuite::Compare::FileToString); } +void AbstractImageConverterTest::convertCompressed3DToFile() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToFile; } + bool doConvertToFile(const CompressedImageView3D& image, Containers::StringView filename) override { + return Utility::Directory::write(filename, Containers::arrayView( + {char(image.size().x()), char(image.size().y()), char(image.size().z())})); + } + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + CORRADE_VERIFY(converter.convertToFile(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {0xd0, 0x0d, 0x1e}, {nullptr, 64}}, filename)); + CORRADE_COMPARE_AS(filename, + "\xd0\x0d\x1e", TestSuite::Compare::FileToString); +} + +void AbstractImageConverterTest::convertCompressed1DToFileThroughData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToData; } + + Containers::Array doConvertToData(const CompressedImageView1D& image) override { + return Containers::array({char(image.size()[0])}); + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* doConvertToFile() should call doConvertToData() */ + CORRADE_VERIFY(converter.convertToFile(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 0xb0, {nullptr, 64}}, filename)); + CORRADE_COMPARE_AS(filename, + "\xb0", TestSuite::Compare::FileToString); +} + void AbstractImageConverterTest::convertCompressed2DToFileThroughData() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } @@ -614,6 +1481,51 @@ void AbstractImageConverterTest::convertCompressed2DToFileThroughData() { "\xb0\xd9", TestSuite::Compare::FileToString); } +void AbstractImageConverterTest::convertCompressed3DToFileThroughData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToData; } + + Containers::Array doConvertToData(const CompressedImageView3D& image) override { + return Containers::array({char(image.size().x()), char(image.size().y()), char(image.size().z())}); + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* doConvertToFile() should call doConvertToData() */ + CORRADE_VERIFY(converter.convertToFile(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {0xb0, 0xd1, 0xe5}, {nullptr, 64}}, filename)); + CORRADE_COMPARE_AS(filename, + "\xb0\xd1\xe5", TestSuite::Compare::FileToString); +} + +void AbstractImageConverterTest::convertCompressed1DToFileThroughDataFailed() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToData; } + + Containers::Array doConvertToData(const CompressedImageView1D&) override { + return {}; + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* Function should fail, no file should get written and no error output + should be printed (the base implementation assumes the plugin does it) */ + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.convertToFile(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 0xb0, {nullptr, 64}}, filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_COMPARE(out.str(), ""); +} + void AbstractImageConverterTest::convertCompressed2DToFileThroughDataFailed() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } @@ -638,6 +1550,47 @@ void AbstractImageConverterTest::convertCompressed2DToFileThroughDataFailed() { CORRADE_COMPARE(out.str(), ""); } +void AbstractImageConverterTest::convertCompressed3DToFileThroughDataFailed() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToData; } + + Containers::Array doConvertToData(const CompressedImageView3D&) override { + return {}; + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* Function should fail, no file should get written and no error output + should be printed (the base implementation assumes the plugin does it) */ + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.convertToFile(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {0xb0, 0xd1, 0xe5}, {nullptr, 64}}, filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_COMPARE(out.str(), ""); +} + +void AbstractImageConverterTest::convertCompressed1DToFileThroughDataNotWritable() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToData; } + + Containers::Array doConvertToData(const CompressedImageView1D& image) override { + return Containers::array({char(image.size()[0])}); + }; + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToFile(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, {nullptr, 64}}, "/some/path/that/does/not/exist"); + CORRADE_COMPARE(out.str(), + "Utility::Directory::write(): can't open /some/path/that/does/not/exist\n" + "Trade::AbstractImageConverter::convertToFile(): cannot write to file /some/path/that/does/not/exist\n"); +} + void AbstractImageConverterTest::convertCompressed2DToFileThroughDataNotWritable() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } @@ -655,6 +1608,38 @@ void AbstractImageConverterTest::convertCompressed2DToFileThroughDataNotWritable "Trade::AbstractImageConverter::convertToFile(): cannot write to file /some/path/that/does/not/exist\n"); } +void AbstractImageConverterTest::convertCompressed3DToFileThroughDataNotWritable() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToData; } + + Containers::Array doConvertToData(const CompressedImageView3D& image) override { + return Containers::array({char(image.size().x()), char(image.size().y()), char(image.size().z())}); + }; + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToFile(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, {nullptr, 64}}, "/some/path/that/does/not/exist"); + CORRADE_COMPARE(out.str(), + "Utility::Directory::write(): can't open /some/path/that/does/not/exist\n" + "Trade::AbstractImageConverter::convertToFile(): cannot write to file /some/path/that/does/not/exist\n"); +} + +void AbstractImageConverterTest::convertCompressed1DToFileNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToFile; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToFile(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, {nullptr, 64}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToFile(): compressed 1D image conversion advertised but not implemented\n"); +} + void AbstractImageConverterTest::convertCompressed2DToFileNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); @@ -670,6 +1655,35 @@ void AbstractImageConverterTest::convertCompressed2DToFileNotImplemented() { CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToFile(): compressed 2D image conversion advertised but not implemented\n"); } +void AbstractImageConverterTest::convertCompressed3DToFileNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToFile; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToFile(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, {nullptr, 64}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToFile(): compressed 3D image conversion advertised but not implemented\n"); +} + +void AbstractImageConverterTest::convertImageData1DToFile() { + ImageData1DConverter converter; + + /* Should get "B" when converting uncompressed */ + CORRADE_VERIFY(converter.convertToFile(ImageData1D{PixelFormat::RGBA16F, {}, nullptr}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); + CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), + "B", TestSuite::Compare::FileToString); + + /* Should get "C" when converting compressed */ + CORRADE_VERIFY(converter.convertToFile(ImageData1D{CompressedPixelFormat::Bc2RGBAUnorm, {}, nullptr}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); + CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), + "C", TestSuite::Compare::FileToString); +} + void AbstractImageConverterTest::convertImageData2DToFile() { ImageData2DConverter converter; @@ -684,6 +1698,20 @@ void AbstractImageConverterTest::convertImageData2DToFile() { "C", TestSuite::Compare::FileToString); } +void AbstractImageConverterTest::convertImageData3DToFile() { + ImageData3DConverter converter; + + /* Should get "B" when converting uncompressed */ + CORRADE_VERIFY(converter.convertToFile(ImageData3D{PixelFormat::RGBA16F, {}, nullptr}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); + CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), + "B", TestSuite::Compare::FileToString); + + /* Should get "C" when converting compressed */ + CORRADE_VERIFY(converter.convertToFile(ImageData3D{CompressedPixelFormat::Bc2RGBAUnorm, {}, nullptr}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); + CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), + "C", TestSuite::Compare::FileToString); +} + void AbstractImageConverterTest::debugFeature() { std::ostringstream out;