Browse Source

Trade: support mip levels in image import.

There's a new level option in each imageND() API, plus an
imageNDLevelCount() query to get image level count.
pull/369/head
Vladimír Vondruš 6 years ago
parent
commit
dfacd7fb2d
  1. 7
      doc/changelog.dox
  2. 86
      src/Magnum/Trade/AbstractImporter.cpp
  3. 85
      src/Magnum/Trade/AbstractImporter.h
  4. 301
      src/Magnum/Trade/Test/AbstractImporterTest.cpp
  5. 6
      src/MagnumPlugins/AnyImageImporter/AnyImageImporter.cpp
  6. 3
      src/MagnumPlugins/AnyImageImporter/AnyImageImporter.h
  7. 11
      src/MagnumPlugins/AnySceneImporter/AnySceneImporter.cpp
  8. 9
      src/MagnumPlugins/AnySceneImporter/AnySceneImporter.h
  9. 2
      src/MagnumPlugins/ObjImporter/ObjImporter.cpp
  10. 4
      src/MagnumPlugins/TgaImporter/TgaImporter.cpp
  11. 2
      src/MagnumPlugins/TgaImporter/TgaImporter.h

7
doc/changelog.dox

@ -150,6 +150,13 @@ See also:
and @ref SceneGraph::AbstractBasicTranslationRotation3D::rotateLocal(const Math::Quaternion<T>&) "rotateLocal()"
overloads taking a @ref Math::Quaternion
@subsubsection changelog-latest-new-trade Trade library
- Ability to import image mip levels via an additional parameter in
@ref Trade::AbstractImporter::image2D(),
@ref Trade::AbstractImporter::image2DLevelCount() and similar APIs for 1D
and 3D images
@subsubsection changelog-latest-new-vk Vk library
- Updated Vulkan headers for version 1.2

86
src/Magnum/Trade/AbstractImporter.cpp

@ -52,7 +52,7 @@
namespace Magnum { namespace Trade {
std::string AbstractImporter::pluginInterface() {
return "cz.mosra.magnum.Trade.AbstractImporter/0.3";
return "cz.mosra.magnum.Trade.AbstractImporter/0.3.1";
}
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
@ -538,6 +538,16 @@ UnsignedInt AbstractImporter::image1DCount() const {
UnsignedInt AbstractImporter::doImage1DCount() const { return 0; }
UnsignedInt AbstractImporter::image1DLevelCount(const UnsignedInt id) {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image1DLevelCount(): no file opened", {});
CORRADE_ASSERT(id < doImage1DCount(), "Trade::AbstractImporter::image1DLevelCount(): index" << id << "out of range for" << doImage1DCount() << "entries", {});
const UnsignedInt out = doImage1DLevelCount(id);
CORRADE_ASSERT(out, "Trade::AbstractImporter::image1DLevelCount(): implementation reported zero levels", {});
return out;
}
UnsignedInt AbstractImporter::doImage1DLevelCount(UnsignedInt) { return 1; }
Int AbstractImporter::image1DForName(const std::string& name) {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image1DForName(): no file opened", {});
return doImage1DForName(name);
@ -553,15 +563,27 @@ std::string AbstractImporter::image1DName(const UnsignedInt id) {
std::string AbstractImporter::doImage1DName(UnsignedInt) { return {}; }
Containers::Optional<ImageData1D> AbstractImporter::image1D(const UnsignedInt id) {
Containers::Optional<ImageData1D> AbstractImporter::image1D(const UnsignedInt id, const UnsignedInt level) {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image1D(): no file opened", {});
CORRADE_ASSERT(id < doImage1DCount(), "Trade::AbstractImporter::image1D(): index" << id << "out of range for" << doImage1DCount() << "entries", {});
Containers::Optional<ImageData1D> image = doImage1D(id);
#ifndef CORRADE_NO_ASSERT
/* Check for the range only if requested level is nonzero, as
image*DLevelCount() is expected to return >= 1. This is done to prevent
random assertions and messages from a doImage*DLevelCount() to be
printed (e.g., many plugins delegate image loading and assert an access
to the manager for that), which may be confusing */
if(level) {
const UnsignedInt levelCount = doImage1DLevelCount(id);
CORRADE_ASSERT(levelCount, "Trade::AbstractImporter::image1D(): implementation reported zero levels", {});
CORRADE_ASSERT(level < levelCount, "Trade::AbstractImporter::image1D(): level" << level << "out of range for" << levelCount << "entries", {});
}
#endif
Containers::Optional<ImageData1D> image = doImage1D(id, level);
CORRADE_ASSERT(!image || !image->_data.deleter(), "Trade::AbstractImporter::image1D(): implementation is not allowed to use a custom Array deleter", {});
return image;
}
Containers::Optional<ImageData1D> AbstractImporter::doImage1D(UnsignedInt) {
Containers::Optional<ImageData1D> AbstractImporter::doImage1D(UnsignedInt, UnsignedInt) {
CORRADE_ASSERT(false, "Trade::AbstractImporter::image1D(): not implemented", {});
}
@ -572,6 +594,16 @@ UnsignedInt AbstractImporter::image2DCount() const {
UnsignedInt AbstractImporter::doImage2DCount() const { return 0; }
UnsignedInt AbstractImporter::image2DLevelCount(const UnsignedInt id) {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image2DLevelCount(): no file opened", {});
CORRADE_ASSERT(id < doImage2DCount(), "Trade::AbstractImporter::image2DLevelCount(): index" << id << "out of range for" << doImage2DCount() << "entries", {});
const UnsignedInt out = doImage2DLevelCount(id);
CORRADE_ASSERT(out, "Trade::AbstractImporter::image2DLevelCount(): implementation reported zero levels", {});
return out;
}
UnsignedInt AbstractImporter::doImage2DLevelCount(UnsignedInt) { return 1; }
Int AbstractImporter::image2DForName(const std::string& name) {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image2DForName(): no file opened", {});
return doImage2DForName(name);
@ -587,15 +619,27 @@ std::string AbstractImporter::image2DName(const UnsignedInt id) {
std::string AbstractImporter::doImage2DName(UnsignedInt) { return {}; }
Containers::Optional<ImageData2D> AbstractImporter::image2D(const UnsignedInt id) {
Containers::Optional<ImageData2D> AbstractImporter::image2D(const UnsignedInt id, const UnsignedInt level) {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image2D(): no file opened", {});
CORRADE_ASSERT(id < doImage2DCount(), "Trade::AbstractImporter::image2D(): index" << id << "out of range for" << doImage2DCount() << "entries", {});
Containers::Optional<ImageData2D> image = doImage2D(id);
#ifndef CORRADE_NO_ASSERT
/* Check for the range only if requested level is nonzero, as
image*DLevelCount() is expected to return >= 1. This is done to prevent
random assertions and messages from a doImage*DLevelCount() to be
printed (e.g., many plugins delegate image loading and assert an access
to the manager for that), which may be confusing */
if(level) {
const UnsignedInt levelCount = doImage2DLevelCount(id);
CORRADE_ASSERT(levelCount, "Trade::AbstractImporter::image2D(): implementation reported zero levels", {});
CORRADE_ASSERT(level < levelCount, "Trade::AbstractImporter::image2D(): level" << level << "out of range for" << levelCount << "entries", {});
}
#endif
Containers::Optional<ImageData2D> image = doImage2D(id, level);
CORRADE_ASSERT(!image || !image->_data.deleter(), "Trade::AbstractImporter::image2D(): implementation is not allowed to use a custom Array deleter", {});
return image;
}
Containers::Optional<ImageData2D> AbstractImporter::doImage2D(UnsignedInt) {
Containers::Optional<ImageData2D> AbstractImporter::doImage2D(UnsignedInt, UnsignedInt) {
CORRADE_ASSERT(false, "Trade::AbstractImporter::image2D(): not implemented", {});
}
@ -606,6 +650,16 @@ UnsignedInt AbstractImporter::image3DCount() const {
UnsignedInt AbstractImporter::doImage3DCount() const { return 0; }
UnsignedInt AbstractImporter::image3DLevelCount(const UnsignedInt id) {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image3DLevelCount(): no file opened", {});
CORRADE_ASSERT(id < doImage3DCount(), "Trade::AbstractImporter::image3DLevelCount(): index" << id << "out of range for" << doImage3DCount() << "entries", {});
const UnsignedInt out = doImage3DLevelCount(id);
CORRADE_ASSERT(out, "Trade::AbstractImporter::image3DLevelCount(): implementation reported zero levels", {});
return out;
}
UnsignedInt AbstractImporter::doImage3DLevelCount(UnsignedInt) { return 1; }
Int AbstractImporter::image3DForName(const std::string& name) {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image3DForName(): no file opened", {});
return doImage3DForName(name);
@ -621,15 +675,27 @@ std::string AbstractImporter::image3DName(const UnsignedInt id) {
std::string AbstractImporter::doImage3DName(UnsignedInt) { return {}; }
Containers::Optional<ImageData3D> AbstractImporter::image3D(const UnsignedInt id) {
Containers::Optional<ImageData3D> AbstractImporter::image3D(const UnsignedInt id, const UnsignedInt level) {
CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::image3D(): no file opened", {});
CORRADE_ASSERT(id < doImage3DCount(), "Trade::AbstractImporter::image3D(): index" << id << "out of range for" << doImage3DCount() << "entries", {});
Containers::Optional<ImageData3D> image = doImage3D(id);
#ifndef CORRADE_NO_ASSERT
/* Check for the range only if requested level is nonzero, as
image*DLevelCount() is expected to return >= 1. This is done to prevent
random assertions and messages from a doImage*DLevelCount() to be
printed (e.g., many plugins delegate image loading and assert an access
to the manager for that), which may be confusing */
if(level) {
const UnsignedInt levelCount = doImage3DLevelCount(id);
CORRADE_ASSERT(levelCount, "Trade::AbstractImporter::image3D(): implementation reported zero levels", {});
CORRADE_ASSERT(level < levelCount, "Trade::AbstractImporter::image3D(): level" << level << "out of range for" << levelCount << "entries", {});
}
#endif
Containers::Optional<ImageData3D> image = doImage3D(id, level);
CORRADE_ASSERT(!image || !image->_data.deleter(), "Trade::AbstractImporter::image3D(): implementation is not allowed to use a custom Array deleter", {});
return image;
}
Containers::Optional<ImageData3D> AbstractImporter::doImage3D(UnsignedInt) {
Containers::Optional<ImageData3D> AbstractImporter::doImage3D(UnsignedInt, UnsignedInt) {
CORRADE_ASSERT(false, "Trade::AbstractImporter::image3D(): not implemented", {});
}

85
src/Magnum/Trade/AbstractImporter.h

@ -243,6 +243,9 @@ checked by the implementation:
there is any file opened.
- All `do*()` implementations taking data ID as parameter are called only if
the ID is from valid range.
- For `doImage*()` and @p level parameter being nonzero, implementations are
called only if it is from valid range. Level zero is always expected to be
present and thus no check is done in that case.
@m_class{m-block m-warning}
@ -282,7 +285,7 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @brief Plugin interface
*
* @code{.cpp}
* "cz.mosra.magnum.Trade.AbstractImporter/0.3"
* "cz.mosra.magnum.Trade.AbstractImporter/0.3.1"
* @endcode
*/
static std::string pluginInterface();
@ -813,9 +816,20 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
* @brief One-dimensional image count
*
* Expects that a file is opened.
* @see @ref image1DLevelCount()
*/
UnsignedInt image1DCount() const;
/**
* @brief One-dimensional image mip level count
* @param id Image ID, from range [0, @ref image1DCount())
* @m_since_latest
*
* Always returns at least one level, import failures are deferred to
* @ref image1D(). Expects that a file is opened.
*/
UnsignedInt image1DLevelCount(UnsignedInt id);
/**
* @brief One-dimensional image ID for given name
*
@ -837,19 +851,31 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
/**
* @brief One-dimensional image
* @param id Image ID, from range [0, @ref image1DCount()).
* @param level Mip level, from range [0, @ref image1DLevelCount())
*
* Returns given image or @ref Containers::NullOpt if importing failed.
* Expects that a file is opened.
*/
Containers::Optional<ImageData1D> image1D(UnsignedInt id);
Containers::Optional<ImageData1D> image1D(UnsignedInt id, UnsignedInt level = 0);
/**
* @brief Two-dimensional image count
*
* Expects that a file is opened.
* @see @ref image2DLevelCount()
*/
UnsignedInt image2DCount() const;
/**
* @brief Two-dimensional image mip level count
* @param id Image ID, from range [0, @ref image2DCount()).
* @m_since_latest
*
* Always returns at least one level, import failures are deferred to
* @ref image2D(). Expects that a file is opened.
*/
UnsignedInt image2DLevelCount(UnsignedInt id);
/**
* @brief Two-dimensional image ID for given name
*
@ -871,19 +897,31 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
/**
* @brief Two-dimensional image
* @param id Image ID, from range [0, @ref image2DCount()).
* @param level Mip level, from range [0, @ref image2DLevelCount())
*
* Returns given image or @ref Containers::NullOpt if importing failed.
* Expects that a file is opened.
*/
Containers::Optional<ImageData2D> image2D(UnsignedInt id);
Containers::Optional<ImageData2D> image2D(UnsignedInt id, UnsignedInt level = 0);
/**
* @brief Three-dimensional image count
*
* Expects that a file is opened.
* @see @ref image3DLevelCount()
*/
UnsignedInt image3DCount() const;
/**
* @brief Three-dimensional image mip level count
* @param id Image ID, from range [0, @ref image3DCount())
* @m_since_latest
*
* Always returns at least one level, import failures are deferred to
* @ref image3D(). Expects that a file is opened.
*/
UnsignedInt image3DLevelCount(UnsignedInt id);
/**
* @brief Three-dimensional image ID for given name
*
@ -905,11 +943,12 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
/**
* @brief Three-dimensional image
* @param id Image ID, from range [0, @ref image3DCount()).
* @param level Mip level, from range [0, @ref image3DLevelCount())
*
* Returns given image or @ref Containers::NullOpt if importing failed.
* Expects that a file is opened.
*/
Containers::Optional<ImageData3D> image3D(UnsignedInt id);
Containers::Optional<ImageData3D> image3D(UnsignedInt id, UnsignedInt level = 0);
/*@}*/
@ -1228,6 +1267,14 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
*/
virtual UnsignedInt doImage1DCount() const;
/**
* @brief Implementation for @ref image1DLevelCount()
*
* Default implementation returns @cpp 1 @ce. See
* @ref doImage2DLevelCount() for expected implementation behavior.
*/
virtual UnsignedInt doImage1DLevelCount(UnsignedInt id);
/**
* @brief Implementation for @ref image1DForName()
*
@ -1243,7 +1290,7 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
virtual std::string doImage1DName(UnsignedInt id);
/** @brief Implementation for @ref image1D() */
virtual Containers::Optional<ImageData1D> doImage1D(UnsignedInt id);
virtual Containers::Optional<ImageData1D> doImage1D(UnsignedInt id, UnsignedInt level);
/**
* @brief Implementation for @ref image2DCount()
@ -1252,6 +1299,22 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
*/
virtual UnsignedInt doImage2DCount() const;
/**
* @brief Implementation for @ref image2DLevelCount()
*
* Default implementation returns @cpp 1 @ce. Similarly to all other
* `*Count()` functions, this function isn't expected to fail --- if an
* import error occus, this function should return @cpp 1 @ce and the
* error state should be returned from @ref image2D() instead; if a
* file really contains a zero-level image, the implementation should
* exclude that image from @ref doImage2DCount() instead of returning
* @cpp 0 @ce here.
*
* Deliberately not @cpp const @ce to allow plugins cache decoded
* data.
*/
virtual UnsignedInt doImage2DLevelCount(UnsignedInt id);
/**
* @brief Implementation for @ref image2DForName()
*
@ -1267,7 +1330,7 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
virtual std::string doImage2DName(UnsignedInt id);
/** @brief Implementation for @ref image2D() */
virtual Containers::Optional<ImageData2D> doImage2D(UnsignedInt id);
virtual Containers::Optional<ImageData2D> doImage2D(UnsignedInt id, UnsignedInt level);
/**
* @brief Implementation for @ref image3DCount()
@ -1276,6 +1339,14 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
*/
virtual UnsignedInt doImage3DCount() const;
/**
* @brief Implementation for @ref image3DLevelCount()
*
* Default implementation returns @cpp 1 @ce. See
* @ref doImage2DLevelCount() for expected implementation behavior.
*/
virtual UnsignedInt doImage3DLevelCount(UnsignedInt id);
/**
* @brief Implementation for @ref image3DForName()
*
@ -1291,7 +1362,7 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
virtual std::string doImage3DName(UnsignedInt id);
/** @brief Implementation for @ref image3D() */
virtual Containers::Optional<ImageData3D> doImage3D(UnsignedInt id);
virtual Containers::Optional<ImageData3D> doImage3D(UnsignedInt id, UnsignedInt level);
/** @brief Implementation for @ref importerState() */
virtual const void* doImporterState() const;

301
src/Magnum/Trade/Test/AbstractImporterTest.cpp

@ -207,6 +207,10 @@ struct AbstractImporterTest: TestSuite::Tester {
void image1D();
void image1DCountNotImplemented();
void image1DCountNoFile();
void image1DLevelCountNotImplemented();
void image1DLevelCountNoFile();
void image1DLevelCountOutOfRange();
void image1DLevelCountZero();
void image1DForNameNotImplemented();
void image1DForNameNoFile();
void image1DNameNotImplemented();
@ -215,11 +219,16 @@ struct AbstractImporterTest: TestSuite::Tester {
void image1DNotImplemented();
void image1DNoFile();
void image1DOutOfRange();
void image1DLevelOutOfRange();
void image1DCustomDeleter();
void image2D();
void image2DCountNotImplemented();
void image2DCountNoFile();
void image2DLevelCountNotImplemented();
void image2DLevelCountNoFile();
void image2DLevelCountOutOfRange();
void image2DLevelCountZero();
void image2DForNameNotImplemented();
void image2DForNameNoFile();
void image2DNameNotImplemented();
@ -228,11 +237,16 @@ struct AbstractImporterTest: TestSuite::Tester {
void image2DNotImplemented();
void image2DNoFile();
void image2DOutOfRange();
void image2DLevelOutOfRange();
void image2DCustomDeleter();
void image3D();
void image3DCountNotImplemented();
void image3DCountNoFile();
void image3DLevelCountNotImplemented();
void image3DLevelCountNoFile();
void image3DLevelCountOutOfRange();
void image3DLevelCountZero();
void image3DForNameNotImplemented();
void image3DForNameNoFile();
void image3DNameNotImplemented();
@ -241,6 +255,7 @@ struct AbstractImporterTest: TestSuite::Tester {
void image3DNotImplemented();
void image3DNoFile();
void image3DOutOfRange();
void image3DLevelOutOfRange();
void image3DCustomDeleter();
void importerState();
@ -407,6 +422,10 @@ AbstractImporterTest::AbstractImporterTest() {
&AbstractImporterTest::image1D,
&AbstractImporterTest::image1DCountNotImplemented,
&AbstractImporterTest::image1DCountNoFile,
&AbstractImporterTest::image1DLevelCountNotImplemented,
&AbstractImporterTest::image1DLevelCountNoFile,
&AbstractImporterTest::image1DLevelCountOutOfRange,
&AbstractImporterTest::image1DLevelCountZero,
&AbstractImporterTest::image1DForNameNotImplemented,
&AbstractImporterTest::image1DForNameNoFile,
&AbstractImporterTest::image1DNameNotImplemented,
@ -415,11 +434,16 @@ AbstractImporterTest::AbstractImporterTest() {
&AbstractImporterTest::image1DNotImplemented,
&AbstractImporterTest::image1DNoFile,
&AbstractImporterTest::image1DOutOfRange,
&AbstractImporterTest::image1DLevelOutOfRange,
&AbstractImporterTest::image1DCustomDeleter,
&AbstractImporterTest::image2D,
&AbstractImporterTest::image2DCountNotImplemented,
&AbstractImporterTest::image2DCountNoFile,
&AbstractImporterTest::image2DLevelCountNotImplemented,
&AbstractImporterTest::image2DLevelCountNoFile,
&AbstractImporterTest::image2DLevelCountOutOfRange,
&AbstractImporterTest::image2DLevelCountZero,
&AbstractImporterTest::image2DForNameNotImplemented,
&AbstractImporterTest::image2DForNameNoFile,
&AbstractImporterTest::image2DNameNotImplemented,
@ -428,11 +452,16 @@ AbstractImporterTest::AbstractImporterTest() {
&AbstractImporterTest::image2DNotImplemented,
&AbstractImporterTest::image2DNoFile,
&AbstractImporterTest::image2DOutOfRange,
&AbstractImporterTest::image2DLevelOutOfRange,
&AbstractImporterTest::image2DCustomDeleter,
&AbstractImporterTest::image3D,
&AbstractImporterTest::image3DCountNotImplemented,
&AbstractImporterTest::image3DCountNoFile,
&AbstractImporterTest::image3DLevelCountNotImplemented,
&AbstractImporterTest::image3DLevelCountNoFile,
&AbstractImporterTest::image3DLevelCountOutOfRange,
&AbstractImporterTest::image3DLevelCountZero,
&AbstractImporterTest::image3DForNameNotImplemented,
&AbstractImporterTest::image3DForNameNoFile,
&AbstractImporterTest::image3DNameNotImplemented,
@ -441,6 +470,7 @@ AbstractImporterTest::AbstractImporterTest() {
&AbstractImporterTest::image3DNotImplemented,
&AbstractImporterTest::image3DNoFile,
&AbstractImporterTest::image3DOutOfRange,
&AbstractImporterTest::image3DLevelOutOfRange,
&AbstractImporterTest::image3DCustomDeleter,
&AbstractImporterTest::importerState,
@ -2672,6 +2702,10 @@ void AbstractImporterTest::image1D() {
void doClose() override {}
UnsignedInt doImage1DCount() const override { return 8; }
UnsignedInt doImage1DLevelCount(UnsignedInt id) override {
if(id == 7) return 3;
else return {};
}
Int doImage1DForName(const std::string& name) override {
if(name == "eighth") return 7;
else return -1;
@ -2680,17 +2714,18 @@ void AbstractImporterTest::image1D() {
if(id == 7) return "eighth";
else return {};
}
Containers::Optional<ImageData1D> doImage1D(UnsignedInt id) override {
if(id == 7) return ImageData1D{PixelFormat::RGBA8Unorm, {}, {}, &state};
Containers::Optional<ImageData1D> doImage1D(UnsignedInt id, UnsignedInt level) override {
if(id == 7 && level == 2) return ImageData1D{PixelFormat::RGBA8Unorm, {}, {}, &state};
else return {};
}
} importer;
CORRADE_COMPARE(importer.image1DCount(), 8);
CORRADE_COMPARE(importer.image1DLevelCount(7), 3);
CORRADE_COMPARE(importer.image1DForName("eighth"), 7);
CORRADE_COMPARE(importer.image1DName(7), "eighth");
auto data = importer.image1D(7);
auto data = importer.image1D(7, 2);
CORRADE_VERIFY(data);
CORRADE_COMPARE(data->importerState(), &state);
}
@ -2719,6 +2754,67 @@ void AbstractImporterTest::image1DCountNoFile() {
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::image1DCount(): no file opened\n");
}
void AbstractImporterTest::image1DLevelCountNotImplemented() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doImage1DCount() const override { return 8; }
} importer;
CORRADE_COMPARE(importer.image1DLevelCount(7), 1);
}
void AbstractImporterTest::image1DLevelCountNoFile() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return false; }
void doClose() override {}
} importer;
std::ostringstream out;
Error redirectError{&out};
importer.image1DLevelCount(7);
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::image1DLevelCount(): no file opened\n");
}
void AbstractImporterTest::image1DLevelCountOutOfRange() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doImage1DCount() const override { return 8; }
} importer;
std::ostringstream out;
Error redirectError{&out};
importer.image1DLevelCount(8);
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::image1DLevelCount(): index 8 out of range for 8 entries\n");
}
void AbstractImporterTest::image1DLevelCountZero() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doImage1DCount() const override { return 8; }
UnsignedInt doImage1DLevelCount(UnsignedInt) override { return 0; }
} importer;
std::ostringstream out;
Error redirectError{&out};
importer.image1DLevelCount(7);
/* This should print a similar message instead of a confusing
"level 1 out of range for 0 entries" */
importer.image1D(7, 1);
CORRADE_COMPARE(out.str(),
"Trade::AbstractImporter::image1DLevelCount(): implementation reported zero levels\n"
"Trade::AbstractImporter::image1D(): implementation reported zero levels\n");
}
void AbstractImporterTest::image1DForNameNotImplemented() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
@ -2831,6 +2927,22 @@ void AbstractImporterTest::image1DOutOfRange() {
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::image1D(): index 8 out of range for 8 entries\n");
}
void AbstractImporterTest::image1DLevelOutOfRange() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doImage1DCount() const override { return 8; }
UnsignedInt doImage1DLevelCount(UnsignedInt) override { return 3; }
} importer;
std::ostringstream out;
Error redirectError{&out};
importer.image1D(7, 3);
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::image1D(): level 3 out of range for 3 entries\n");
}
void AbstractImporterTest::image1DCustomDeleter() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
@ -2838,7 +2950,7 @@ void AbstractImporterTest::image1DCustomDeleter() {
void doClose() override {}
UnsignedInt doImage1DCount() const override { return 1; }
Containers::Optional<ImageData1D> doImage1D(UnsignedInt) override {
Containers::Optional<ImageData1D> doImage1D(UnsignedInt, UnsignedInt) override {
return ImageData1D{PixelFormat::RGBA8Unorm, {}, Containers::Array<char>{nullptr, 0, [](char*, std::size_t) {}}};
}
} importer;
@ -2857,6 +2969,10 @@ void AbstractImporterTest::image2D() {
void doClose() override {}
UnsignedInt doImage2DCount() const override { return 8; }
UnsignedInt doImage2DLevelCount(UnsignedInt id) override {
if(id == 7) return 3;
else return {};
}
Int doImage2DForName(const std::string& name) override {
if(name == "eighth") return 7;
else return -1;
@ -2865,17 +2981,18 @@ void AbstractImporterTest::image2D() {
if(id == 7) return "eighth";
else return {};
}
Containers::Optional<ImageData2D> doImage2D(UnsignedInt id) override {
if(id == 7) return ImageData2D{PixelFormat::RGBA8Unorm, {}, {}, &state};
Containers::Optional<ImageData2D> doImage2D(UnsignedInt id, UnsignedInt level) override {
if(id == 7 && level == 2) return ImageData2D{PixelFormat::RGBA8Unorm, {}, {}, &state};
else return {};
}
} importer;
CORRADE_COMPARE(importer.image2DCount(), 8);
CORRADE_COMPARE(importer.image2DLevelCount(7), 3);
CORRADE_COMPARE(importer.image2DForName("eighth"), 7);
CORRADE_COMPARE(importer.image2DName(7), "eighth");
auto data = importer.image2D(7);
auto data = importer.image2D(7, 2);
CORRADE_VERIFY(data);
CORRADE_COMPARE(data->importerState(), &state);
}
@ -2904,6 +3021,67 @@ void AbstractImporterTest::image2DCountNoFile() {
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::image2DCount(): no file opened\n");
}
void AbstractImporterTest::image2DLevelCountNotImplemented() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doImage2DCount() const override { return 8; }
} importer;
CORRADE_COMPARE(importer.image2DLevelCount(7), 1);
}
void AbstractImporterTest::image2DLevelCountNoFile() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return false; }
void doClose() override {}
} importer;
std::ostringstream out;
Error redirectError{&out};
importer.image2DLevelCount(7);
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::image2DLevelCount(): no file opened\n");
}
void AbstractImporterTest::image2DLevelCountOutOfRange() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doImage2DCount() const override { return 8; }
} importer;
std::ostringstream out;
Error redirectError{&out};
importer.image2DLevelCount(8);
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::image2DLevelCount(): index 8 out of range for 8 entries\n");
}
void AbstractImporterTest::image2DLevelCountZero() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doImage2DCount() const override { return 8; }
UnsignedInt doImage2DLevelCount(UnsignedInt) override { return 0; }
} importer;
std::ostringstream out;
Error redirectError{&out};
importer.image2DLevelCount(7);
/* This should print a similar message instead of a confusing
"level 1 out of range for 0 entries" */
importer.image2D(7, 1);
CORRADE_COMPARE(out.str(),
"Trade::AbstractImporter::image2DLevelCount(): implementation reported zero levels\n"
"Trade::AbstractImporter::image2D(): implementation reported zero levels\n");
}
void AbstractImporterTest::image2DForNameNotImplemented() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
@ -3016,6 +3194,22 @@ void AbstractImporterTest::image2DOutOfRange() {
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::image2D(): index 8 out of range for 8 entries\n");
}
void AbstractImporterTest::image2DLevelOutOfRange() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doImage2DCount() const override { return 8; }
UnsignedInt doImage2DLevelCount(UnsignedInt) override { return 3; }
} importer;
std::ostringstream out;
Error redirectError{&out};
importer.image2D(7, 3);
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::image2D(): level 3 out of range for 3 entries\n");
}
void AbstractImporterTest::image2DCustomDeleter() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
@ -3023,7 +3217,7 @@ void AbstractImporterTest::image2DCustomDeleter() {
void doClose() override {}
UnsignedInt doImage2DCount() const override { return 1; }
Containers::Optional<ImageData2D> doImage2D(UnsignedInt) override {
Containers::Optional<ImageData2D> doImage2D(UnsignedInt, UnsignedInt) override {
return ImageData2D{PixelFormat::RGBA8Unorm, {}, Containers::Array<char>{nullptr, 0, [](char*, std::size_t) {}}};
}
} importer;
@ -3042,6 +3236,10 @@ void AbstractImporterTest::image3D() {
void doClose() override {}
UnsignedInt doImage3DCount() const override { return 8; }
UnsignedInt doImage3DLevelCount(UnsignedInt id) override {
if(id == 7) return 3;
else return {};
}
Int doImage3DForName(const std::string& name) override {
if(name == "eighth") return 7;
else return -1;
@ -3050,17 +3248,18 @@ void AbstractImporterTest::image3D() {
if(id == 7) return "eighth";
else return {};
}
Containers::Optional<ImageData3D> doImage3D(UnsignedInt id) override {
if(id == 7) return ImageData3D{PixelFormat::RGBA8Unorm, {}, {}, &state};
Containers::Optional<ImageData3D> doImage3D(UnsignedInt id, UnsignedInt level) override {
if(id == 7 && level == 2) return ImageData3D{PixelFormat::RGBA8Unorm, {}, {}, &state};
else return {};
}
} importer;
CORRADE_COMPARE(importer.image3DCount(), 8);
CORRADE_COMPARE(importer.image3DLevelCount(7), 3);
CORRADE_COMPARE(importer.image3DForName("eighth"), 7);
CORRADE_COMPARE(importer.image3DName(7), "eighth");
auto data = importer.image3D(7);
auto data = importer.image3D(7, 2);
CORRADE_VERIFY(data);
CORRADE_COMPARE(data->importerState(), &state);
}
@ -3089,6 +3288,68 @@ void AbstractImporterTest::image3DCountNoFile() {
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::image3DCount(): no file opened\n");
}
void AbstractImporterTest::image3DLevelCountNotImplemented() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doImage3DCount() const override { return 8; }
} importer;
CORRADE_COMPARE(importer.image3DLevelCount(7), 1);
}
void AbstractImporterTest::image3DLevelCountNoFile() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return false; }
void doClose() override {}
} importer;
std::ostringstream out;
Error redirectError{&out};
importer.image3DLevelCount(7);
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::image3DLevelCount(): no file opened\n");
}
void AbstractImporterTest::image3DLevelCountOutOfRange() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doImage3DCount() const override { return 8; }
} importer;
std::ostringstream out;
Error redirectError{&out};
importer.image3DLevelCount(8);
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::image3DLevelCount(): index 8 out of range for 8 entries\n");
}
void AbstractImporterTest::image3DLevelCountZero() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doImage3DCount() const override { return 8; }
UnsignedInt doImage3DLevelCount(UnsignedInt) override { return 0; }
} importer;
std::ostringstream out;
Error redirectError{&out};
importer.image3DLevelCount(7);
/* This should print a similar message instead of a confusing
"level 1 out of range for 0 entries" */
importer.image3D(7, 1);
CORRADE_COMPARE(out.str(),
"Trade::AbstractImporter::image3DLevelCount(): implementation reported zero levels\n"
"Trade::AbstractImporter::image3D(): implementation reported zero levels\n");
}
void AbstractImporterTest::image3DForNameNotImplemented() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
@ -3201,6 +3462,22 @@ void AbstractImporterTest::image3DOutOfRange() {
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::image3D(): index 8 out of range for 8 entries\n");
}
void AbstractImporterTest::image3DLevelOutOfRange() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doImage3DCount() const override { return 8; }
UnsignedInt doImage3DLevelCount(UnsignedInt) override { return 3; }
} importer;
std::ostringstream out;
Error redirectError{&out};
importer.image3D(7, 3);
CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::image3D(): level 3 out of range for 3 entries\n");
}
void AbstractImporterTest::image3DCustomDeleter() {
struct: AbstractImporter {
ImporterFeatures doFeatures() const override { return {}; }
@ -3208,7 +3485,7 @@ void AbstractImporterTest::image3DCustomDeleter() {
void doClose() override {}
UnsignedInt doImage3DCount() const override { return 1; }
Containers::Optional<ImageData3D> doImage3D(UnsignedInt) override {
Containers::Optional<ImageData3D> doImage3D(UnsignedInt, UnsignedInt) override {
return ImageData3D{PixelFormat::RGBA8Unorm, {}, Containers::Array<char>{nullptr, 0, [](char*, std::size_t) {}}};
}
} importer;

6
src/MagnumPlugins/AnyImageImporter/AnyImageImporter.cpp

@ -199,9 +199,11 @@ void AnyImageImporter::doOpenData(Containers::ArrayView<const char> data) {
UnsignedInt AnyImageImporter::doImage2DCount() const { return _in->image2DCount(); }
Containers::Optional<ImageData2D> AnyImageImporter::doImage2D(const UnsignedInt id) { return _in->image2D(id); }
UnsignedInt AnyImageImporter::doImage2DLevelCount(UnsignedInt id) { return _in->image2DLevelCount(id); }
Containers::Optional<ImageData2D> AnyImageImporter::doImage2D(const UnsignedInt id, const UnsignedInt level) { return _in->image2D(id, level); }
}}
CORRADE_PLUGIN_REGISTER(AnyImageImporter, Magnum::Trade::AnyImageImporter,
"cz.mosra.magnum.Trade.AbstractImporter/0.3")
"cz.mosra.magnum.Trade.AbstractImporter/0.3.1")

3
src/MagnumPlugins/AnyImageImporter/AnyImageImporter.h

@ -143,7 +143,8 @@ class MAGNUM_ANYIMAGEIMPORTER_EXPORT AnyImageImporter: public AbstractImporter {
MAGNUM_ANYIMAGEIMPORTER_LOCAL void doOpenData(Containers::ArrayView<const char> data) override;
MAGNUM_ANYIMAGEIMPORTER_LOCAL UnsignedInt doImage2DCount() const override;
MAGNUM_ANYIMAGEIMPORTER_LOCAL Containers::Optional<ImageData2D> doImage2D(UnsignedInt id) override;
MAGNUM_ANYIMAGEIMPORTER_LOCAL UnsignedInt doImage2DLevelCount(UnsignedInt id) override;
MAGNUM_ANYIMAGEIMPORTER_LOCAL Containers::Optional<ImageData2D> doImage2D(UnsignedInt id, UnsignedInt level) override;
Containers::Pointer<AbstractImporter> _in;
};

11
src/MagnumPlugins/AnySceneImporter/AnySceneImporter.cpp

@ -196,21 +196,24 @@ std::string AnySceneImporter::doTextureName(const UnsignedInt id) { return _in->
Containers::Optional<TextureData> AnySceneImporter::doTexture(const UnsignedInt id) { return _in->texture(id); }
UnsignedInt AnySceneImporter::doImage1DCount() const { return _in->image1DCount(); }
UnsignedInt AnySceneImporter::doImage1DLevelCount(UnsignedInt id) { return _in->image1DLevelCount(id); }
Int AnySceneImporter::doImage1DForName(const std::string& name) { return _in->image1DForName(name); }
std::string AnySceneImporter::doImage1DName(const UnsignedInt id) { return _in->image1DName(id); }
Containers::Optional<ImageData1D> AnySceneImporter::doImage1D(const UnsignedInt id) { return _in->image1D(id); }
Containers::Optional<ImageData1D> AnySceneImporter::doImage1D(const UnsignedInt id, const UnsignedInt level) { return _in->image1D(id, level); }
UnsignedInt AnySceneImporter::doImage2DCount() const { return _in->image2DCount(); }
UnsignedInt AnySceneImporter::doImage2DLevelCount(UnsignedInt id) { return _in->image2DLevelCount(id); }
Int AnySceneImporter::doImage2DForName(const std::string& name) { return _in->image2DForName(name); }
std::string AnySceneImporter::doImage2DName(const UnsignedInt id) { return _in->image2DName(id); }
Containers::Optional<ImageData2D> AnySceneImporter::doImage2D(const UnsignedInt id) { return _in->image2D(id); }
Containers::Optional<ImageData2D> AnySceneImporter::doImage2D(const UnsignedInt id, const UnsignedInt level) { return _in->image2D(id, level); }
UnsignedInt AnySceneImporter::doImage3DCount() const { return _in->image3DCount(); }
UnsignedInt AnySceneImporter::doImage3DLevelCount(UnsignedInt id) { return _in->image3DLevelCount(id); }
Int AnySceneImporter::doImage3DForName(const std::string& name) { return _in->image3DForName(name); }
std::string AnySceneImporter::doImage3DName(const UnsignedInt id) { return _in->image3DName(id); }
Containers::Optional<ImageData3D> AnySceneImporter::doImage3D(const UnsignedInt id) { return _in->image3D(id); }
Containers::Optional<ImageData3D> AnySceneImporter::doImage3D(const UnsignedInt id, const UnsignedInt level) { return _in->image3D(id, level); }
}}
CORRADE_PLUGIN_REGISTER(AnySceneImporter, Magnum::Trade::AnySceneImporter,
"cz.mosra.magnum.Trade.AbstractImporter/0.3")
"cz.mosra.magnum.Trade.AbstractImporter/0.3.1")

9
src/MagnumPlugins/AnySceneImporter/AnySceneImporter.h

@ -196,19 +196,22 @@ class MAGNUM_ANYSCENEIMPORTER_EXPORT AnySceneImporter: public AbstractImporter {
MAGNUM_ANYSCENEIMPORTER_LOCAL Containers::Optional<TextureData> doTexture(UnsignedInt id) override;
MAGNUM_ANYSCENEIMPORTER_LOCAL UnsignedInt doImage1DCount() const override;
MAGNUM_ANYSCENEIMPORTER_LOCAL UnsignedInt doImage1DLevelCount(UnsignedInt id) override;
MAGNUM_ANYSCENEIMPORTER_LOCAL Int doImage1DForName(const std::string& name) override;
MAGNUM_ANYSCENEIMPORTER_LOCAL std::string doImage1DName(UnsignedInt id) override;
MAGNUM_ANYSCENEIMPORTER_LOCAL Containers::Optional<ImageData1D> doImage1D(UnsignedInt id) override;
MAGNUM_ANYSCENEIMPORTER_LOCAL Containers::Optional<ImageData1D> doImage1D(UnsignedInt id, UnsignedInt level) override;
MAGNUM_ANYSCENEIMPORTER_LOCAL UnsignedInt doImage2DCount() const override;
MAGNUM_ANYSCENEIMPORTER_LOCAL UnsignedInt doImage2DLevelCount(UnsignedInt id) override;
MAGNUM_ANYSCENEIMPORTER_LOCAL Int doImage2DForName(const std::string& name) override;
MAGNUM_ANYSCENEIMPORTER_LOCAL std::string doImage2DName(UnsignedInt id) override;
MAGNUM_ANYSCENEIMPORTER_LOCAL Containers::Optional<ImageData2D> doImage2D(UnsignedInt id) override;
MAGNUM_ANYSCENEIMPORTER_LOCAL Containers::Optional<ImageData2D> doImage2D(UnsignedInt id, UnsignedInt level) override;
MAGNUM_ANYSCENEIMPORTER_LOCAL UnsignedInt doImage3DCount() const override;
MAGNUM_ANYSCENEIMPORTER_LOCAL UnsignedInt doImage3DLevelCount(UnsignedInt id) override;
MAGNUM_ANYSCENEIMPORTER_LOCAL Int doImage3DForName(const std::string& name) override;
MAGNUM_ANYSCENEIMPORTER_LOCAL std::string doImage3DName(UnsignedInt id) override;
MAGNUM_ANYSCENEIMPORTER_LOCAL Containers::Optional<ImageData3D> doImage3D(UnsignedInt id) override;
MAGNUM_ANYSCENEIMPORTER_LOCAL Containers::Optional<ImageData3D> doImage3D(UnsignedInt id, UnsignedInt level) override;
Containers::Pointer<AbstractImporter> _in;
};

2
src/MagnumPlugins/ObjImporter/ObjImporter.cpp

@ -448,4 +448,4 @@ Containers::Optional<MeshData3D> ObjImporter::doMesh3D(UnsignedInt id) {
}}
CORRADE_PLUGIN_REGISTER(ObjImporter, Magnum::Trade::ObjImporter,
"cz.mosra.magnum.Trade.AbstractImporter/0.3")
"cz.mosra.magnum.Trade.AbstractImporter/0.3.1")

4
src/MagnumPlugins/TgaImporter/TgaImporter.cpp

@ -71,7 +71,7 @@ void TgaImporter::doOpenData(const Containers::ArrayView<const char> data) {
UnsignedInt TgaImporter::doImage2DCount() const { return 1; }
Containers::Optional<ImageData2D> TgaImporter::doImage2D(UnsignedInt) {
Containers::Optional<ImageData2D> TgaImporter::doImage2D(UnsignedInt, UnsignedInt) {
/* Check if the file is long enough */
if(_in.size() < std::streamoff(sizeof(Implementation::TgaHeader))) {
Error() << "Trade::TgaImporter::image2D(): the file is too short:" << _in.size() << "bytes";
@ -149,4 +149,4 @@ Containers::Optional<ImageData2D> TgaImporter::doImage2D(UnsignedInt) {
}}
CORRADE_PLUGIN_REGISTER(TgaImporter, Magnum::Trade::TgaImporter,
"cz.mosra.magnum.Trade.AbstractImporter/0.3")
"cz.mosra.magnum.Trade.AbstractImporter/0.3.1")

2
src/MagnumPlugins/TgaImporter/TgaImporter.h

@ -110,7 +110,7 @@ class MAGNUM_TGAIMPORTER_EXPORT TgaImporter: public AbstractImporter {
void MAGNUM_TGAIMPORTER_LOCAL doOpenData(Containers::ArrayView<const char> data) override;
void MAGNUM_TGAIMPORTER_LOCAL doClose() override;
UnsignedInt MAGNUM_TGAIMPORTER_LOCAL doImage2DCount() const override;
Containers::Optional<ImageData2D> MAGNUM_TGAIMPORTER_LOCAL doImage2D(UnsignedInt id) override;
Containers::Optional<ImageData2D> MAGNUM_TGAIMPORTER_LOCAL doImage2D(UnsignedInt id, UnsignedInt level) override;
Containers::Array<char> _in;
};

Loading…
Cancel
Save