Browse Source

Trade: add AbstractImageConverter::extension() and mimeType().

pull/565/merge
Vladimír Vondruš 4 years ago
parent
commit
3892ddc4dc
  1. 4
      doc/changelog.dox
  2. 36
      src/Magnum/Trade/AbstractImageConverter.cpp
  3. 52
      src/Magnum/Trade/AbstractImageConverter.h
  4. 60
      src/Magnum/Trade/Test/AbstractImageConverterTest.cpp

4
doc/changelog.dox

@ -527,6 +527,10 @@ See also:
@relativeref{Trade::AbstractImageConverter,doConvertToData()}, for example @relativeref{Trade::AbstractImageConverter,doConvertToData()}, for example
when the implementation only neeeds to do a format detection based on file when the implementation only neeeds to do a format detection based on file
extension extension
- New @ref Trade::AbstractImageConverter::extension() and
@relativeref{Trade::AbstractImageConverter,mimeType()} interfaces to get
a file extension and MIME type corresponding to a file format produced by
a particular plugin.
- Recognizing BMP and TIFF file header magic in @relativeref{Trade,AnyImageImporter} - Recognizing BMP and TIFF file header magic in @relativeref{Trade,AnyImageImporter}
- Recognizing ASTC and WebP files and data in - Recognizing ASTC and WebP files and data in
@relativeref{Trade,AnyImageImporter} @relativeref{Trade,AnyImageImporter}

36
src/Magnum/Trade/AbstractImageConverter.cpp

@ -57,7 +57,7 @@ using namespace Containers::Literals;
Containers::StringView AbstractImageConverter::pluginInterface() { Containers::StringView AbstractImageConverter::pluginInterface() {
return return
/* [interface] */ /* [interface] */
"cz.mosra.magnum.Trade.AbstractImageConverter/0.3.2"_s "cz.mosra.magnum.Trade.AbstractImageConverter/0.3.3"_s
/* [interface] */ /* [interface] */
; ;
} }
@ -106,6 +106,40 @@ void AbstractImageConverter::clearFlags(ImageConverterFlags flags) {
setFlags(_flags & ~flags); setFlags(_flags & ~flags);
} }
Containers::String AbstractImageConverter::extension() const {
CORRADE_ASSERT(features() & (ImageConverterFeature::Convert1DToFile|
ImageConverterFeature::Convert2DToFile|
ImageConverterFeature::Convert3DToFile|
ImageConverterFeature::ConvertCompressed1DToFile|
ImageConverterFeature::ConvertCompressed2DToFile|
ImageConverterFeature::ConvertCompressed3DToFile),
"Trade::AbstractImageConverter::extension(): file conversion not supported", {});
Containers::String out = doExtension();
CORRADE_ASSERT(out.isSmall() || !out.deleter(),
"Trade::AbstractImageConverter::extension(): implementation is not allowed to use a custom String deleter", {});
return out;
}
Containers::String AbstractImageConverter::doExtension() const { return {}; }
Containers::String AbstractImageConverter::mimeType() const {
CORRADE_ASSERT(features() & (ImageConverterFeature::Convert1DToFile|
ImageConverterFeature::Convert2DToFile|
ImageConverterFeature::Convert3DToFile|
ImageConverterFeature::ConvertCompressed1DToFile|
ImageConverterFeature::ConvertCompressed2DToFile|
ImageConverterFeature::ConvertCompressed3DToFile),
"Trade::AbstractImageConverter::mimeType(): file conversion not supported", {});
Containers::String out = doMimeType();
CORRADE_ASSERT(out.isSmall() || !out.deleter(),
"Trade::AbstractImageConverter::mimeType(): implementation is not allowed to use a custom String deleter", {});
return out;
}
Containers::String AbstractImageConverter::doMimeType() const { return {}; }
Containers::Optional<ImageData1D> AbstractImageConverter::convert(const ImageView1D& image) { Containers::Optional<ImageData1D> AbstractImageConverter::convert(const ImageView1D& image) {
CORRADE_ASSERT(features() & ImageConverterFeature::Convert1D, CORRADE_ASSERT(features() & ImageConverterFeature::Convert1D,
"Trade::AbstractImageConverter::convert(): 1D image conversion not supported", {}); "Trade::AbstractImageConverter::convert(): 1D image conversion not supported", {});

52
src/Magnum/Trade/AbstractImageConverter.h

@ -572,6 +572,10 @@ based on what features are supported.
You don't need to do most of the redundant sanity checks, these things are You don't need to do most of the redundant sanity checks, these things are
checked by the implementation: checked by the implementation:
- The @ref doExtension() and @ref doMimeType() functions are called only
if @ref ImageConverterFeature::Convert2DToData "ImageConverterFeature::Convert*ToData"
or @ref ImageConverterFeature::Convert2DToFile "Convert*ToFile" is
supported
- The @ref doConvert(const ImageView2D&) function is called only if - The @ref doConvert(const ImageView2D&) function is called only if
@ref ImageConverterFeature::Convert2D is supported; equivalently for the @ref ImageConverterFeature::Convert2D is supported; equivalently for the
1D and 3D case. 1D and 3D case.
@ -724,6 +728,38 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
*/ */
void clearFlags(ImageConverterFlags flags); void clearFlags(ImageConverterFlags flags);
/**
* @brief File extension
* @m_since_latest
*
* Available only if @ref ImageConverterFeature::Convert2DToFile "ImageConverterFeature::Convert*ToFile"
* or @ref ImageConverterFeature::Convert2DToData "ImageConverterFeature::Convert*ToData"
* is supported. Returns a standardized file extension corresponding
* to the file format used, such as @cpp "png" @ce for PNG files. If
* the file format doesn't have a standardized extension, empty string
* is returned.
*
* The returned value may depend on flags or configuration options and
* can change during plugin lifetime.
*/
Containers::String extension() const;
/**
* @brief File MIME type
* @m_since_latest
*
* Available only if @ref ImageConverterFeature::Convert2DToFile "ImageConverterFeature::Convert*ToFile"
* or @ref ImageConverterFeature::Convert2DToData "ImageConverterFeature::Convert*ToData"
* is supported. Returns a standardized [MIME type](https://en.wikipedia.org/wiki/Media_type)
* corresponding to the file format used, such as @cpp "image/png" @ce
* for PNG files. If the file format doesn't have a standardized MIME
* type, empty string is returned.
*
* The returned value may depend on flags or configuration options and
* can change during plugin lifetime.
*/
Containers::String mimeType() const;
/** /**
* @brief Convert a 1D image * @brief Convert a 1D image
* @m_since_latest * @m_since_latest
@ -1777,6 +1813,22 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
*/ */
virtual void doSetFlags(ImageConverterFlags flags); virtual void doSetFlags(ImageConverterFlags flags);
/**
* @brief Implementation for @ref extension()
* @m_since_latest
*
* Default implementation returns an empty string.
*/
virtual Containers::String doExtension() const;
/**
* @brief Implementation for @ref mimeType()
* @m_since_latest
*
* Default implementation returns an empty string.
*/
virtual Containers::String doMimeType() const;
/** /**
* @brief Implementation for @ref convert(const ImageView1D&) * @brief Implementation for @ref convert(const ImageView1D&)
* @m_since_latest * @m_since_latest

60
src/Magnum/Trade/Test/AbstractImageConverterTest.cpp

@ -56,6 +56,10 @@ struct AbstractImageConverterTest: TestSuite::Tester {
void thingNotSupported(); void thingNotSupported();
void extensionMimeType();
void extensionMimeTypeNotImplemented();
void extensionMimeTypeCustomDeleter();
void convert1D(); void convert1D();
void convert2D(); void convert2D();
void convert3D(); void convert3D();
@ -307,6 +311,10 @@ AbstractImageConverterTest::AbstractImageConverterTest() {
&AbstractImageConverterTest::thingNotSupported, &AbstractImageConverterTest::thingNotSupported,
&AbstractImageConverterTest::extensionMimeType,
&AbstractImageConverterTest::extensionMimeTypeNotImplemented,
&AbstractImageConverterTest::extensionMimeTypeCustomDeleter,
&AbstractImageConverterTest::convert1D, &AbstractImageConverterTest::convert1D,
&AbstractImageConverterTest::convert2D, &AbstractImageConverterTest::convert2D,
&AbstractImageConverterTest::convert3D, &AbstractImageConverterTest::convert3D,
@ -599,6 +607,8 @@ void AbstractImageConverterTest::thingNotSupported() {
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
converter.extension();
converter.mimeType();
converter.convert(ImageView1D{PixelFormat::R8Unorm, 0, nullptr}); converter.convert(ImageView1D{PixelFormat::R8Unorm, 0, nullptr});
converter.convert(ImageView2D{PixelFormat::R8Unorm, {}, nullptr}); converter.convert(ImageView2D{PixelFormat::R8Unorm, {}, nullptr});
converter.convert(ImageView3D{PixelFormat::R8Unorm, {}, nullptr}); converter.convert(ImageView3D{PixelFormat::R8Unorm, {}, nullptr});
@ -630,6 +640,8 @@ void AbstractImageConverterTest::thingNotSupported() {
converter.convertToFile({CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {}, nullptr}}, Utility::Path::join(TRADE_TEST_OUTPUT_DIR, "image.out")); converter.convertToFile({CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {}, nullptr}}, Utility::Path::join(TRADE_TEST_OUTPUT_DIR, "image.out"));
converter.convertToFile({CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {}, nullptr}}, Utility::Path::join(TRADE_TEST_OUTPUT_DIR, "image.out")); converter.convertToFile({CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {}, nullptr}}, Utility::Path::join(TRADE_TEST_OUTPUT_DIR, "image.out"));
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"Trade::AbstractImageConverter::extension(): file conversion not supported\n"
"Trade::AbstractImageConverter::mimeType(): file conversion not supported\n"
"Trade::AbstractImageConverter::convert(): 1D image conversion not supported\n" "Trade::AbstractImageConverter::convert(): 1D image conversion not supported\n"
"Trade::AbstractImageConverter::convert(): 2D 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(): 3D image conversion not supported\n"
@ -662,6 +674,54 @@ void AbstractImageConverterTest::thingNotSupported() {
"Trade::AbstractImageConverter::convertToFile(): multi-level compressed 3D image conversion not supported\n"); "Trade::AbstractImageConverter::convertToFile(): multi-level compressed 3D image conversion not supported\n");
} }
void AbstractImageConverterTest::extensionMimeType() {
struct: AbstractImageConverter {
ImageConverterFeatures doFeatures() const override {
return ImageConverterFeature::ConvertCompressedLevels3DToData;
}
Containers::String doExtension() const override { return "yello"; }
Containers::String doMimeType() const override { return "yel/low"; }
} converter;
CORRADE_COMPARE(converter.extension(), "yello");
CORRADE_COMPARE(converter.mimeType(), "yel/low");
}
void AbstractImageConverterTest::extensionMimeTypeNotImplemented() {
struct: AbstractImageConverter {
ImageConverterFeatures doFeatures() const override {
return ImageConverterFeature::Convert1DToFile;
}
} converter;
CORRADE_COMPARE(converter.extension(), "");
CORRADE_COMPARE(converter.mimeType(), "");
}
void AbstractImageConverterTest::extensionMimeTypeCustomDeleter() {
CORRADE_SKIP_IF_NO_ASSERT();
struct: AbstractImageConverter {
ImageConverterFeatures doFeatures() const override {
return ImageConverterFeature::ConvertCompressed1DToData;
}
Containers::String doExtension() const override {
return Containers::String{"yello", 5, [](char*, std::size_t) {}};
}
Containers::String doMimeType() const override {
return Containers::String{"yel/low", 7, [](char*, std::size_t) {}};
}
} converter;
std::ostringstream out;
Error redirectError{&out};
converter.extension();
converter.mimeType();
CORRADE_COMPARE(out.str(),
"Trade::AbstractImageConverter::extension(): implementation is not allowed to use a custom String deleter\n"
"Trade::AbstractImageConverter::mimeType(): implementation is not allowed to use a custom String deleter\n");
}
void AbstractImageConverterTest::convert1D() { void AbstractImageConverterTest::convert1D() {
struct: AbstractImageConverter { struct: AbstractImageConverter {
ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1D; } ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1D; }

Loading…
Cancel
Save