Developping Action Plugins

Getting Started: Invert

Introduction

The best way to start is first to develop an PIL function which handles the manipulation. Afterwards you create input fields in order to pass the required parameters to the PIL function. Invert is taken as a first case study as it doesn't require any parameters except for the image itself. Let's look at the source code:

Example 1. Invert Action Source Code

from core import models                                    # 1
from core.translation import _t

def init():
    #lazy import
    global Image, ImageChops
    import Image, ImageChops

#--- PIL function
def invert(image,amount=100):                              # 2
    inverted = ImageChops.invert(image)
    if amount < 100:
        inverted  = Image.blend(image, inverted, amount/100.0)
    if image.mode == 'RGBA':
        inverted.putalpha(image.split()[-1])
    return inverted

#--- Phatch Action
class Action(models.Action):                               # 3
    label       = _t('Invert')
    author      = 'Stani'
    email       = 'spe.stani.be@gmail.com'
    init        = staticmethod(init)                       # 4
    pil         = staticmethod(invert)                     # 5
    version     = '0.1'
    tags        = [_t('colours')]
    __doc__     = _t('Invert the colors of an image')      # 6

    def interface(self,fields):                            # 7
        fields[_t('Amount')] = self.SliderField(100,1,100)

    icon = \                                               # 8
'x\xda\x01\x91\nn\xf5\x89PNG\r\n\x1a\n\x00\x00\x00...'

1

Importing Modules.

2

Defining The PIL Function.

3

Defining The Action.

4

Linking The init function.

5

Linking The pil function.

6

Describing The Action.

7

Defining The Interface.

8

Adding An Icon

Importing Modules

For every action you need to add the first two lines which import the basic functionality for writing action plugins. The module models provide the architecture for the plugin: the class Action and the input fields.Every other module you need to import with the function init(), in which you declare them as global. For example to invert an image with PIL you need the ImageChops module.

[Note]

Why do modules have to be imported in a seperate method? The reason is that Phatch at startup imports all actions to extract the information it needs about the actions. If the imports would be declared normally, the startup would be delayed by maybe unneeded modules.

Defining The PIL function

The PIL function should be defined separately from the action. This is a design choice, similar to splitting the Model from the View in the MVC approach.

Defining The Action

You need to create a new class Action which is derived from models.Action. You need to define the action with the label, author, email, init, pil, version, tags and doc properties. label and doc will appear translated in the Add Action dialog box. That is why you need to mark them with the _t function. We link our init and pil function as static methods to the class. (At the moment tags and description, which can contain a longer description than the doc one-liner, are not exposed yet.)

Describing The Action

In the description property you can describe the action more elaborately. Use triple quotes for multi-line text.

Adding An Icon

As in the example no specific icon was added, Phatch will use a default one. In the wxPython demo package (python-wxtools) there is an utility img2py.py. With the following command you can convert any image (eg.png) to a python file:

$ python img2py.py fileName icon.py

This will generate an icon.py file, in which you will find the following code:

def getData():
    return zlib.decompress('icon data')

You can add now the icon data to your action source file to define the icon:

class Action(models.Action):
    description = """Invert the colors of the image."""
    icon        = 'icon data'
[Note]

Internally Phatch works with photos. Photos consist of multiple layers. Every layer contains an image, but also has its own offset postion. Phatch doesn't expose this functionality yet, but will later support full layered photos, just like in Gimp. The hierarchy to remember is: Photo>Layer>Image. Luckily you don't have to worry about this in the beginning as Phatch provides you an easy method to apply a PIL function the current layer image: apply_to_current_layer_image.

Further Study

Probably looking at the source code of the actions, will teach you the most. You find all the actions in the folder phatch/actions

[Note]

If you installed Phatch on Ubuntu, probably the actions are in the folder: /usr/lib/python2.5/site-packages/phatch/actions

Read the tutorial on the wiki.