Browse Source

Trade: tighten AbstractImageConverter input requirements.

The multi-level APIs still don't check anything regarding level sizes
and order since for example *.ico has no restrictions at all. But the
rest (like non-zero size) is a restriction for all file formats I'm
aware of.

TgaImageConverter test had to be adapted, I expect a lot of breakages in
plugins tests as well. But user code should be fine I think. Also
reduced the rather excessive dimensions in AbstractImageConverterTest,
since the allocation requirement now made the default Emscripten heap
OOM.
pull/537/head
Vladimír Vondruš 5 years ago
parent
commit
eea9d32959
  1. 5
      doc/changelog.dox
  2. 248
      src/Magnum/Trade/AbstractImageConverter.cpp
  3. 182
      src/Magnum/Trade/AbstractImageConverter.h
  4. 1043
      src/Magnum/Trade/Test/AbstractImageConverterTest.cpp
  5. 8
      src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp

5
doc/changelog.dox

@ -733,6 +733,11 @@ See also:
interfaces, which are also @cpp const @ce and can't fail. Documentation of interfaces, which are also @cpp const @ce and can't fail. Documentation of
each function was expanded to suggest a recommended place for potential each function was expanded to suggest a recommended place for potential
error handling. error handling.
- @ref Trade::AbstractImageConverter::convertToData() and
@relativeref{Trade::AbstractImageConverter,convertToFile()} now expect
image views to not be @cpp nullptr @ce and to have a non-zero size in all
dimensions. This used to fail for all existing plugin implementations
anyway, but now it's treated as a programmer error and thus asserted on.
- @ref Trade::TextureData constructor was not @cpp explicit @ce by mistake, - @ref Trade::TextureData constructor was not @cpp explicit @ce by mistake,
now it is now it is
- @ref Trade::TextureData::image() used to document that cube map images are - @ref Trade::TextureData::image() used to document that cube map images are

248
src/Magnum/Trade/AbstractImageConverter.cpp

@ -36,6 +36,7 @@
#include "Magnum/Image.h" #include "Magnum/Image.h"
#include "Magnum/ImageView.h" #include "Magnum/ImageView.h"
#include "Magnum/PixelFormat.h"
#include "Magnum/Trade/ImageData.h" #include "Magnum/Trade/ImageData.h"
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
@ -99,6 +100,24 @@ Containers::Optional<ImageData1D> AbstractImageConverter::convert(const ImageVie
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", {});
/* Unlike with convertToData() / convertToFile(), where images are checked
for having a non-zero size and being non-null, here it's explicitly
allowed:
- Usual format conversions / resamplings are a loop that "just works"
with zero-sized dimensions.
- Nullptr views could be potentially useful for converters that fill
an image of desired format and size with data, such as generating a
noise image or some test pattern. While it could be implemented as
an importer plugin as well, the size/format would have to be passed
manually through plugin-specific configuration there, which is
rather annoying compared to having an API prepared directly for
that.
Plugin implementations that can't work with these have to do this check
themselves, and since that's then a plugin-specific behavior, it should
be a runtime error, not an assert. */
Containers::Optional<ImageData1D> out = doConvert(image); Containers::Optional<ImageData1D> out = doConvert(image);
CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -112,6 +131,9 @@ Containers::Optional<ImageData2D> AbstractImageConverter::convert(const ImageVie
CORRADE_ASSERT(features() & ImageConverterFeature::Convert2D, CORRADE_ASSERT(features() & ImageConverterFeature::Convert2D,
"Trade::AbstractImageConverter::convert(): 2D image conversion not supported", {}); "Trade::AbstractImageConverter::convert(): 2D image conversion not supported", {});
/* No zero size / nullptr checks here, see convert(const ImageView1D&) for
reasons why */
Containers::Optional<ImageData2D> out = doConvert(image); Containers::Optional<ImageData2D> out = doConvert(image);
CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -157,6 +179,9 @@ Containers::Optional<ImageData3D> AbstractImageConverter::convert(const ImageVie
CORRADE_ASSERT(features() & ImageConverterFeature::Convert3D, CORRADE_ASSERT(features() & ImageConverterFeature::Convert3D,
"Trade::AbstractImageConverter::convert(): 3D image conversion not supported", {}); "Trade::AbstractImageConverter::convert(): 3D image conversion not supported", {});
/* No zero size / nullptr checks here, see convert(const ImageView1D&) for
reasons why */
Containers::Optional<ImageData3D> out = doConvert(image); Containers::Optional<ImageData3D> out = doConvert(image);
CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -170,6 +195,9 @@ Containers::Optional<ImageData1D> AbstractImageConverter::convert(const Compress
CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed1D, CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed1D,
"Trade::AbstractImageConverter::convert(): compressed 1D image conversion not supported", {}); "Trade::AbstractImageConverter::convert(): compressed 1D image conversion not supported", {});
/* No zero size / nullptr checks here, see convert(const ImageView1D&) for
reasons why */
Containers::Optional<ImageData1D> out = doConvert(image); Containers::Optional<ImageData1D> out = doConvert(image);
CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -183,6 +211,9 @@ Containers::Optional<ImageData2D> AbstractImageConverter::convert(const Compress
CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed2D, CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed2D,
"Trade::AbstractImageConverter::convert(): compressed 2D image conversion not supported", {}); "Trade::AbstractImageConverter::convert(): compressed 2D image conversion not supported", {});
/* No zero size / nullptr checks here, see convert(const ImageView1D&) for
reasons why */
Containers::Optional<ImageData2D> out = doConvert(image); Containers::Optional<ImageData2D> out = doConvert(image);
CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -196,6 +227,9 @@ Containers::Optional<ImageData3D> AbstractImageConverter::convert(const Compress
CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed3D, CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed3D,
"Trade::AbstractImageConverter::convert(): compressed 3D image conversion not supported", {}); "Trade::AbstractImageConverter::convert(): compressed 3D image conversion not supported", {});
/* No zero size / nullptr checks here, see convert(const ImageView1D&) for
reasons why */
Containers::Optional<ImageData3D> out = doConvert(image); Containers::Optional<ImageData3D> out = doConvert(image);
CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -217,10 +251,37 @@ Containers::Optional<ImageData3D> AbstractImageConverter::convert(const ImageDat
return image.isCompressed() ? convert(CompressedImageView3D(image)) : convert(ImageView3D(image)); return image.isCompressed() ? convert(CompressedImageView3D(image)) : convert(ImageView3D(image));
} }
#ifndef CORRADE_NO_ASSERT
namespace {
template<UnsignedInt dimensions, template<UnsignedInt, class> class View> bool checkImageValidity(const char* const messagePrefix, const View<dimensions, const char>& image) {
/* At some point there might be a file format that allows zero-sized
images, but so far I don't know about any. When such format appears,
this check will get moved to plugin implementations that can't work with
zero-sized images.
Also note that this check isn't done for the Image->Image conversion
above, there zero-sized images and nullptr *could* make sense. */
CORRADE_ASSERT(image.size().product(),
messagePrefix << "can't convert image with a zero size:" << image.size(), false);
CORRADE_ASSERT(image.data(),
messagePrefix << "can't convert image with a nullptr view", false);
return true;
}
}
#endif
Containers::Array<char> AbstractImageConverter::convertToData(const ImageView1D& image) { Containers::Array<char> AbstractImageConverter::convertToData(const ImageView1D& image) {
CORRADE_ASSERT(features() >= ImageConverterFeature::Convert1DToData, CORRADE_ASSERT(features() >= ImageConverterFeature::Convert1DToData,
"Trade::AbstractImageConverter::convertToData(): 1D image conversion not supported", nullptr); "Trade::AbstractImageConverter::convertToData(): 1D image conversion not supported", nullptr);
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToData():", image))
return {};
#endif
Containers::Array<char> out = doConvertToData(image); Containers::Array<char> out = doConvertToData(image);
CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -237,6 +298,12 @@ Containers::Array<char> AbstractImageConverter::convertToData(const ImageView2D&
CORRADE_ASSERT(features() >= ImageConverterFeature::Convert2DToData, CORRADE_ASSERT(features() >= ImageConverterFeature::Convert2DToData,
"Trade::AbstractImageConverter::convertToData(): 2D image conversion not supported", nullptr); "Trade::AbstractImageConverter::convertToData(): 2D image conversion not supported", nullptr);
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToData():", image))
return {};
#endif
Containers::Array<char> out = doConvertToData(image); Containers::Array<char> out = doConvertToData(image);
CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -259,6 +326,12 @@ Containers::Array<char> AbstractImageConverter::convertToData(const ImageView3D&
CORRADE_ASSERT(features() >= ImageConverterFeature::Convert3DToData, CORRADE_ASSERT(features() >= ImageConverterFeature::Convert3DToData,
"Trade::AbstractImageConverter::convertToData(): 3D image conversion not supported", nullptr); "Trade::AbstractImageConverter::convertToData(): 3D image conversion not supported", nullptr);
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToData():", image))
return {};
#endif
Containers::Array<char> out = doConvertToData(image); Containers::Array<char> out = doConvertToData(image);
CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -275,6 +348,12 @@ Containers::Array<char> AbstractImageConverter::convertToData(const CompressedIm
CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed1DToData, CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed1DToData,
"Trade::AbstractImageConverter::convertToData(): compressed 1D image conversion not supported", nullptr); "Trade::AbstractImageConverter::convertToData(): compressed 1D image conversion not supported", nullptr);
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToData():", image))
return {};
#endif
Containers::Array<char> out = doConvertToData(image); Containers::Array<char> out = doConvertToData(image);
CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -291,6 +370,12 @@ Containers::Array<char> AbstractImageConverter::convertToData(const CompressedIm
CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed2DToData, CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed2DToData,
"Trade::AbstractImageConverter::convertToData(): compressed 2D image conversion not supported", nullptr); "Trade::AbstractImageConverter::convertToData(): compressed 2D image conversion not supported", nullptr);
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToData():", image))
return {};
#endif
Containers::Array<char> out = doConvertToData(image); Containers::Array<char> out = doConvertToData(image);
CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -313,6 +398,12 @@ Containers::Array<char> AbstractImageConverter::convertToData(const CompressedIm
CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed3DToData, CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed3DToData,
"Trade::AbstractImageConverter::convertToData(): compressed 3D image conversion not supported", nullptr); "Trade::AbstractImageConverter::convertToData(): compressed 3D image conversion not supported", nullptr);
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToData():", image))
return {};
#endif
Containers::Array<char> out = doConvertToData(image); Containers::Array<char> out = doConvertToData(image);
CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -343,10 +434,65 @@ Containers::Array<char> AbstractImageConverter::convertToData(const ImageData3D&
return image.isCompressed() ? convertToData(CompressedImageView3D(image)) : convertToData(ImageView3D(image)); return image.isCompressed() ? convertToData(CompressedImageView3D(image)) : convertToData(ImageView3D(image));
} }
#ifndef CORRADE_NO_ASSERT
namespace {
template<UnsignedInt dimensions> bool checkImageValidity(const char* const messagePrefix, const Containers::ArrayView<const BasicImageView<dimensions>> imageLevels) {
CORRADE_ASSERT(!imageLevels.empty(),
messagePrefix << "at least one image has to be specified", false);
const PixelFormat format = imageLevels[0].format();
const UnsignedInt formatExtra = imageLevels[0].formatExtra();
/* Going through *all* levels although the format assertion is never fired
in the first iteration in order to properly check also the first one for
zero size / nullptr. */
for(std::size_t i = 0; i != imageLevels.size(); ++i) {
CORRADE_ASSERT(imageLevels[i].size().product(),
messagePrefix << "can't convert image" << i << "with a zero size:" << imageLevels[i].size(), false);
CORRADE_ASSERT(imageLevels[i].data(),
messagePrefix << "can't convert image" << i << "with a nullptr view", false);
CORRADE_ASSERT(imageLevels[i].format() == format,
messagePrefix << "levels don't have the same format, expected" << format << "but got" << imageLevels[i].format() << "for image" << i, false);
CORRADE_ASSERT(imageLevels[i].formatExtra() == formatExtra,
messagePrefix << "levels don't have the same extra format field, expected" << formatExtra << "but got" << imageLevels[i].formatExtra() << "for image" << i, false);
}
return true;
}
template<UnsignedInt dimensions> bool checkImageValidity(const char* const messagePrefix, const Containers::ArrayView<const BasicCompressedImageView<dimensions>> imageLevels) {
CORRADE_ASSERT(!imageLevels.empty(),
messagePrefix << "at least one image has to be specified", false);
const CompressedPixelFormat format = imageLevels[0].format();
/* Going through *all* levels although the format assertion is never fired
in the first iteration in order to properly check also the first one for
zero size / nullptr. */
for(std::size_t i = 0; i != imageLevels.size(); ++i) {
CORRADE_ASSERT(imageLevels[i].size().product(),
messagePrefix << "can't convert image" << i << "with a zero size:" << imageLevels[i].size(), false);
CORRADE_ASSERT(imageLevels[i].data(),
messagePrefix << "can't convert image" << i << "with a nullptr view", false);
CORRADE_ASSERT(imageLevels[i].format() == format,
messagePrefix << "levels don't have the same format, expected" << format << "but got" << imageLevels[i].format() << "for image" << i, false);
}
return true;
}
}
#endif
Containers::Array<char> AbstractImageConverter::convertToData(const Containers::ArrayView<const ImageView1D> imageLevels) { Containers::Array<char> AbstractImageConverter::convertToData(const Containers::ArrayView<const ImageView1D> imageLevels) {
CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertLevels1DToData, CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertLevels1DToData,
"Trade::AbstractImageConverter::convertToData(): multi-level 1D image conversion not supported", nullptr); "Trade::AbstractImageConverter::convertToData(): multi-level 1D image conversion not supported", nullptr);
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToData():", imageLevels))
return {};
#endif
Containers::Array<char> out = doConvertToData(imageLevels); Containers::Array<char> out = doConvertToData(imageLevels);
CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -364,6 +510,12 @@ Containers::Array<char> AbstractImageConverter::convertToData(const Containers::
CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertLevels2DToData, CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertLevels2DToData,
"Trade::AbstractImageConverter::convertToData(): multi-level 2D image conversion not supported", nullptr); "Trade::AbstractImageConverter::convertToData(): multi-level 2D image conversion not supported", nullptr);
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToData():", imageLevels))
return {};
#endif
Containers::Array<char> out = doConvertToData(imageLevels); Containers::Array<char> out = doConvertToData(imageLevels);
CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -381,6 +533,12 @@ Containers::Array<char> AbstractImageConverter::convertToData(const Containers::
CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertLevels3DToData, CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertLevels3DToData,
"Trade::AbstractImageConverter::convertToData(): multi-level 3D image conversion not supported", nullptr); "Trade::AbstractImageConverter::convertToData(): multi-level 3D image conversion not supported", nullptr);
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToData():", imageLevels))
return {};
#endif
Containers::Array<char> out = doConvertToData(imageLevels); Containers::Array<char> out = doConvertToData(imageLevels);
CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -398,6 +556,12 @@ Containers::Array<char> AbstractImageConverter::convertToData(const Containers::
CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressedLevels1DToData, CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressedLevels1DToData,
"Trade::AbstractImageConverter::convertToData(): multi-level compressed 1D image conversion not supported", nullptr); "Trade::AbstractImageConverter::convertToData(): multi-level compressed 1D image conversion not supported", nullptr);
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToData():", imageLevels))
return {};
#endif
Containers::Array<char> out = doConvertToData(imageLevels); Containers::Array<char> out = doConvertToData(imageLevels);
CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -415,6 +579,12 @@ Containers::Array<char> AbstractImageConverter::convertToData(const Containers::
CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressedLevels2DToData, CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressedLevels2DToData,
"Trade::AbstractImageConverter::convertToData(): multi-level compressed 2D image conversion not supported", nullptr); "Trade::AbstractImageConverter::convertToData(): multi-level compressed 2D image conversion not supported", nullptr);
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToData():", imageLevels))
return {};
#endif
Containers::Array<char> out = doConvertToData(imageLevels); Containers::Array<char> out = doConvertToData(imageLevels);
CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -432,6 +602,12 @@ Containers::Array<char> AbstractImageConverter::convertToData(const Containers::
CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressedLevels3DToData, CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressedLevels3DToData,
"Trade::AbstractImageConverter::convertToData(): multi-level compressed 3D image conversion not supported", nullptr); "Trade::AbstractImageConverter::convertToData(): multi-level compressed 3D image conversion not supported", nullptr);
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToData():", imageLevels))
return {};
#endif
Containers::Array<char> out = doConvertToData(imageLevels); Containers::Array<char> out = doConvertToData(imageLevels);
CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {});
return out; return out;
@ -449,6 +625,12 @@ bool AbstractImageConverter::convertToFile(const ImageView1D& image, const Conta
CORRADE_ASSERT(features() & ImageConverterFeature::Convert1DToFile, CORRADE_ASSERT(features() & ImageConverterFeature::Convert1DToFile,
"Trade::AbstractImageConverter::convertToFile(): 1D image conversion not supported", {}); "Trade::AbstractImageConverter::convertToFile(): 1D image conversion not supported", {});
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToFile():", image))
return {};
#endif
return doConvertToFile(image, filename); return doConvertToFile(image, filename);
} }
@ -477,6 +659,12 @@ bool AbstractImageConverter::convertToFile(const ImageView2D& image, const Conta
CORRADE_ASSERT(features() & ImageConverterFeature::Convert2DToFile, CORRADE_ASSERT(features() & ImageConverterFeature::Convert2DToFile,
"Trade::AbstractImageConverter::convertToFile(): 2D image conversion not supported", {}); "Trade::AbstractImageConverter::convertToFile(): 2D image conversion not supported", {});
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToFile():", image))
return {};
#endif
return doConvertToFile(image, filename); return doConvertToFile(image, filename);
} }
@ -511,6 +699,12 @@ bool AbstractImageConverter::convertToFile(const ImageView3D& image, const Conta
CORRADE_ASSERT(features() & ImageConverterFeature::Convert3DToFile, CORRADE_ASSERT(features() & ImageConverterFeature::Convert3DToFile,
"Trade::AbstractImageConverter::convertToFile(): 3D image conversion not supported", {}); "Trade::AbstractImageConverter::convertToFile(): 3D image conversion not supported", {});
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToFile():", image))
return {};
#endif
return doConvertToFile(image, filename); return doConvertToFile(image, filename);
} }
@ -539,6 +733,12 @@ bool AbstractImageConverter::convertToFile(const CompressedImageView1D& image, c
CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed1DToFile, CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed1DToFile,
"Trade::AbstractImageConverter::convertToFile(): compressed 1D image conversion not supported", {}); "Trade::AbstractImageConverter::convertToFile(): compressed 1D image conversion not supported", {});
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToFile():", image))
return {};
#endif
return doConvertToFile(image, filename); return doConvertToFile(image, filename);
} }
@ -567,6 +767,12 @@ bool AbstractImageConverter::convertToFile(const CompressedImageView2D& image, c
CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed2DToFile, CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed2DToFile,
"Trade::AbstractImageConverter::convertToFile(): compressed 2D image conversion not supported", {}); "Trade::AbstractImageConverter::convertToFile(): compressed 2D image conversion not supported", {});
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToFile():", image))
return {};
#endif
return doConvertToFile(image, filename); return doConvertToFile(image, filename);
} }
@ -601,6 +807,12 @@ bool AbstractImageConverter::convertToFile(const CompressedImageView3D& image, c
CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed3DToFile, CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed3DToFile,
"Trade::AbstractImageConverter::convertToFile(): compressed 3D image conversion not supported", {}); "Trade::AbstractImageConverter::convertToFile(): compressed 3D image conversion not supported", {});
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToFile():", image))
return {};
#endif
return doConvertToFile(image, filename); return doConvertToFile(image, filename);
} }
@ -647,6 +859,12 @@ bool AbstractImageConverter::convertToFile(const Containers::ArrayView<const Ima
CORRADE_ASSERT(features() & ImageConverterFeature::ConvertLevels1DToFile, CORRADE_ASSERT(features() & ImageConverterFeature::ConvertLevels1DToFile,
"Trade::AbstractImageConverter::convertToFile(): multi-level 1D image conversion not supported", {}); "Trade::AbstractImageConverter::convertToFile(): multi-level 1D image conversion not supported", {});
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToFile():", imageLevels))
return {};
#endif
return doConvertToFile(imageLevels, filename); return doConvertToFile(imageLevels, filename);
} }
@ -673,6 +891,12 @@ bool AbstractImageConverter::convertToFile(const Containers::ArrayView<const Ima
CORRADE_ASSERT(features() & ImageConverterFeature::ConvertLevels2DToFile, CORRADE_ASSERT(features() & ImageConverterFeature::ConvertLevels2DToFile,
"Trade::AbstractImageConverter::convertToFile(): multi-level 2D image conversion not supported", {}); "Trade::AbstractImageConverter::convertToFile(): multi-level 2D image conversion not supported", {});
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToFile():", imageLevels))
return {};
#endif
return doConvertToFile(imageLevels, filename); return doConvertToFile(imageLevels, filename);
} }
@ -699,6 +923,12 @@ bool AbstractImageConverter::convertToFile(const Containers::ArrayView<const Ima
CORRADE_ASSERT(features() & ImageConverterFeature::ConvertLevels3DToFile, CORRADE_ASSERT(features() & ImageConverterFeature::ConvertLevels3DToFile,
"Trade::AbstractImageConverter::convertToFile(): multi-level 3D image conversion not supported", {}); "Trade::AbstractImageConverter::convertToFile(): multi-level 3D image conversion not supported", {});
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToFile():", imageLevels))
return {};
#endif
return doConvertToFile(imageLevels, filename); return doConvertToFile(imageLevels, filename);
} }
@ -725,6 +955,12 @@ bool AbstractImageConverter::convertToFile(const Containers::ArrayView<const Com
CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressedLevels1DToFile, CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressedLevels1DToFile,
"Trade::AbstractImageConverter::convertToFile(): multi-level compressed 1D image conversion not supported", {}); "Trade::AbstractImageConverter::convertToFile(): multi-level compressed 1D image conversion not supported", {});
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToFile():", imageLevels))
return {};
#endif
return doConvertToFile(imageLevels, filename); return doConvertToFile(imageLevels, filename);
} }
@ -751,6 +987,12 @@ bool AbstractImageConverter::convertToFile(const Containers::ArrayView<const Com
CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressedLevels2DToFile, CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressedLevels2DToFile,
"Trade::AbstractImageConverter::convertToFile(): multi-level compressed 2D image conversion not supported", {}); "Trade::AbstractImageConverter::convertToFile(): multi-level compressed 2D image conversion not supported", {});
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToFile():", imageLevels))
return {};
#endif
return doConvertToFile(imageLevels, filename); return doConvertToFile(imageLevels, filename);
} }
@ -777,6 +1019,12 @@ bool AbstractImageConverter::convertToFile(const Containers::ArrayView<const Com
CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressedLevels3DToFile, CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressedLevels3DToFile,
"Trade::AbstractImageConverter::convertToFile(): multi-level compressed 3D image conversion not supported", {}); "Trade::AbstractImageConverter::convertToFile(): multi-level compressed 3D image conversion not supported", {});
#ifndef CORRADE_NO_ASSERT
/* Explicitly return if checks fail for CORRADE_GRACEFUL_ASSERT builds */
if(!checkImageValidity("Trade::AbstractImageConverter::convertToFile():", imageLevels))
return {};
#endif
return doConvertToFile(imageLevels, filename); return doConvertToFile(imageLevels, filename);
} }

182
src/Magnum/Trade/AbstractImageConverter.h

@ -565,6 +565,20 @@ checked by the implementation:
- The function @ref doConvertToFile(Containers::ArrayView<const CompressedImageView2D>, Containers::StringView) - The function @ref doConvertToFile(Containers::ArrayView<const CompressedImageView2D>, Containers::StringView)
is called only if @ref ImageConverterFeature::ConvertCompressedLevels2DToFile is called only if @ref ImageConverterFeature::ConvertCompressedLevels2DToFile
is supported and equivalently for the 1D and 3D case. is supported and equivalently for the 1D and 3D case.
- All @ref doConvertToData() and @ref doConvertToFile() functions taking a
single (compressed) image are called only if the image has a non-zero size
in all dimensions and the view is not @cpp nullptr @ce. Note that this does
not apply to @ref doConvert() --- there a zero-size image or a
@cpp nullptr @ce view may be a valid use case, and if the plugin
implementation doesn't work with any of those, it's expected to check that
on its own and produce a runtime error.
- All @ref doConvertToData() and @ref doConvertToFile() functions taking
multiple (compressed) images are called only the list has at least one
image, each of the images has a non-zero size, the views are not
@cpp nullptr @ce and additionally all views have the same pixel format.
Since file formats have varying requirements on image level sizes and their
order and some don't impose any requirements at all, the plugin
implementation is expected to check the sizes on its own.
@m_class{m-block m-warning} @m_class{m-block m-warning}
@ -826,8 +840,9 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::Convert1DToData or * Available only if @ref ImageConverterFeature::Convert1DToData or
* @ref ImageConverterFeature::ConvertLevels1DToData is supported. * @ref ImageConverterFeature::ConvertLevels1DToData is supported. The
* Returns data on success, @cpp nullptr @ce otherwise. * image view is expected to not be @cpp nullptr @ce and to have a
* non-zero size. Returns data on success, @cpp nullptr @ce otherwise.
* @see @ref features(), @ref convertToData(const CompressedImageView1D&), * @see @ref features(), @ref convertToData(const CompressedImageView1D&),
* @ref convertToData(const ImageData1D&), @ref convert(), * @ref convertToData(const ImageData1D&), @ref convert(),
* @ref convertToFile() * @ref convertToFile()
@ -839,8 +854,10 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::Convert2DToData or * Available only if @ref ImageConverterFeature::Convert2DToData or
* @ref ImageConverterFeature::ConvertLevels2DToData is supported. * @ref ImageConverterFeature::ConvertLevels2DToData is supported. The
* Returns data on success, @cpp nullptr @ce otherwise. * image view is expected to not be @cpp nullptr @ce and to have a
* non-zero size in all dimensions. Returns data on success,
* @cpp nullptr @ce otherwise.
* @see @ref features(), @ref convertToData(const CompressedImageView2D&), * @see @ref features(), @ref convertToData(const CompressedImageView2D&),
* @ref convertToData(const ImageData2D&), @ref convert(), * @ref convertToData(const ImageData2D&), @ref convert(),
* @ref convertToFile() * @ref convertToFile()
@ -861,8 +878,10 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::Convert3DToData or * Available only if @ref ImageConverterFeature::Convert3DToData or
* @ref ImageConverterFeature::ConvertLevels3DToData is supported. * @ref ImageConverterFeature::ConvertLevels3DToData is supported. The
* Returns data on success, @cpp nullptr @ce otherwise. * image view is expected to not be @cpp nullptr @ce and to have a
* non-zero size in all dimensions. Returns data on success,
* @cpp nullptr @ce otherwise.
* @see @ref features(), @ref convertToData(const CompressedImageView3D&), * @see @ref features(), @ref convertToData(const CompressedImageView3D&),
* @ref convertToData(const ImageData3D&), @ref convert(), * @ref convertToData(const ImageData3D&), @ref convert(),
* @ref convertToFile() * @ref convertToFile()
@ -875,7 +894,9 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* *
* Available only if @ref ImageConverterFeature::ConvertCompressed1DToData * Available only if @ref ImageConverterFeature::ConvertCompressed1DToData
* or @ref ImageConverterFeature::ConvertCompressedLevels1DToData is * or @ref ImageConverterFeature::ConvertCompressedLevels1DToData is
* supported. Returns data on success, @cpp nullptr @ce otherwise. * supported. The image view is expected to not be @cpp nullptr @ce and
* to have a non-zero size. Returns data on success, @cpp nullptr @ce
* otherwise.
* @see @ref features(), @ref convertToData(const ImageView1D&), * @see @ref features(), @ref convertToData(const ImageView1D&),
* @ref convertToData(const ImageData1D&), @ref convert(), * @ref convertToData(const ImageData1D&), @ref convert(),
* @ref convertToFile() * @ref convertToFile()
@ -888,7 +909,9 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* *
* Available only if @ref ImageConverterFeature::ConvertCompressed2DToData * Available only if @ref ImageConverterFeature::ConvertCompressed2DToData
* or @ref ImageConverterFeature::ConvertCompressedLevels2DToData is * or @ref ImageConverterFeature::ConvertCompressedLevels2DToData is
* supported. Returns data on success, @cpp nullptr @ce otherwise. * supported. The image view is expected to not be @cpp nullptr @ce and
* to have a non-zero size in all dimensions. Returns data on success,
* @cpp nullptr @ce otherwise.
* @see @ref features(), @ref convertToData(const ImageView2D&), * @see @ref features(), @ref convertToData(const ImageView2D&),
* @ref convertToData(const ImageData2D&), @ref convert(), * @ref convertToData(const ImageData2D&), @ref convert(),
* @ref convertToFile() * @ref convertToFile()
@ -910,7 +933,9 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* *
* Available only if @ref ImageConverterFeature::ConvertCompressed3DToData * Available only if @ref ImageConverterFeature::ConvertCompressed3DToData
* or @ref ImageConverterFeature::ConvertCompressedLevels3DToData is * or @ref ImageConverterFeature::ConvertCompressedLevels3DToData is
* supported. Returns data on success, @cpp nullptr @ce otherwise. * supported. The image view is expected to not be @cpp nullptr @ce and
* to have a non-zero size in all dimensions. Returns data on success,
* @cpp nullptr @ce otherwise.
* @see @ref features(), @ref convertToData(const ImageView3D&), * @see @ref features(), @ref convertToData(const ImageView3D&),
* @ref convertToData(const ImageData3D&), @ref convert(), * @ref convertToData(const ImageData3D&), @ref convert(),
* @ref convertToFile() * @ref convertToFile()
@ -967,7 +992,10 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::ConvertLevels1DToData * Available only if @ref ImageConverterFeature::ConvertLevels1DToData
* is supported. Note that certain converters may impose size and order * is supported. The function expects at least one image to be passed,
* with each view expected to not be @cpp nullptr @ce, to have a
* non-zero size, and all of them sharing the same pixel format. Note
* that certain converters may impose additional size and order
* restrictions on the images, see documentation of a particular plugin * restrictions on the images, see documentation of a particular plugin
* for more information. Returns data on success, @cpp nullptr @ce * for more information. Returns data on success, @cpp nullptr @ce
* otherwise. * otherwise.
@ -983,10 +1011,13 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::ConvertLevels2DToData * Available only if @ref ImageConverterFeature::ConvertLevels2DToData
* is supported. Note that certain converters may impose size and order * is supported. The function expects at least one image to be passed,
* restrictions on the images, see documentation of a particular plugin * with each view expected to not be @cpp nullptr @ce, to have a
* for more information. Returns data on success, @cpp nullptr @ce * non-zero size in all dimensions, and all views sharing the same
* otherwise. * pixel format. Note that certain converters may impose additional
* size and order restrictions on the images, see documentation of a
* particular plugin for more information. Returns data on success,
* @cpp nullptr @ce otherwise.
* @see @ref features(), @ref convertToData(Containers::ArrayView<const CompressedImageView2D>), * @see @ref features(), @ref convertToData(Containers::ArrayView<const CompressedImageView2D>),
* @ref convert(), @ref convertToFile() * @ref convert(), @ref convertToFile()
*/ */
@ -999,10 +1030,13 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::ConvertLevels3DToData * Available only if @ref ImageConverterFeature::ConvertLevels3DToData
* is supported. Note that certain converters may impose size and order * is supported. The function expects at least one image to be passed,
* restrictions on the images, see documentation of a particular plugin * with each view expected to not be @cpp nullptr @ce, to have a
* for more information. Returns data on success, @cpp nullptr @ce * non-zero size in all dimensions, and all views sharing the same
* otherwise. * pixel format. Note that certain converters may impose additional
* size and order restrictions on the images, see documentation of a
* particular plugin for more information. Returns data on success,
* @cpp nullptr @ce otherwise.
* @see @ref features(), @ref convertToData(Containers::ArrayView<const CompressedImageView3D>), * @see @ref features(), @ref convertToData(Containers::ArrayView<const CompressedImageView3D>),
* @ref convert(), @ref convertToFile() * @ref convert(), @ref convertToFile()
*/ */
@ -1015,7 +1049,10 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::ConvertCompressedLevels1DToData * Available only if @ref ImageConverterFeature::ConvertCompressedLevels1DToData
* is supported. Note that certain converters may impose size and order * is supported. The function expects at least one image to be passed,
* with each view expected to not be @cpp nullptr @ce, to have a
* non-zero size, and all views sharing the same pixel format. Note
* that certain converters may impose additional size and order
* restrictions on the images, see documentation of a particular plugin * restrictions on the images, see documentation of a particular plugin
* for more information. Returns data on success, @cpp nullptr @ce * for more information. Returns data on success, @cpp nullptr @ce
* otherwise. * otherwise.
@ -1031,10 +1068,13 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::ConvertCompressedLevels2DToData * Available only if @ref ImageConverterFeature::ConvertCompressedLevels2DToData
* is supported. Note that certain converters may impose size and order * is supported. The function expects at least one image to be passed,
* restrictions on the images, see documentation of a particular plugin * with each view expected to not be @cpp nullptr @ce, to have a
* for more information. Returns data on success, @cpp nullptr @ce * non-zero size in all dimensions, and all views sharing the same
* otherwise. * pixel format. Note that certain converters may impose additional
* size and order restrictions on the images, see documentation of a
* particular plugin for more information. Returns data on success,
* @cpp nullptr @ce otherwise.
* @see @ref features(), @ref convertToData(Containers::ArrayView<const ImageView2D>), * @see @ref features(), @ref convertToData(Containers::ArrayView<const ImageView2D>),
* @ref convert(), @ref convertToFile() * @ref convert(), @ref convertToFile()
*/ */
@ -1047,10 +1087,13 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::ConvertCompressedLevels3DToData * Available only if @ref ImageConverterFeature::ConvertCompressedLevels3DToData
* is supported. Note that certain converters may impose size and order * is supported. The function expects at least one image to be passed,
* restrictions on the images, see documentation of a particular plugin * with each view expected to not be @cpp nullptr @ce, to have a
* for more information. Returns data on success, @cpp nullptr @ce * non-zero size in all dimensions, and all views sharing the same
* otherwise. * pixel format. Note that certain converters may impose additional
* size and order restrictions on the images, see documentation of a
* particular plugin for more information. Returns data on success,
* @cpp nullptr @ce otherwise.
* @see @ref features(), @ref convertToData(Containers::ArrayView<const ImageView3D>), * @see @ref features(), @ref convertToData(Containers::ArrayView<const ImageView3D>),
* @ref convert(), @ref convertToFile() * @ref convert(), @ref convertToFile()
*/ */
@ -1063,8 +1106,9 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::Convert1DToFile or * Available only if @ref ImageConverterFeature::Convert1DToFile or
* @ref ImageConverterFeature::Convert1DToData is supported. Returns * @ref ImageConverterFeature::Convert1DToData is supported. The image
* @cpp true @ce on success, @cpp false @ce otherwise. * view is expected to not be @cpp nullptr @ce and to have a non-zero
* size. Returns @cpp true @ce on success, @cpp false @ce otherwise.
* @see @ref features(), @ref convertToFile(const CompressedImageView1D&, Containers::StringView), * @see @ref features(), @ref convertToFile(const CompressedImageView1D&, Containers::StringView),
* @ref convertToFile(const ImageData1D&, Containers::StringView), * @ref convertToFile(const ImageData1D&, Containers::StringView),
* @ref convert(), @ref convertToData() * @ref convert(), @ref convertToData()
@ -1076,8 +1120,10 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::Convert2DToFile or * Available only if @ref ImageConverterFeature::Convert2DToFile or
* @ref ImageConverterFeature::Convert2DToData is supported. Returns * @ref ImageConverterFeature::Convert2DToData is supported. The image
* @cpp true @ce on success, @cpp false @ce otherwise. * view is expected to not be @cpp nullptr @ce and to have a non-zero
* size in all dimensions. Returns @cpp true @ce on success,
* @cpp false @ce otherwise.
* @see @ref features(), @ref convertToFile(const CompressedImageView2D&, Containers::StringView), * @see @ref features(), @ref convertToFile(const CompressedImageView2D&, Containers::StringView),
* @ref convertToFile(const ImageData2D&, Containers::StringView), * @ref convertToFile(const ImageData2D&, Containers::StringView),
* @ref convert(), @ref convertToData() * @ref convert(), @ref convertToData()
@ -1099,8 +1145,9 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::Convert3DToFile or * Available only if @ref ImageConverterFeature::Convert3DToFile or
* @ref ImageConverterFeature::Convert3DToData is supported. Returns * @ref ImageConverterFeature::Convert3DToData is supported. The image
* @cpp true @ce on success, @cpp false @ce otherwise. * view is expected to not be @cpp nullptr @ce and to have a non-zero
* size. Returns @cpp true @ce on success, @cpp false @ce otherwise.
* @see @ref features(), @ref convertToFile(const CompressedImageView3D&, Containers::StringView), * @see @ref features(), @ref convertToFile(const CompressedImageView3D&, Containers::StringView),
* @ref convertToFile(const ImageData3D&, Containers::StringView), * @ref convertToFile(const ImageData3D&, Containers::StringView),
* @ref convert(), @ref convertToData() * @ref convert(), @ref convertToData()
@ -1113,8 +1160,9 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* *
* Available only if @ref ImageConverterFeature::ConvertCompressed1DToFile * Available only if @ref ImageConverterFeature::ConvertCompressed1DToFile
* or @ref ImageConverterFeature::ConvertCompressed1DToData is * or @ref ImageConverterFeature::ConvertCompressed1DToData is
* supported. Returns @cpp true @ce on success, @cpp false @ce * supported. The image view is expected to not be @cpp nullptr @ce and
* otherwise. * to have a non-zero size in all dimensions. Returns @cpp true @ce on
* success, @cpp false @ce otherwise.
* @see @ref features(), @ref convertToFile(const ImageView1D&, Containers::StringView), * @see @ref features(), @ref convertToFile(const ImageView1D&, Containers::StringView),
* @ref convertToFile(const ImageData1D&, Containers::StringView), * @ref convertToFile(const ImageData1D&, Containers::StringView),
* @ref convert(), @ref convertToData() * @ref convert(), @ref convertToData()
@ -1127,8 +1175,9 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* *
* Available only if @ref ImageConverterFeature::ConvertCompressed2DToFile * Available only if @ref ImageConverterFeature::ConvertCompressed2DToFile
* or @ref ImageConverterFeature::ConvertCompressed2DToData is * or @ref ImageConverterFeature::ConvertCompressed2DToData is
* supported. Returns @cpp true @ce on success, @cpp false @ce * supported. The image view is expected to not be @cpp nullptr @ce and
* otherwise. * to have a non-zero size in all dimensions. Returns @cpp true @ce on
* success, @cpp false @ce otherwise.
* @see @ref features(), @ref convertToFile(const ImageView2D&, Containers::StringView), * @see @ref features(), @ref convertToFile(const ImageView2D&, Containers::StringView),
* @ref convertToFile(const ImageData2D&, Containers::StringView), * @ref convertToFile(const ImageData2D&, Containers::StringView),
* @ref convert(), @ref convertToData() * @ref convert(), @ref convertToData()
@ -1151,8 +1200,9 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* *
* Available only if @ref ImageConverterFeature::ConvertCompressed3DToFile * Available only if @ref ImageConverterFeature::ConvertCompressed3DToFile
* or @ref ImageConverterFeature::ConvertCompressed3DToData is * or @ref ImageConverterFeature::ConvertCompressed3DToData is
* supported. Returns @cpp true @ce on success, @cpp false @ce * supported. The image view is expected to not be @cpp nullptr @ce and
* otherwise. * to have a non-zero size in all dimensions. Returns @cpp true @ce on
* success, @cpp false @ce otherwise.
* @see @ref features(), @ref convertToFile(const ImageView3D&, Containers::StringView), * @see @ref features(), @ref convertToFile(const ImageView3D&, Containers::StringView),
* @ref convertToFile(const ImageData3D&, Containers::StringView), * @ref convertToFile(const ImageData3D&, Containers::StringView),
* @ref convert(), @ref convertToData() * @ref convert(), @ref convertToData()
@ -1222,7 +1272,10 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::ConvertLevels1DToFile * Available only if @ref ImageConverterFeature::ConvertLevels1DToFile
* is supported. Note that certain converters may impose size and order * is supported. The function expects at least one image to be passed,
* with each view expected to not be @cpp nullptr @ce, to have a
* non-zero size, and all views sharing the same pixel format. Note
* that certain converters may impose additional size and order
* restrictions on the images, see documentation of a particular plugin * restrictions on the images, see documentation of a particular plugin
* for more information. Returns @cpp true @ce on success, * for more information. Returns @cpp true @ce on success,
* @cpp false @ce otherwise. * @cpp false @ce otherwise.
@ -1238,10 +1291,13 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::ConvertLevels2DToFile * Available only if @ref ImageConverterFeature::ConvertLevels2DToFile
* is supported. Note that certain converters may impose size and order * is supported. The function expects at least one image to be passed,
* restrictions on the images, see documentation of a particular plugin * with each view expected to not be @cpp nullptr @ce, to have a
* for more information. Returns @cpp true @ce on success, * non-zero size in all dimensions, and all views sharing the same
* @cpp false @ce otherwise. * pixel format. Note that certain converters may impose additional
* size and order restrictions on the images, see documentation of a
* particular plugin for more information. Returns @cpp true @ce on
* success, @cpp false @ce otherwise.
* @see @ref features(), @ref convertToFile(Containers::ArrayView<const CompressedImageView2D>, Containers::StringView), * @see @ref features(), @ref convertToFile(Containers::ArrayView<const CompressedImageView2D>, Containers::StringView),
* @ref convert(), @ref convertToData() * @ref convert(), @ref convertToData()
*/ */
@ -1254,10 +1310,13 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::ConvertLevels3DToFile * Available only if @ref ImageConverterFeature::ConvertLevels3DToFile
* is supported. Note that certain converters may impose size and order * is supported. The function expects at least one image to be passed,
* restrictions on the images, see documentation of a particular plugin * with each view expected to not be @cpp nullptr @ce, to have a
* for more information. Returns @cpp true @ce on success, * non-zero size in all dimensions, and all views sharing the same
* @cpp false @ce otherwise. * pixel format. Note that certain converters may impose additional
* size and order restrictions on the images, see documentation of a
* particular plugin for more information. Returns @cpp true @ce on
* success, @cpp false @ce otherwise.
* @see @ref features(), @ref convertToFile(Containers::ArrayView<const CompressedImageView3D>, Containers::StringView), * @see @ref features(), @ref convertToFile(Containers::ArrayView<const CompressedImageView3D>, Containers::StringView),
* @ref convert(), @ref convertToData() * @ref convert(), @ref convertToData()
*/ */
@ -1270,7 +1329,10 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::ConvertCompressedLevels1DToFile * Available only if @ref ImageConverterFeature::ConvertCompressedLevels1DToFile
* is supported. Note that certain converters may impose size and order * is supported. The function expects at least one image to be passed,
* with each view expected to not be @cpp nullptr @ce, to have a
* non-zero size, and all views sharing the same pixel format. Note
* that certain converters may impose additional size and order
* restrictions on the images, see documentation of a particular plugin * restrictions on the images, see documentation of a particular plugin
* for more information. Returns @cpp true @ce on success, * for more information. Returns @cpp true @ce on success,
* @cpp false @ce otherwise. * @cpp false @ce otherwise.
@ -1286,10 +1348,13 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::ConvertCompressedLevels2DToFile * Available only if @ref ImageConverterFeature::ConvertCompressedLevels2DToFile
* is supported. Note that certain converters may impose size and order * is supported. The function expects at least one image to be passed,
* restrictions on the images, see documentation of a particular plugin * with each view expected to not be @cpp nullptr @ce, to have a
* for more information. Returns @cpp true @ce on success, * non-zero size in all dimensions, and all views sharing the same
* @cpp false @ce otherwise. * pixel format. Note that certain converters may impose additional
* size and order restrictions on the images, see documentation of a
* particular plugin for more information. Returns @cpp true @ce on
* success, @cpp false @ce otherwise.
* @see @ref features(), @ref convertToFile(Containers::ArrayView<const ImageView2D>, Containers::StringView), * @see @ref features(), @ref convertToFile(Containers::ArrayView<const ImageView2D>, Containers::StringView),
* @ref convert(), @ref convertToData() * @ref convert(), @ref convertToData()
*/ */
@ -1302,10 +1367,13 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract
* @m_since_latest * @m_since_latest
* *
* Available only if @ref ImageConverterFeature::ConvertCompressedLevels3DToFile * Available only if @ref ImageConverterFeature::ConvertCompressedLevels3DToFile
* is supported. Note that certain converters may impose size and order * is supported. The function expects at least one image to be passed,
* restrictions on the images, see documentation of a particular plugin * with each view expected to not be @cpp nullptr @ce, to have a
* for more information. Returns @cpp true @ce on success, * non-zero size in all dimensions, and all views sharing the same
* @cpp false @ce otherwise. * pixel format. Note that certain converters may impose additional
* size and order restrictions on the images, see documentation of a
* particular plugin for more information. Returns @cpp true @ce on
* success, @cpp false @ce otherwise.
* @see @ref features(), @ref convertToFile(Containers::ArrayView<const ImageView3D>, Containers::StringView), * @see @ref features(), @ref convertToFile(Containers::ArrayView<const ImageView3D>, Containers::StringView),
* @ref convert(), @ref convertToData() * @ref convert(), @ref convertToData()
*/ */

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

File diff suppressed because it is too large Load Diff

8
src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp

@ -112,14 +112,12 @@ TgaImageConverterTest::TgaImageConverterTest() {
} }
void TgaImageConverterTest::wrongFormat() { void TgaImageConverterTest::wrongFormat() {
ImageView2D image{PixelFormat::RG8Unorm, {}, nullptr}; Containers::Pointer<AbstractImageConverter> converter = _converterManager.instantiate("TgaImageConverter");
const char data[4]{};
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_VERIFY(!converter->convertToData(ImageView2D{PixelFormat::RG8Unorm, {1, 1}, data}));
Containers::Pointer<AbstractImageConverter> converter = _converterManager.instantiate("TgaImageConverter");
const auto data = converter->convertToData(image);
CORRADE_VERIFY(!data);
CORRADE_COMPARE(out.str(), "Trade::TgaImageConverter::convertToData(): unsupported pixel format PixelFormat::RG8Unorm\n"); CORRADE_COMPARE(out.str(), "Trade::TgaImageConverter::convertToData(): unsupported pixel format PixelFormat::RG8Unorm\n");
} }

Loading…
Cancel
Save