Browse Source

Trade: implement magnum-imageconverter --info.

Useful for inspecting unknown files.
pull/432/head
Vladimír Vondruš 6 years ago
parent
commit
92655c7238
  1. 2
      doc/changelog.dox
  2. 71
      src/Magnum/Trade/Implementation/converterUtilities.h
  3. 66
      src/Magnum/Trade/imageconverter.cpp

2
doc/changelog.dox

@ -248,6 +248,8 @@ See also:
- @ref Trade::PhongMaterialData now supports both color and texture instead
of just one or the other, can reference normal textures as well and
specfify texture coordinate transform
- @ref magnum-imageconverter "magnum-imageconverter" has a new `--info`
option for printing detailed info about a particular file
- RLE compression support in @ref Trade::TgaImporter "TgaImporter"
@subsubsection changelog-latest-new-vk Vk library

71
src/Magnum/Trade/Implementation/converterUtilities.h

@ -25,13 +25,15 @@
DEALINGS IN THE SOFTWARE.
*/
#include <Corrade/Containers/GrowableArray.h>
#include <Corrade/Containers/StaticArray.h>
#include <Corrade/PluginManager/AbstractPlugin.h>
#include <Corrade/Utility/ConfigurationGroup.h>
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/String.h>
#include "Magnum/Magnum.h"
#include "Magnum/Trade/AbstractImporter.h"
#include "Magnum/Trade/ImageData.h"
namespace Magnum { namespace Trade { namespace Implementation {
@ -61,6 +63,73 @@ void setOptions(PluginManager::AbstractPlugin& plugin, const std::string& option
}
}
struct ImageInfo {
UnsignedInt image, level;
bool compressed;
PixelFormat format;
CompressedPixelFormat compressedFormat;
Vector3i size;
std::string name;
};
Containers::Array<ImageInfo> imageInfo(AbstractImporter& importer, bool& error) {
Containers::Array<ImageInfo> infos;
for(UnsignedInt i = 0; i != importer.image1DCount(); ++i) {
for(UnsignedInt j = 0;j != importer.image1DLevelCount(i); ++j) {
Containers::Optional<Trade::ImageData1D> image = importer.image1D(i, j);
if(!image) {
error = true;
continue;
}
arrayAppend(infos, Containers::InPlaceInit, i, j,
image->isCompressed(),
image->isCompressed() ?
PixelFormat{} : image->format(),
image->isCompressed() ?
image->compressedFormat() : CompressedPixelFormat{},
Vector3i::pad(image->size()),
j ? "" : importer.image1DName(i));
}
}
for(UnsignedInt i = 0; i != importer.image2DCount(); ++i) {
for(UnsignedInt j = 0;j != importer.image2DLevelCount(i); ++j) {
Containers::Optional<Trade::ImageData2D> image = importer.image2D(i, j);
if(!image) {
error = true;
continue;
}
arrayAppend(infos, Containers::InPlaceInit, i, j,
image->isCompressed(),
image->isCompressed() ?
PixelFormat{} : image->format(),
image->isCompressed() ?
image->compressedFormat() : CompressedPixelFormat{},
Vector3i::pad(image->size()),
j ? "" : importer.image2DName(i));
}
}
for(UnsignedInt i = 0; i != importer.image3DCount(); ++i) {
for(UnsignedInt j = 0;j != importer.image3DLevelCount(i); ++j) {
Containers::Optional<Trade::ImageData3D> image = importer.image3D(i, j);
if(!image) {
error = true;
continue;
}
arrayAppend(infos, Containers::InPlaceInit, i, j,
image->isCompressed(),
image->isCompressed() ?
PixelFormat{} : image->format(),
image->isCompressed() ?
image->compressedFormat() : CompressedPixelFormat{},
image->size(),
j ? "" : importer.image2DName(i));
}
}
return infos;
}
}
}}}

66
src/Magnum/Trade/imageconverter.cpp

@ -24,6 +24,7 @@
*/
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/GrowableArray.h>
#include <Corrade/Containers/StaticArray.h>
#include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/Arguments.h>
@ -65,7 +66,7 @@ information.
@code{.sh}
magnum-imageconverter [-h|--help] [--importer IMPORTER] [--converter CONVERTER]
[--plugin-dir DIR] [-i|--importer-options key=val,key2=val2,]
[-c|--converter-options key=val,key2=val2,] [--] input output
[-c|--converter-options key=val,key2=val2,] [--info] [--] input output
@endcode
Arguments:
@ -82,12 +83,17 @@ Arguments:
pass to the importer
- `-c`, `--converter-options key=val,key2=val2,` --- configuration options
to pass to the converter
- `--info` --- print info about the input file and exit
Specifying `--importer raw:&lt;format&gt;` will treat the input as a raw
tightly-packed square of pixels in given @ref PixelFormat. Specifying
`--converter raw` will save raw imported data instead of using a converter
plugin.
If `--info` is given, the utility will print information about all images
present in the file. In this case no conversion is done and output file doesn't
need to be specified.
The `-i` / `--importer-options` and `-c` / `--converter-options` arguments
accept a comma-separated list of key/value pairs to set in the importer /
converter plugin configuration. If the `=` character is omitted, it's
@ -135,12 +141,26 @@ int main(int argc, char** argv) {
.addOption("plugin-dir").setHelp("plugin-dir", "override base plugin dir", "DIR")
.addOption('i', "importer-options").setHelp("importer-options", "configuration options to pass to the importer", "key=val,key2=val2,…")
.addOption('c', "converter-options").setHelp("converter-options", "configuration options to pass to the converter", "key=val,key2=val2,…")
.addBooleanOption("info").setHelp("info", "print info about the input file and exit")
.setParseErrorCallback([](const Utility::Arguments& args, Utility::Arguments::ParseError error, const std::string& key) {
/* If --info is passed, we don't need the output argument */
if(error == Utility::Arguments::ParseError::MissingArgument &&
key == "output" &&
args.isSet("info")) return true;
/* Handle all other errors as usual */
return false;
})
.setGlobalHelp(R"(Converts images of different formats.
Specifying --importer raw:<format> will treat the input as a raw tightly-packed
square of pixels in given pixel format. Specifying --converter raw will save
raw imported data instead of using a converter plugin.
If --info is given, the utility will print information about all images present
in the file. In this case no conversion is done and output file doesn't need to
be specified.
The -i / --importer-options and -c / --converter-options arguments accept a
comma-separated list of key/value pairs to set in the importer / converter
plugin configuration. If the = character is omitted, it's equivalent to saying
@ -177,6 +197,12 @@ key=true.)")
return 5;
}
/* Print image info, if requested */
if(args.isSet("info")) {
Debug{} << "Image 0:\n Mip 0:" << format << Vector2i{side};
return 0;
}
image = Trade::ImageData2D(format, Vector2i{side}, std::move(data));
/* Otherwise load it using an importer plugin */
@ -190,7 +216,43 @@ key=true.)")
/* Set options, if passed */
Trade::Implementation::setOptions(*importer, args.value("importer-options"));
/* Open input file */
/* Print image info, if requested */
if(args.isSet("info")) {
/* Open the file, but don't fail when an image can't be opened */
if(!importer->openFile(args.value("input"))) {
Error() << "Cannot open file" << args.value("input");
return 3;
}
if(!importer->image1DCount() && !importer->image2DCount() && !importer->image2DCount()) {
Debug{} << "No images found.";
return 0;
}
/* Parse everything first to avoid errors interleaved with output */
bool error = false;
Containers::Array<Trade::Implementation::ImageInfo> infos =
Trade::Implementation::imageInfo(*importer, error);
for(const Trade::Implementation::ImageInfo& info: infos) {
Debug d;
if(info.level == 0) {
d << "Image" << info.image << Debug::nospace << ":";
if(!info.name.empty()) d << info.name;
d << Debug::newline;
}
d << " Level" << info.level << Debug::nospace << ":";
if(info.compressed) d << info.compressedFormat;
else d << info.format;
if(info.size.z()) d << info.size;
else if(info.size.y()) d << info.size.xy();
else d << Math::Vector<1, Int>(info.size.x());
}
return error ? 1 : 0;
}
/* Open input file and the first image */
if(!importer->openFile(args.value("input")) || !(image = importer->image2D(0))) {
Error() << "Cannot open file" << args.value("input");
return 3;

Loading…
Cancel
Save