Wednesday, September 4, 2013

Plugin manager - part 2

The second part of the plugin manager is the downloading and installing tab: it groups all available plugins in the same table allowing for a fast selection and install.

The screenshot is available underneath. Currently there are only a few test plugins on the list used for testing purposes.
The plugin manager downloads the information of all the plugins. The table displays the name and version of the plugin. An install button downloads and installs selected plugin which can be immediately used. The already installed plugins are marked so. The selection of the plugin displays a detailed description and preview image. For a fast find there is a search field to quickly display only wanted plugins in the table.

Now the plugin manager is finished. The plugins can be downloaded and incorporated into nomacs. So the first version of the plugin system is finished. It will still improve during the next week when also the first plugins will be developed.

Monday, August 19, 2013

Trip to Vienna

For the Google Summer of Code the mentoring organization receives a certain amount of money that can be used for students to come to visit their mentors. Because Ljubljana, the town where I live, is not far away (approx. 400 km) from Vienna, the town of the mentoring organization, the costs of traveling are not great. I was asked last year if I want to come to visit but I didn't have time. This year I had time so I gladly accepted the offer. On Thursday, July 11th I packed my bags and traveled to Vienna for a 3 days visit.

On Friday, after many skype conferences, I met my mentors in person. This day we set together in the same office and we did a lot of work on the nomacs plugin system. We modified the plugin interface to allow the user to create a submenu in the plugins menu. We also extended the interface to a viewport interface which now allows the plugins to completely connect to nomacs and to use all of its functionality. This is major addition to the plugin system. But it also needed a big change in nomacs which is now a dll. The main application had to be converted to a dll and a smaller application to call the dll. Because of the interconnection between different classes this is the only way for the plugins to use nomacs classes.

On Saturday I had some time to go some sightseeing around the town. In the evening I was invited to a dinner with all the mentors. On Sunday I finished my visit to Vienna and returned to home.

Thanks to all nomacs mentors: Markus, Stefan and Florian for a great trip to Vienna!

Monday, August 12, 2013

Plugin manager - part 1

Together with the nomacs mentors we decided that all the plugins will be managed by a Plugin manager: it will allow the user to download new plugins and to enable/disable already installed plugins. In this way the plugin installation is fast and simple. The user doesn't have to search for the plugins online but a refreshed database is shown in the plugin manager and the user just finds and installs the wanted plugin.

The plugin manager is the central part of the whole plugin system. It connects nomacs to the online database with plugin dlls and descriptions. It is also a connection to the dlls themselves. Because of the size of the plugin manager there was a change in my timeline from the proposal. The GUI for the plugin manager is much more extensive than the initially planed GUI of the plugin system. This is why more weeks will be used to develop the GUI.

Qt GUI on which nomacs is based has a great solution for the display of database data in tables: Model/View Programming. It is a great approach to connect the data to the tables for displaying. But it takes time to learn because of its vastness. The great thing is that it separates the displaying part and the data part. So when the data is changed only the cell in the table where the data was changed is refreshed. The table itself is very modifiable because with the use of delegates you can have buttons, checkboxes and many other things in the cells.

The first part of the plugin manager is the managing part. Bellow is the screenshot of it.
 The table displays the name and version of the installed plugin. A checkbox allows the user to enable or disable the installed plugin. And there is also an uninstall button for removing plugins. By selecting a plugin a plugin description and image preview are displayed.

Sunday, July 21, 2013

Qt plugins applied to nomacs

Because nomacs is based on Qt I decided that the best way to create plugins is using the Qt QPluginLoader. First we need to create an interface that is the connection between nomacs and dlls:
class DkPluginInterface {
    virtual ~DkPluginInterface() {}

    virtual QString pluginID() const = 0;
    virtual QString pluginName() const = 0;
    virtual QString pluginDescription() const = 0;
    virtual QImage pluginDescriptionImage() const = 0;
    virtual QString pluginVersion() const = 0;

    virtual QStringList runID() const = 0;
    virtual QString pluginMenuName(const QString &runID) const = 0;
    virtual QString pluginStatusTip(const QString &runID) const = 0; 
    virtual QImage runPlugin(const QString &runID, const QImage &image) const = 0;

Q_DECLARE_INTERFACE(nmc::DkPluginInterface, "com.nomacs.ImageLounge.DkPluginInterface/0.1")
In the interface there are the functions that need to be implemented in the plugins. These are the function called from nomacs to retrieve plugin information and to run it. So that the QPluginLoader can know about the interface we have to declare it with Q_DECLARE_INTERFACE. The header file of a the plugin extends the above interface. Here is a test plugin header to show the import:
class DkFlipPlugin : public QObject, DkPluginInterface {

    QString pluginID() const;
    QString pluginName() const;
    QString pluginDescription() const;
    QImage pluginDescriptionImage() const;
    QString pluginVersion() const;

    QStringList runID() const;
    QString pluginMenuName(const QString &runID) const;
    QString pluginStatusTip(const QString &runID) const; 
    QImage runPlugin(const QString &runID, const QImage &image) const;
With Q_INTERFACES we let Qt know which interfaces the plugin uses. Just before the end of the plugin cpp file we need to export the plugin: Q_EXPORT_PLUGIN2(dkflipplugin, DkFlipPlugin). By doing this we tell Qt that class DkFlipPlugin is part of the plugin interface.

To build a Qt dll using cmake we need to add  the following lines to the cmake file:
 Now we have a plugin that we need to import into nomacs. We load the plugin using QPluginLoader from which we create a QObject instance that we cast to our DkPluginInterface class:
    QPluginLoader *loader = new QPluginLoader(filePath);
    QObject *plugin = loader->instance();
    if(plugin) {

        DkPluginInterface *initializedPlugin = qobject_cast<DkPluginInterface*>(plugin);
        if(initializedPlugin) {
            // do something with the plugin
    else delete loader;

Friday, June 28, 2013

The start to a second year with GSoC and Nomacs

This year I decided to apply for GSoC again. The main reason is the great experience I had last year. I really liked working with Nomacs and the Nomacs developers. They were really great mentors, always available to talk and help. This is also why I wanted to work with the Nomacs team again.

When April came I was glad to see that Nomacs team (part of the Computational Science and Engineering at TU Wien organisation) was again selected as a mentoring organisation. I looked at the project ideas they've prepared and one of them completely caught my eyes. It was the plug-in system idea. I decided that I want to do this project and I want anyone else take it from me.

Every year there are thousands of  students applying to GSoC. So to get selected ones needs to distinguish himself  from the others. I already had the advantage of knowing Nomacs and Qt from last years GSoC so I could really focus to prepare the project so it would best fit Nomacs. I read some books on the topic of Qt plug-ins and then implemented a simple test plug-in in Nomacs to show the feasibility. I also became a Nomacs translator. I've translated it into Slovene and Italian. So before the selection I already did a lot of work to show my commitment to the project.

My proposal with a full description of the project and timeline is accessible at:

In the weeks to come I'll be writing posts on the development of the plug-in system.

Saturday, August 25, 2012

The End

The Google Summer of Code 2012 came to an end. I would like to thank all Nomacs mentors for this great experience.

Thursday, August 9, 2012

Filtering image noise

Every image we shoot with a digital camera has some noise in it. Depending on the environment where we shoot the noise can be noticeable or unnoticeable. A very big component of the camera noise depends on the ISO speed. Higher the ISO value we select, more sensitive will the camera sensor be and a more noise picture we will get. The noise can be divided to color and luminance noise.

To get a prettier image we need to filter the noise out. In Nomacs RAW Loader we added median filtering of the image because it is a good method to filter noise without ruining the edges in the image. We replace every pixel in the image with the median value of the pixels within a square around the pixel we are replacing. The size of the square is called window size and it has to be an odd number. Because we only want to filter color noise we transform the RGB image to the YCrCb color space where we filter both chroma channels and then we transform back to the RGB space.

The only parameter in the median filter is the window size. Bigger the window size more time will the filtering take and also we can over filter an image. This is why we need to be careful which window size we select for each ISO value. To find them we did a small scientific research.

We put a Nikon D300 on a tripod and shoot a Colorchecker SG card 19 times. Each time we changed the ISO value that ranged from 100 to 6400. For determining the noise of a picture we calculated the peak signal to noise ratio (PSNR) . For the reference we used the image with the lower noise = ISO 100. Bottom graph shows the PSNR value to ISO value dependency. Higher is the PSNR value, lower is the noise.

We see that in general the PSNR value is decreasing with increasing the ISO value. Because the exposure is not the same in every image there is some zigzagging but the general trend is clearly visible. Lets now take a look what happens with PSNR values after median filtering with increasing the window size: 3,5,...,13:

We see that the PSNR value is increasing. But we also see that there is a limit to where the noise can be reduced. For higher ISO values we need higher window size to get there. The best way to decide the window size for each ISO is to take a look at PSNR as a function of window size. Bellow are the graphs for ISO 250 and 3200.

ISO = 250:
ISO = 3200:

We can see that the noise is decreasing with the increase of window size but if the number is too big the noise starts to increase again. For the window size we select the value where the noise stops to improve. The results for the window size are:

ISO > 6400: winSize = 13
ISO >= 3200: winSize = 11
ISO >= 2500: winSize = 9
ISO >= 400: winSize = 7
ISO < 400: winSize = 5