Verified Commit a352a7da authored by Flavien BRIDAULT-LOUCHEZ's avatar Flavien BRIDAULT-LOUCHEZ
Browse files

feat(core): add an image parser to allow basic initialisation in xml

parent d1c97f1a
/************************************************************************
*
* Copyright (C) 2009-2021 IRCAD France
* Copyright (C) 2012-2020 IHU Strasbourg
*
* This file is part of Sight.
*
* Sight is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Sight is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Sight. If not, see <https://www.gnu.org/licenses/>.
*
***********************************************************************/
#include "service/parser/Image.hpp"
#include <core/runtime/ConfigurationElement.hpp>
#include <core/runtime/Convert.hpp>
#include <data/Image.hpp>
#include <data/tools/Color.hpp>
namespace sight::service
{
namespace parser
{
//------------------------------------------------------------------------------
void Image::createConfig(core::tools::Object::sptr _obj)
{
const auto image = data::Image::dynamicCast(_obj);
SIGHT_ASSERT("Image does not exist.", image);
const auto config = core::runtime::Convert::toPropertyTree(m_cfg).get_child("object");
if(config.count("color"))
{
const std::string colorStr = config.get<std::string>("color");
std::uint8_t color[4];
data::tools::Color::hexaStringToRGBA(colorStr, color);
// Initialize with a dummy 4x4 black image
image->setType(core::tools::Type::s_UINT8);
image->setNumberOfComponents(4);
image->setSize2({4, 4, 1});
image->setSpacing2({1, 1, 1});
image->setOrigin2({0, 0, 0});
image->setPixelFormat(data::Image::RGBA);
image->resize();
auto itr = image->begin<sight::data::iterator::RGBA>();
const auto itrEnd = image->end<sight::data::iterator::RGBA>();
for( ; itr != itrEnd ; ++itr)
{
itr->r = color[0];
itr->g = color[1];
itr->b = color[2];
itr->a = color[3];
}
}
}
//------------------------------------------------------------------------------
} //namespace parser
} //namespace sight::service
/************************************************************************
*
* Copyright (C) 2009-2021 IRCAD France
* Copyright (C) 2012-2020 IHU Strasbourg
*
* This file is part of Sight.
*
* Sight is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Sight is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Sight. If not, see <https://www.gnu.org/licenses/>.
*
***********************************************************************/
#pragma once
#include "service/config.hpp"
#include <service/IXMLParser.hpp>
namespace sight::service
{
namespace parser
{
/**
* @brief Specific service that allows to initialize a sight::data::Image.
* Currently, this only allows to create a default 4x4 2D image with a custom color.
*
* @section XML XML Configuration
* @code{.xml}
<object uid="usExtractedImage" type="sight::data::Image" >
<color>#00FF00FF</color>
</object>
@endcode
* @see service::IXMLParser
*/
class SERVICE_CLASS_API Image : public service::IXMLParser
{
public:
SIGHT_DECLARE_SERVICE(Image, service::IXMLParser);
SERVICE_API void createConfig(core::tools::Object::sptr _obj) override;
};
} //namespace parser
} //namespace sight::service
......@@ -26,18 +26,15 @@
#include <core/runtime/Convert.hpp>
#include <data/Composite.hpp>
#include <data/Image.hpp>
#include <data/Mesh.hpp>
#include <service/AppConfigManager.hpp>
#include <service/IService.hpp>
#include <service/macros.hpp>
#include <service/op/Get.hpp>
#include <service/registry/ObjectService.hpp>
#include <service/base.hpp>
#include <service/parser/Image.hpp>
// Registers the fixture into the 'registry'
CPPUNIT_TEST_SUITE_REGISTRATION(::sight::service::ut::ConfigParserTest);
CPPUNIT_TEST_SUITE_REGISTRATION(sight::service::ut::ConfigParserTest);
//------------------------------------------------------------------------------
......@@ -51,7 +48,16 @@ namespace ut
void ConfigParserTest::setUp()
{
// Set up context before running a test.
// Set up context before running a test
core::runtime::init();
std::filesystem::path location = core::runtime::getResourceFilePath("tu_exec_service");
CPPUNIT_ASSERT(std::filesystem::exists(location));
auto& runtime = core::runtime::Runtime::get();
runtime.addModules(location);
core::runtime::loadModule("sight::module::service");
}
//------------------------------------------------------------------------------
......@@ -106,6 +112,52 @@ void ConfigParserTest::testObjectCreationWithConfig()
//------------------------------------------------------------------------------
void ConfigParserTest::testImageParser()
{
const std::string objectUUID = "objectUUID";
service::IService::ConfigType config;
// Configuration on core::tools::Object which uid is objectUUID
service::IService::ConfigType objCfg;
objCfg.add("<xmlattr>.uid", objectUUID);
objCfg.add("<xmlattr>.type", "sight::data::Image");
objCfg.add("color", "#FF459812");
config.add_child("object", objCfg);
service::IService::ConfigType serviceCfg;
serviceCfg.add_child("config", config);
// Create object configuration
const auto cfg = core::runtime::Convert::fromPropertyTree(serviceCfg);
// Create the object and its services from the configuration
service::AppConfigManager::sptr configManager = service::AppConfigManager::New();
configManager->service::IAppConfigManager::setConfig(cfg);
configManager->create();
auto image = std::dynamic_pointer_cast<data::Image>(core::tools::fwID::getObject(objectUUID));
// Test object uid
CPPUNIT_ASSERT_EQUAL(objectUUID, image->getID());
CPPUNIT_ASSERT_EQUAL(sight::data::Image::RGBA, image->getPixelFormat());
CPPUNIT_ASSERT_EQUAL(sight::core::tools::Type::s_UINT8, image->getType());
// We only test the image content, we do not really care about the image size and other attributes for now
auto itr = image->begin<sight::data::iterator::RGBA>();
const auto itrEnd = image->end<sight::data::iterator::RGBA>();
for( ; itr != itrEnd ; ++itr)
{
CPPUNIT_ASSERT_EQUAL(std::uint8_t(0xFF), itr->r);
CPPUNIT_ASSERT_EQUAL(std::uint8_t(0x45), itr->g);
CPPUNIT_ASSERT_EQUAL(std::uint8_t(0x98), itr->b);
CPPUNIT_ASSERT_EQUAL(std::uint8_t(0X12), itr->a);
}
configManager->destroy();
}
//------------------------------------------------------------------------------
core::runtime::ConfigurationElement::sptr ConfigParserTest::buildObjectConfig()
{
service::IService::ConfigType config;
......@@ -113,13 +165,13 @@ core::runtime::ConfigurationElement::sptr ConfigParserTest::buildObjectConfig()
// Configuration on core::tools::Object which uid is objectUUID
service::IService::ConfigType objCfg;
objCfg.add("<xmlattr>.uid", "objectUUID");
objCfg.add("<xmlattr>.type", "::sight::data::Image");
objCfg.add("<xmlattr>.type", "sight::data::Image");
config.add_child("object", objCfg);
// Object's service A
service::IService::ConfigType serviceA;
serviceA.add("<xmlattr>.uid", "myTestService1");
serviceA.add("<xmlattr>.type", "::sight::service::ut::STest1Image");
serviceA.add("<xmlattr>.type", "sight::service::ut::STest1Image");
service::IService::ConfigType dataServiceA;
dataServiceA.add("<xmlattr>.key", "data");
......@@ -130,7 +182,7 @@ core::runtime::ConfigurationElement::sptr ConfigParserTest::buildObjectConfig()
// Object's service B
service::IService::ConfigType serviceB;
serviceB.add("<xmlattr>.uid", "myTestService2");
serviceB.add("<xmlattr>.type", "::sight::service::ut::STest1Image");
serviceB.add("<xmlattr>.type", "sight::service::ut::STest1Image");
config.add_child("service", serviceB);
// Start method from object's services
......
......@@ -44,6 +44,7 @@ class ConfigParserTest : public CPPUNIT_NS::TestFixture
{
CPPUNIT_TEST_SUITE(ConfigParserTest);
CPPUNIT_TEST(testObjectCreationWithConfig);
CPPUNIT_TEST(testImageParser);
CPPUNIT_TEST_SUITE_END();
public:
......@@ -53,6 +54,7 @@ public:
/// test object with services creation from a configuration
void testObjectCreationWithConfig();
void testImageParser();
private:
......
......@@ -46,6 +46,7 @@
<xs:element name="node" type="NodeType" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="edge" type="EdgeType" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="colors" type="ColorType" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="color" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="param" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name='uid' type='xs:string' use="required" />
......
......@@ -25,6 +25,12 @@
<object>sight::data::Composite</object>
</extension>
<extension implements="::sight::service::extension::Factory">
<type>sight::service::IXMLParser</type>
<service>sight::service::parser::Image</service>
<object>sight::data::Image</object>
</extension>
<extension implements="::sight::service::extension::Factory">
<type>sight::service::IXMLParser</type>
<service>sight::service::parser::Matrix4</service>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment