* Firstly, we need to create a directory for our module under modules directory. Copy folder //dummy// and name it //imagemagick// * We can use the module with name DummyModule, but for any real module, we probably want to give some beeter name. So the next few steps are optional, but recommended: * Rename DummyModule.cpp to ImageMagickSource.cpp and DummyModule.h to ImageMagickSource.h * Change DummyModule.h in #include in ImageMagickSource.cpp to ImageMagickSource.h * Rename the class: change all occurences of DummyModule class to ImageMagickSource * We're gonna use ImageMagick library, specifically it's C++ bindings called **Magick++**. CMake know about this packafe, so it's easy to add test for in. We add following line into CMakeLists.txt in modules directory: find_package(ImageMagick COMPONENTS Magick++) * If we found ImageMagick, we can tell cmake to compile our module. So we add subdirectory imagemagic, if the test was successfull: IF(${ImageMagick_Magick++_FOUND}) add_subdirectory(imagemagick) ENDIF() * Now we have to edit CMakeLists.txt in imagemagick directory: change SET(MODULE dummy) to SET(MODULE imagemagick_source) and filenames in SET(SRC.... to ImageMagickSource.* * And lastly, we add the library to CMakeLists.txt in imagemagick directory: add following line for imagemagick includes: include_directories(${ImageMagick_Magick++_INCLUDE_DIR}) and change linking to this: target_link_libraries(${MODULE} ${LIBNAME} ${ImageMagick_Magick++_LIBRARY}) * Now the module should compile under new name and link with libMagick++.so * So we can finally move to the code. Let's change the header file like this: #ifndef DUMMYMODULE_H_ #define DUMMYMODULE_H_ #include "yuri/io/BasicIOThread.h" namespace yuri { namespace imagemagick_module { using yuri::log::Log; using yuri::config::Parameter; using yuri::config::Parameters; using yuri::io::pThreadBase; class ImageMagickSource: public yuri::io::BasicIOThread { public: IO_THREAD_GENERATOR_DECLARATION static shared_ptr configure(); virtual ~ImageMagickSource(); private: ImageMagickSource(Log &log_,pThreadBase parent,Parameters ¶meters); virtual bool step(); virtual bool set_param(Parameter& param); }; } /* namespace dummy_module */ } /* namespace yuri */ The only difference between this and the DummyModule.h is (except for the name) that we removed the attribute **dummy_name**. Not for the cpp file: #include "ImageMagickSource.h" #include "yuri/config/RegisteredClass.h" #include "Magick++.h" #include namespace yuri { namespace imagemagick_module { REGISTER("imagemagick_source",ImageMagickSource) IO_THREAD_GENERATOR(ImageMagickSource) using namespace yuri::io; shared_ptr ImageMagickSource::configure() { shared_ptr p = BasicIOThread::configure(); p->set_description("Image loader based on ImageMagick."); p->set_max_pipes(1,1); return p; } ImageMagickSource::ImageMagickSource(Log &log_,pThreadBase parent,Parameters ¶meters): BasicIOThread(log_,parent,1,1,std::string("ImageMagickSource")) { IO_THREAD_INIT("ImageMagickSource") } ImageMagickSource::~ImageMagickSource() { } bool ImageMagickSource::step() { pBasicFrame frame = in[0]->pop_frame(); if (!frame) return true; if (frame->get_planes_count()>1) { log[warning] << "Input frame has more than 1 plane, ignoring them\n"; } try { Magick::Blob blob(PLANE_RAW_DATA(frame,0),PLANE_SIZE(frame,0)); Magick::Image image(blob); image.modifyImage(); yuri::size_t width = image.columns(); yuri::size_t height = image.rows(); log[debug] << "Loaded image " << width << "x" < The only relevant changes are in the **step()** method. * First we get input frame. If there's no frame available, we return. Always return true, unless some unrecoverable fatal error occurred. Returning false will most often terminate the program. * We support only frames with single plane, so we print a warning when we get more. * Then it's just using API of Magick++. Note how we use **PLANE_RAW_DATA** and **PLANE_SIZE** to get data and size of first (index 0) plane in the incoming frame. * Next important thing is the call to **allocate_empty_frame**, that allocates just enough data for a frame with given resolution and format. * Lastly, we call **push_raw_video_frame** to push the frame to the output pipe. That's all, this is working code for imagemagick_source module! Look at the actual version in source distribution, there are some minor enhancements, but this was the first version.