From 9f64e86584f2bcab9b31304b2b61e0007e4136f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 26 Aug 2013 01:14:35 +0200 Subject: [PATCH] TextureTools: added `magnum-distancefield` utility. Standalone command-line executable allowing for easy conversion of black&white images to distance field texture. --- CMakeLists.txt | 5 +- doc/building.dox | 5 +- src/TextureTools/CMakeLists.txt | 15 ++++ src/TextureTools/configure.h.cmake | 26 ++++++ src/TextureTools/distance-field.cpp | 134 ++++++++++++++++++++++++++++ 5 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 src/TextureTools/configure.h.cmake create mode 100644 src/TextureTools/distance-field.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b9fc43d6..3d97e031d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,8 +45,9 @@ cmake_dependent_option(WITH_SCENEGRAPH "Build SceneGraph library" ON "NOT WITH_D cmake_dependent_option(WITH_SHADERS "Build Shaders library" ON "NOT WITH_DEBUGTOOLS" ON) cmake_dependent_option(WITH_SHAPES "Build Shapes library" ON "NOT WITH_DEBUGTOOLS" ON) option(WITH_TEXT "Build Text library" ON) -cmake_dependent_option(WITH_TEXTURETOOLS "Build TextureTools library" ON "NOT WITH_TEXT" ON) +cmake_dependent_option(WITH_TEXTURETOOLS "Build TextureTools library" ON "NOT WITH_TEXT;NOT WITH_DISTANCEFIELDCONVERTER" ON) option(WITH_MAGNUMINFO "Build magnum-info utility" OFF) +cmake_dependent_option(WITH_DISTANCEFIELDCONVERTER "Build magnum-distancefield utility" OFF "NOT TARGET_GLES" OFF) # Application libraries if(CORRADE_TARGET_NACL) @@ -54,7 +55,7 @@ if(CORRADE_TARGET_NACL) cmake_dependent_option(WITH_WINDOWLESSNACLAPPLICATION "Build WindowlessNaClApplication library" OFF "NOT WITH_MAGNUMINFO" ON) else() option(WITH_GLXAPPLICATION "Build GlxApplication library" OFF) - cmake_dependent_option(WITH_WINDOWLESSGLXAPPLICATION "Build WindowlessGlxApplication library" OFF "NOT WITH_MAGNUMINFO" ON) + cmake_dependent_option(WITH_WINDOWLESSGLXAPPLICATION "Build WindowlessGlxApplication library" OFF "NOT WITH_MAGNUMINFO;NOT WITH_DISTANCEFIELDCONVERTER" ON) cmake_dependent_option(WITH_XEGLAPPLICATION "Build XEglApplication library" OFF "TARGET_GLES" OFF) cmake_dependent_option(WITH_GLUTAPPLICATION "Build GlutApplication library" OFF "NOT TARGET_GLES" OFF) option(WITH_SDL2APPLICATION "Build Sdl2Application library" OFF) diff --git a/doc/building.dox b/doc/building.dox index 97044ac8b..7de021c2e 100644 --- a/doc/building.dox +++ b/doc/building.dox @@ -169,9 +169,12 @@ be built and which not: Enabled automatically if `WITH_DEBUGTOOLS` is enabled. - `WITH_TEXT` - Text library. Enables also building of TextureTools library. - `WITH_TEXTURETOOLS` - TextureTools library. Enabled automatically if `WITH_TEXT` - is enabled. + or `WITH_DISTANCEFIELDCONVERTER` is enabled. - `WITH_MAGNUMINFO` - `magnum-info` executable, provides information about the engine and OpenGL capabilities. + - `WITH_DISTANCEFIELDCONVERTER` - `magnum-distancefield` executable for + converting black&white images to distance field textures. Enables also + building of TextureTools library. None of the @ref Platform "application libraries" is built by default (and you need at least one). Choose the one which suits your requirements and your diff --git a/src/TextureTools/CMakeLists.txt b/src/TextureTools/CMakeLists.txt index 6529facbf..f3dc153c0 100644 --- a/src/TextureTools/CMakeLists.txt +++ b/src/TextureTools/CMakeLists.txt @@ -46,6 +46,21 @@ if(BUILD_STATIC_PIC) endif() target_link_libraries(MagnumTextureTools Magnum) +if(WITH_DISTANCEFIELDCONVERTER) + if(NOT UNIX OR TARGET_GLES) + message(FATAL_ERROR "magnum-distancefield is not available on this platform. Set WITH_DISTANCEFIELDCONVERTER to OFF to suppress this warning.") + endif() + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/configure.h) + + include_directories(${CMAKE_CURRENT_BINARY_DIR}) + + add_executable(magnum-distancefield distance-field.cpp) + target_link_libraries(magnum-distancefield MagnumTextureTools Magnum MagnumWindowlessGlxApplication ${X11_LIBRARIES}) + install(TARGETS magnum-distancefield DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}) +endif() + install(TARGETS MagnumTextureTools DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) install(FILES ${MagnumTextureTools_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/TextureTools) diff --git a/src/TextureTools/configure.h.cmake b/src/TextureTools/configure.h.cmake new file mode 100644 index 000000000..5ab11b3db --- /dev/null +++ b/src/TextureTools/configure.h.cmake @@ -0,0 +1,26 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#define MAGNUM_IMPORTER_PLUGIN_DIR "${MAGNUM_LIBRARY_INSTALL_DIR}/magnum/importers" +#define MAGNUM_IMAGECONVERTER_PLUGIN_DIR "${MAGNUM_LIBRARY_INSTALL_DIR}/magnum/imageconverters" diff --git a/src/TextureTools/distance-field.cpp b/src/TextureTools/distance-field.cpp new file mode 100644 index 000000000..82c2d6ac0 --- /dev/null +++ b/src/TextureTools/distance-field.cpp @@ -0,0 +1,134 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include + +#include "Math/Geometry/Rectangle.h" +#include "Image.h" +#include "ImageFormat.h" +#include "Renderer.h" +#include "Texture.h" +#include "TextureFormat.h" +#include "Platform/WindowlessGlxApplication.h" +#include "TextureTools/DistanceField.h" +#include "Trade/AbstractImporter.h" +#include "Trade/AbstractImageConverter.h" +#include "Trade/ImageData.h" + +#include "configure.h" + +namespace Magnum { + +class DistanceFieldConverter: public Platform::WindowlessApplication { + public: + explicit DistanceFieldConverter(const Arguments& arguments); + + int exec() override; + + private: + Utility::Arguments args; +}; + +DistanceFieldConverter::DistanceFieldConverter(const Arguments& arguments): WindowlessGlxApplication(arguments, nullptr) { + args.addArgument("input").setHelp("input", "input image") + .addArgument("output").setHelp("output", "output image") + .addOption("importer", "TgaImporter").setHelp("image importer plugin") + .addOption("converter", "TgaImageConverter").setHelp("image converter plugin") + .addNamedArgument("output-size").setHelpKey("output-size", "\"X Y\"").setHelp("output-size", "size of output image") + .addNamedArgument("radius").setHelpKey("radius", "N").setHelp("radius", "distance field computation radius") + .setHelp("Converts black&white image to distance-field representation.") + .parse(arguments.argc, arguments.argv); + + createContext({}); +} + +int DistanceFieldConverter::exec() { + /* Load plugins */ + PluginManager::Manager importerManager(MAGNUM_IMPORTER_PLUGIN_DIR); + if(!(importerManager.load(args.value("importer")) & (PluginManager::LoadState::Loaded|PluginManager::LoadState::Static))) { + Error() << "Cannot load importer plugin" << args.value("importer") << "from" << MAGNUM_IMPORTER_PLUGIN_DIR; + return 1; + } + PluginManager::Manager converterManager(MAGNUM_IMAGECONVERTER_PLUGIN_DIR); + if(!(converterManager.load(args.value("converter")) & (PluginManager::LoadState::Loaded|PluginManager::LoadState::Static))) { + Error() << "Cannot load converter plugin" << args.value("converter") << "from" << MAGNUM_IMAGECONVERTER_PLUGIN_DIR; + return 1; + } + + /* Instance plugins */ + Trade::AbstractImporter* importer = importerManager.instance(args.value("importer")); + Trade::AbstractImageConverter* converter = converterManager.instance(args.value("converter")); + CORRADE_INTERNAL_ASSERT(importer && converter); + + /* Open input file */ + Trade::ImageData2D* image = nullptr; + if(!importer->openFile(args.value("input")) || !(image = importer->image2D(0))) { + Error() << "Cannot open file" << args.value("input"); + delete importer; + delete converter; + return 1; + } + + delete importer; + if(image->format() != ImageFormat::Red) { + Error() << "Unsupported image format" << image->format(); + delete converter; + return 1; + } + + /* Input texture */ + Texture2D input; + input.setMinificationFilter(Sampler::Filter::Linear) + .setMagnificationFilter(Sampler::Filter::Linear) + .setWrapping(Sampler::Wrapping::ClampToEdge) + .setImage(0, TextureFormat::R8, *image); + + /* Output texture */ + Texture2D output; + output.setStorage(1, TextureFormat::R8, args.value("output-size")); + + CORRADE_INTERNAL_ASSERT(Renderer::error() == Renderer::Error::NoError); + + /* Do it */ + Debug() << "Converting image of size" << image->size() << "to distance field..."; + TextureTools::distanceField(input, output, {{}, args.value("output-size")}, args.value("radius"), image->size()); + delete image; + + /* Save image */ + Image2D result(ImageFormat::Red, ImageType::UnsignedByte); + output.image(0, result); + if(!converter->exportToFile(result, args.value("output"))) { + Error() << "Cannot save file" << args.value("output"); + delete converter; + return 1; + } + + delete converter; + return 0; +} + +} + +MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::DistanceFieldConverter)