Source

python-fu-matrix-transform / matrix-transform.py

from gimpfu import *
from math import *
import gtk

class MatrixEntry(gtk.Dialog):
        """****c* matrix-transform/MatrixEntry
        *       DESCRIPTION
        *               Dialog class for taking in an M x N Matrix of floats
        *       ARGUMENTS
        *               None.
        *       SIDE EFFECTS
        *               None.
        *       RESULT
        *               None.
        *****"""

        def __init__(self, rows, columns):
                """****m* MatrixEntry/__init__
                *       DESCRIPTION
                *               Constructor
                *       ARGUMENTS
                *               rows    -- number of input rows
                *               columns -- number of input columns
                *       SIDE EFFECTS
                *               adds Entrys to self.vbox
                *       RESULT
                *               None.
                *****"""
                super(MatrixEntry, self).__init__("Matrix Transformation", None,gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,gtk.STOCK_OK, gtk.RESPONSE_OK))

                self.matrix = [[gtk.Entry() for j in range(columns)] for i in range(rows)]

                table = gtk.Table(3, 3, False)
                for r in range(rows):
                        for c in range(columns):
                                entry = self.matrix[r][c]
                                entry.set_width_chars(5)
                                if r <> c:
                                        entry.set_text("0.0")
                                else:
                                        entry.set_text("1.0")
                                table.attach(entry, c, c+1, r, r+1, xoptions=0, xpadding=12)

                self.vbox.pack_start(table, False, False)
                self.vbox.show_all()
        def run(self):
                """****m* MatrixEntry/run
                *       DESCRIPTION
                *               Function to show dialog and get user input
                *       ARGUMENTS
                *               None.
                *       SIDE EFFECTS
                *               None.
                *       RESULT
                *               Returns a list of length M containing lists of floats of length N
                *****"""
                result = super(MatrixEntry, self).run()
                if result == gtk.RESPONSE_OK:
                        return [[float(e.get_text())] for r in self.matrix for e in r]

                return None

def transform(item, matrix):
        """****f* matrix-transform/transform
        *       DESCRIPTION
        *               Wrapper function for gimp_item_transform_matrix
        *       ARGUMENTS
        *               item    -- the item to transform
        *               matrix  -- the 3x3 row major matrix
        *       SIDE EFFECTS
        *               calls pdb.gimp_item_transform_matrix on item
        *       RESULT
        *               same as pdb.gimp_item_transform_matrix
        *****"""
        return pdb.gimp_item_transform_matrix(item, *[coeff for row in matrix for coeff in row])

def stub(img, all_layers=True):
        """****f* matrix-transform/stub
        *       DESCRIPTION
        *               gets user input and determines what layers to apply transformation to
        *       ARGUMENTS
        *               all_layers      -- apply the transfer to all layers in the image(DEFAULT), or just the active layer
        *       SIDE EFFECTS
        *               spawns modal dialog for user input, will apply given transform (if any) to active layer or entire image
        *       RESULT
        *               None.
        *****"""
        dialog = MatrixEntry(3,3)
        T = dialog.run()
        dialog.destroy()

        if T <> None:
                if all_layers:
                        layers = img.layers
                else:
                        layers = [img.active_layer]

                pdb.gimp_image_undo_group_start(img)
                for layer in layers:
                        transform(layer, T)
                        layer.set_offsets(0,0)
                pdb.gimp_image_undo_group_end(img)

        return None


def matrix_layer_transform(img, drawable):
        """****f* matrix-transform/matrix_layer_transform
        *       DESCRIPTION
        *               Wrapper around matrix-transform/stub calls with all_layers set to False
        *       ARGUMENTS
        *               img             -- passed by python-fu
        *               drawable        -- passed by python-fu
        *       SIDE EFFECTS
        *               see matrix-transform/stub
        *       RESULT
        *               see matrix-transform/stub
        *****"""
        return stub(img, False)

def matrix_image_transform(img, drawable):
        """****f* matrix-transform/matrix_layer_transform
        *       DESCRIPTION
        *               Wrapper around matrix-transform/stub calls with all_layers set to True
        *       ARGUMENTS
        *               img             -- passed by python-fu
        *               drawable        -- passed by python-fu
        *       SIDE EFFECTS
        *               see matrix-transform/stub
        *       RESULT
        *               see matrix-transform/stub
        *****"""
        return stub(img)

"""****h* matrix-transform/matrix-transform
*       DESCRIPTION
*               Gets a 3x3 user input matrix and applies it to the current image or layer
*       SIDE EFFECTS
*               Adds to GIMP menu "Layer", submenu "Transform", item "Matrix"
*               Adds to GIMP menu "Image", submenu "Transform", item "Matrix"
*       RESULT
*               None.
*       NOTE
*               Only available when an active image is open in GIMP.
*
*       SOURCE
*"""
register(
        #name
        "matrix-image-transform",
        #blurb
        "Apply matrix transform to image",
        #help
        "Select the image to transform",
        #author
        "Code Fox",
        #copyright
        "http://en.wikipedia.org/wiki/MIT_License",
        #date
        "May 26, 2013",
        #menu path
        "<Image>/Image/Transform/Matrix",
        #image types
        "*",
        #params
        [],
        #results
        [],
        #function
        matrix_image_transform
)

register(
        #name
        "matrix-layer-transform",
        #blurb
        "Apply matrix transform to active layer",
        #help
        "Select the layer to transform",
        #author
        "Code Fox",
        #copyright
        "http://en.wikipedia.org/wiki/MIT_License",
        #date
        "May 26, 2013",
        #menu path
        "<Image>/Layer/Transform/Matrix",
        #image types
        "*",
        #params
        [],
        #results
        [],
        #function
        matrix_layer_transform
)

main()
"""*******"""