Extensibility is one of the core ideas behind Marvin Framework. Since there are wide variety of image processing algorithms for many different kinds of applications, one strategy to support the continuous addition of new algorithms to the Marvin Framework is to let third-party developers to implement and share them as a plug-in. This tutorial describes how to implement a image processing algorithm as a Marvin plug-in.

Plug-in interface

Marvin framework only provides basic features to manipulate images. Therefore, image processing algorithms are implemented outside the framework via plug-in interface. Using this interface, algorithms are automatically suitable for third-party application development, image editing through MarvinEditor, and for usage by other plug-ins. The plug-in implementation interface are specified by the interface MarvinImagePlugin, as shown below.

public interface MarvinImagePlugin extends MarvinPlugin
{     
    public void load(); 
     
    public void getAttributesPanel(); 
     
    public void process 
    ( 
        MarvinImage imgIn,  
        MarvinImage imgOut,  
        MarvinAttributes attrOut,  
        MarvinImageMask mask,  
        boolean previewMode 
    ); 

    public void setImagePanel(MarvinImagePanel imgPanel);
     
    public MarvinImagePanel getImagePanel(); 
}

Since some features can have the same implementation for different plug-ins, the class MarvinAbstractImagePlugin can be extended in order to use a generic implementation of that features. So, a new plug-in must only implement the methods load(), getAttributesPanel() and process(...).

The method load() is only invoked one time and must initialize class objects, other plug-ins and data structures.

The method process() is invoked any time an image is processed by the plug-in. So, after loaded, the plug-in can process many images or even a stream of video frames.

The method getAttributesPanel() returns a MarvinAttributesPanel containing interface components used to manipulate the plug-in attributes values. This panel is used by MarvinEditor to create the plug-in configuration window. Moreover, this panel can be added into third-party application in order to integrate the plug-in manipulation inside the application.

Manipulating the pixel data

The method process(...) has two MarvinImage as parameters, the input image imgIn and the output image imageOut. The imgIn must be used as a read-only image and any changing in the image must be made in the imgOut. Usually MarvinImage objects uses RGB color model, so the pixel data of each RGB component is accessible can be manipulated, for instance, using the following methods:

// get color component values 
public int getIntComponent0(int x, int y)
public int getIntComponent1(int x, int y)
public int getIntComponent2(int x, int y)

// set color component values 
public void setIntColor(int x, int y, int color)
public void setIntColor(int x, int y, int c0, int c1, int c2)

In the case of RGB, the methods getIntComponent0(), getIntComponent1() and getIntComponent2() return the values of red, green and blue components, respectively. The set methods is used alter the components value. This generic interface is used in order to support any color model that represent its components using integer values. Nowadays, Marvin only supports integer and boolean color compoents. New formats will be added in the next versions in order to support other color models.

Implementing the plug-in

The source code below shows how to implement a gray scale algorithm as a Marvin plug-in.

package org.marvinproject.image.color.grayScale; 

import marvin.gui.MarvinFilterWindow; 
import marvin.image.MarvinImage; 
import marvin.image.MarvinImageMask; 
import marvin.performance.MarvinPerformanceMeter; 
import marvin.plugin.MarvinAbstractImagePlugin; 
import marvin.util.MarvinAttributes; 

public class GrayScale extends MarvinAbstractImagePlugin
{ 
    public void load(){} 
    public void getAttributesPanel(){return null;} 
     
    public void process 
    ( 
        MarvinImage imageIn,  
        MarvinImage imageOut, 
        MarvinAttributes attributesOut, 
        MarvinImageMask mask,  
        boolean previewMode 
    ) 
    { 
        int r,g,b,finalColor; 
        for (int x = 0; x < imageIn.getWidth(); x++) {
            for (int y = 0; y < imageIn.getHeight(); y++) {
                //Red - 30% / Green - 59% / Blue - 11% 
                r = imageIn.getIntComponent0(x, y); 
                g = imageIn.getIntComponent1(x, y); 
                b = imageIn.getIntComponent2(x, y); 
                finalColor = (int)((r*0.3)+(g*0.59)+(b*0.11)); 
                imageOut.setIntColor(x,y,finalColor,finalColor,finalColor);                 
            } 
        } 
    } 
}

Considering this plug-in does not have any attribute or object to initialize or graphical user interface, the methods load() and getAttributesPanel() have an empty implementation. In the other hand, the method process() takes the input image imgIn and retuns it in gray scale as the output image imgOut

You can check out the implementation of many plug-ins in the MarvinPlugins project: MarvinPlugins/src/org/marvinproject/image/. The MarvinPlugins project is also available for download.

Using your plug-in

In order to use your plug-in in third-party applications or other plug-ins, simply export it as a JAR file and place it inside the folder marvin/plugins/image/ of any project using Marvin. Since your plug-in is in that folder, it can be loaded in any application or other plug-in using the static melhod MarvinPluginLoader.loadPlugin(String name) as shown in the First Application Tutorial.