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
when the implementation only neeeds to do a format detection based on file
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 ASTC and WebP files and data in
@relativeref{Trade,AnyImageImporter}

36
src/Magnum/Trade/AbstractImageConverter.cpp

@ -57,7 +57,7 @@ using namespace Containers::Literals;
Containers::StringView AbstractImageConverter::pluginInterface() {
return
/* [interface] */
"cz.mosra.magnum.Trade.AbstractImageConverter/0.3.2"_s
"cz.mosra.magnum.Trade.AbstractImageConverter/0.3.3"_s
/* [interface] */
;
}
@ -106,6 +106,40 @@ void AbstractImageConverter::clearFlags(ImageConverterFlags 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) {
CORRADE_ASSERT(features() & ImageConverterFeature::Convert1D,
"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
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
@ref ImageConverterFeature::Convert2D is supported; equivalently for the
1D and 3D case.
@ -724,6 +728,38 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
*/
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
* @m_since_latest
@ -1777,6 +1813,22 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
*/
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&)
* @m_since_latest

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

@ -56,6 +56,10 @@ struct AbstractImageConverterTest: TestSuite::Tester {
void thingNotSupported();
void extensionMimeType();
void extensionMimeTypeNotImplemented();
void extensionMimeTypeCustomDeleter();
void convert1D();
void convert2D();
void convert3D();
@ -307,6 +311,10 @@ AbstractImageConverterTest::AbstractImageConverterTest() {
&AbstractImageConverterTest::thingNotSupported,
&AbstractImageConverterTest::extensionMimeType,
&AbstractImageConverterTest::extensionMimeTypeNotImplemented,
&AbstractImageConverterTest::extensionMimeTypeCustomDeleter,
&AbstractImageConverterTest::convert1D,
&AbstractImageConverterTest::convert2D,
&AbstractImageConverterTest::convert3D,
@ -599,6 +607,8 @@ void AbstractImageConverterTest::thingNotSupported() {
std::ostringstream out;
Error redirectError{&out};
converter.extension();
converter.mimeType();
converter.convert(ImageView1D{PixelFormat::R8Unorm, 0, nullptr});
converter.convert(ImageView2D{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({CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {}, nullptr}}, Utility::Path::join(TRADE_TEST_OUTPUT_DIR, "image.out"));
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(): 2D 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");
}
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() {
struct: AbstractImageConverter {
ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1D; }

Loading…
Cancel
Save