Start in 5 minutes GIMP Python-Fu

3 line summary

A short tutorial on the GIMP extension script (Python-Fu). Learn the basics of working with GIMP from Python. The difficulty level is low because it is a more familiar tutorial than learning.

Preface

About GIMP

GIMP is an open source drawing tool. Categorically, it is a paint tool that manipulates images on a pixel-by-pixel basis. It has many features, but you can use it for free. It has been working natively (without X11) on Mac OS X for several years now. The drawing tool is not included in the Mac by default, so it is one of the good apps to include it.

This tutorial assumes GIMP 2.8. If the version is close to 2.8, you can run it without any changes.

About Python-Fu

GIMP comes with a library for extensions that allows you to work with GIMP programmatically. A Python-wrapped library for this extension is called Python-Fu.

Python-Fu allows Python scripts to add functionality to GIMP and automate GIMP operations. This is convenient when you want to execute a large amount of routine processing or iterative processing by changing parameters little by little. For example, if you want to add concentrated lines to the background of an image, it is easier to programmatically draw dozens of lines manually.

Prerequisite knowledge

Anything is fine, so I've used drawing tools, and it's enough to write some Python.

About this article

I'm sorry if there is a mistake somewhere.

Install GIMP

download

Download and install the binaries for your OS from here.

Start GIMP

For Mac OS X, a security check will be applied the first time you launch the app. You can bypass the check by starting it with Ctrl-click, but do it at your own risk. Besides that, it takes a little time to start up for the first time due to initialization processing.

Execute Python-Fu script

This time, I will show you how to execute a Python-Fu script from the Python-Fu console.

Console display

From the GIMP menu, select Filter >> Python-Fu >> Console to open the Python-Fu console with a Python prompt.

With this prompt, the GIMP library has already been loaded. No additional work is required to use the features of GIMP from Python. You can suddenly call a function in the library to manipulate GIMP.

Program input and execution

We have prepared a sample script to let you experience the features of Python-Fu.

Try copying the entire code below and pasting it into the Python-Fu console. When you're done typing down to main () at the bottom, a new window should open with the image. Please try it first.

# Python-Fu sample script
#GIMP Python-Copy and paste to the Fu console and run

#Creation of image data
##Create image data with the specified size
### width :Image data width(px)
### height :Height of image data(px)
def create_image(width, height):
  #Generate image data
  return gimp.Image(width, height, RGB)

#Add layer
##Create a new layer with the specified name and insert it into the image data
### image :Image data to add a layer
### name :Name (character string) of the newly created layer
def add_layer(image, name):
  #Parameters required to create a layer
  width   = image.width
  height  = image.height
  type    = RGB_IMAGE
  opacity = 100
  mode    = NORMAL_MODE
  #
  #Create a layer based on the parameters
  layer = gimp.Layer(image, name, width, height, type, opacity, mode)
  #
  #Fill the layer with a background color (matching GIMP's default behavior)
  layer.fill(1)
  #
  #Insert a layer at the 0th position of the image data
  position = 0
  image.add_layer(layer, position)
  #
  return layer

#Draw a line with the pencil tool
##Draw a line connecting the coordinate strings stored in the array in the drawing area with the pencil tool
### drawable :Drawing area (layer, etc.)
### lines :An array containing the coordinate sequences of the drawn lines
def draw_pencil_lines(drawable, lines):
  #Draw a line with the pencil tool
  pdb.gimp_pencil(drawable, len(lines), lines)

#Draw a rectangle with the pencil tool
##Draw a rectangle in the drawing area based on the upper left and lower right coordinates
### drawable :Drawing area (layer, etc.)
### x1 :Upper left X coordinate
### y1 :Upper left Y coordinate
### x2 :Lower right X coordinate
### y2 :Lower right Y coordinate
def draw_rect(drawable, x1, y1, x2, y2):
  lines = [x1, y1, x2, y1, x2, y2, x1, y2, x1, y1]
  draw_pencil_lines(drawable, lines)

#Draw a line with an airbrush
##Draw a line connecting the coordinate strings stored in the array in the drawing area with an airbrush
### drawable :Drawing area (layer, etc.)
### pressure :Pen pressure(0-100)
### lines :An array containing the coordinate sequences of the drawn lines
def draw_airbrush_lines(drawable, pressure, lines):
  #Draw a line with an airbrush
  pdb.gimp_airbrush(drawable, pressure, len(lines), lines)

#Draw a string
##Draws a character string in the specified drawing area
### drawable :Drawing area (layer, etc.)
### x :X coordinate of the position to draw the string
### y :Y coordinate of the position to draw the character string
### size :font size
### str :Character string to draw
def draw_text(drawable, x, y, size, str):
  image = drawable.image
  border = -1
  antialias = True
  size_type = PIXELS
  fontname = '*'
  floating_sel = pdb.gimp_text_fontname(image, drawable, x, y, str, border,
                 antialias, size, size_type, fontname)
  pdb.gimp_floating_sel_anchor(floating_sel)

#Change the drawing color
##Change the foreground color of the palette to set the drawing color
### r :Red element(0-255)
### g :Green element(0-255)
### b :Blue element(0-255)
### a :Transparency(0-1.0)
def set_color(r, g, b, a):
  color = (r, g, b, a)
  pdb.gimp_context_set_foreground(color)

#Change the thickness of the drawn line
##Resize the brush to set the line thickness
### width :Line thickness
def set_line_width(width):
  pdb.gimp_context_set_brush_size(width)

#Image display
##Create a new window and display the image data
### image :Image data to be displayed
def display_image(image):
  gimp.Display(image)

def main():
  image = create_image(640, 400)
  layer = add_layer(image, "background")
  draw_rect(layer, 390, 210, 490, 310)
  draw_text(layer, 200, 180, 20, "Hello")
  lines = [110,90, 120,180, 130,110, 140,150]
  draw_airbrush_lines(layer, 75, lines)
  set_color(255,0,0,1.0)  # Red
  set_line_width(1)
  draw_rect(layer, 420, 240, 520, 340)
  display_image(image)

main()

If everything went well, a new window should have been created with the image.

Did you get this in 5 minutes? It's just software installation and copying, so I think there wasn't a difficult part that could trip over.

Next, I will explain the contents of the processing of the script that I just executed.

Program description

Overall program structure

In the above script, first, the auxiliary functions required to create and process image data are defined. Functions for securing image data in the program, functions for creating layers, functions for drawing figures, functions for writing character strings, functions for displaying created images, etc.

When those auxiliary functions are completed, the auxiliary functions are called in order in the main () function to actually create and display the image.

Below, I would like to take a closer look at the implementation of auxiliary functions according to the structure of the program.

Image Creation of image

When creating an image with GIMP, first create the image data.

Image data is a container for layers. Images such as figures are not stored directly in the image data, but in the layers within them. When you save the image data, it becomes an image file.

Setting information such as width, height, and image type is required to create image data. The width and height are specified in pixels. The image type can be RGB, GRAY, INDEXED, and so on.

Image data is created with the Python-Fu gimp.Image () function. The following part at the beginning of the script is a function that creates image data.

#Creation of image data
##Create image data with the specified size
### width :Image data width(px)
### height :Height of image data(px)
def create_image(width, height):
  #Generate image data
  return gimp.Image(width, height, RGB)

Call the create_image function as follows:

image = create_image(640, 400)

Doing this creates image data with a width of 640 pixels, a height of 400 pixels, and RGB colors.

Add layer

Next, add a layer to the image data. The image will be drawn on a layer, so you need at least one layer.

The Python-Fu function that creates layers is gimp.Layer (). Pass the image data, layer name, layer width, height, image type, opacity, and mode as arguments to gimp.Layer ().

After creating the layer, fill it with the background color. This is in line with the behavior when creating layers from the GUI of the GIMP app. When you add a layer in GIMP, it behaves like a background color by default.

Then use the gimp.Image.add_layer () function to associate the layer with the image data. The argument position is a parameter that specifies the position to add the layer from the top.

The implementation of the function to add a layer is as follows.

#Add layer
##Create a new layer with the specified name and insert it into the image data
### image :Image data to add a layer
### name :Name (character string) of the newly created layer
def add_layer(image, name):
  #Parameters required to create a layer
  width   = image.width
  height  = image.height
  type    = RGB_IMAGE
  opacity = 100
  mode    = NORMAL_MODE
  #
  #Create a layer based on the parameters
  layer = gimp.Layer(image, name, width, height, type, opacity, mode)
  #
  #Fill the layer with a background color (matching GIMP's default behavior)
  layer.fill(1)
  #
  #Insert a layer at the 0th position of the image data
  position = 0
  image.add_layer(layer, position)
  #
  return layer

In Qiita's Markdown, it seems that blank lines are converted to blank lines and the indentation ends, so I added a comment character (#) as a workaround.

The add_layer () function is called in the main () function as follows:

layer = add_layer(image, "background")

When this is done, a layer named "Background" will be created and added to the image data.

Draw a line

Now that you've created the layer, you're ready to start painting. As the basis of image processing, first of all, we will prepare a method of drawing a line.

When working with Python-Fu, use tools such as pens and brushes in GIMP, just as you would when drawing with the GIMP app. Here we define a function that draws a line using the pencil tool.

You can use the pdb.gimp_pencil () function provided by Python-Fu to draw a line with the pencil tool. The argument of the pdb.gimp_pencil () function is an array that stores the drawing area such as a layer, the number of coordinates that the line goes through, and the coordinates that the line goes through.

It seems that the reason why we bother to pass the number of coordinates as an argument is that this gimp_pencil () is a wrapper for the C function. There is no way to find out the number of elements in an array in C, so you need to explicitly tell the function.

#Draw a line with the pencil tool
##Draw a line connecting the coordinate strings stored in the array in the drawing area with the pencil tool
### drawable :Drawing area (layer, etc.)
### lines :An array containing the coordinate sequences of the drawn lines
def draw_pencil_lines(drawable, lines):
  #Draw a line with the pencil tool
  pdb.gimp_pencil(drawable, len(lines), lines)

The draw_pencil_lines () function is called by the following draw_rect () function.

Draw a rectangle

Next, prepare a rectangle, that is, a function that draws a rectangle. To draw a rectangle, use the draw_pencil_lines () function created earlier instead of the Python-Fu function.

In the code below, the draw_pencil_lines () function that draws a line is passed an array that traces the four sides of the rectangle to draw a rectangle.

#Draw a rectangle with the pencil tool
##Draw a rectangle in the drawing area based on the upper left and lower right coordinates
### drawable :Drawing area (layer, etc.)
### x1 :Upper left X coordinate
### y1 :Upper left Y coordinate
### x2 :Lower right X coordinate
### y2 :Lower right Y coordinate
def draw_rect(drawable, x1, y1, x2, y2):
  lines = [x1, y1, x2, y1, x2, y2, x1, y2, x1, y1]
  draw_pencil_lines(drawable, lines)

The draw_rect () function is called as follows.

draw_rect(layer, 390, 210, 490, 310)

Doing this will draw a rectangle with the default color and default line width. I will explain later how to change the color and line width when drawing.

Draw a line with the airbrush tool

We also have a function to draw a line using an airbrush instead of the pencil tool. The airbrush is available in the pdb.gimp_airbrush () function. The arguments for pdb.gimp_airbrush () are similar to those for pdb.gimp_pencil (), with the addition of a parameter that specifies the pen pressure.

#Draw a line with an airbrush
##Draw a line connecting the coordinate strings stored in the array in the drawing area with an airbrush
### drawable :Drawing area (layer, etc.)
### pressure :Pen pressure(0-100)
### lines :An array containing the coordinate sequences of the drawn lines
def draw_airbrush_lines(drawable, pressure, lines):
  #Draw a line with an airbrush
  pdb.gimp_airbrush(drawable, pressure, len(lines), lines)

The draw_airbrush_lines () function is called in the main () function as follows: First, the path of the line you want to draw is put together in an array, and the function is called with that as an argument. The pen pressure is specified as 75.

lines = [110,90, 120,180, 130,110, 140,150]
draw_airbrush_lines(layer, 75, lines)

Draw a Japanese string

If you want to put a text message in the image, use the pdb.gimp_text_fontname () function. In addition to the character string you want to draw, specify parameters such as font size and whether to perform antialiasing processing. The draw_text () function is a function that wraps pdb.gimp_text_fontname () so that you can draw a string with only the minimum required information.

#Draw a string
##Draws a character string in the specified drawing area
### drawable :Drawing area (layer, etc.)
### x :X coordinate of the position to draw the string
### y :Y coordinate of the position to draw the character string
### size :font size
### str :Character string to draw
def draw_text(drawable, x, y, size, str):
  image = drawable.image
  border = -1
  antialias = True
  size_type = PIXELS
  fontname = '*'
  floating_sel = pdb.gimp_text_fontname(image, drawable, x, y, str, border,
                 antialias, size, size_type, fontname)
  pdb.gimp_floating_sel_anchor(floating_sel)

The way to call the draw_text () function is as follows. The drawing area, the X coordinate of the character writing position, the Y coordinate, the font size, and the character string to be drawn are passed as arguments and executed.

draw_text(layer, 200, 180, 20, "Hello")

Change color

When drawing a figure or character string, the color set in the foreground color in GIMP's color palette is used. The function that sets the foreground color of the color palette is pdb.gimp_context_set_foreground (), and the color data is represented by tuples of R, G, B, and A.

Here, for the sake of clarity, we have given the alias set_color and passed each element of RGBA as an argument separately.

#Change the drawing color
##Change the foreground color of the palette to set the drawing color
### r :Red element(0-255)
### g :Green element(0-255)
### b :Blue element(0-255)
### a :Transparency(0-1.0)
def set_color(r, g, b, a):
  color = (r, g, b, a)
  pdb.gimp_context_set_foreground(color)

In the main () function, this function is used to set the red color.

set_color(255,0,0,1.0)  # Red

Change the line thickness

The function that specifies the thickness of the pencil tool and airbrush is the pdb.gimp_context_set_bursh_size () function. In the code below, we've given the alias set_line_width () to make the feature easier to understand.

#Change the thickness of the drawn line
##Resize the brush to set the line thickness
### width :Line thickness
def set_line_width(width):
  pdb.gimp_context_set_brush_size(width)

If you want to draw a line with a width of 1 pixel, specify 1 as an argument like this.

set_line_width(1)

Image display

When the image processing is completed, the image data is displayed on the desktop. If you specify image data as an argument of the gimp.Display () function and execute it, a new window will be created and the image will be displayed.

As before, we've given it an easy-to-understand alias here as well.

#Image display
##Create a new window and display the image data
### image :Image data to be displayed
def display_image(image):
  gimp.Display(image)

The way to call the display_image () function is as follows.

display_image(image)

main () function

Below is the main () function. The function calls defined so far are summarized in one place.

In Python, the main () function is not defined as the entry point for the program, so we simply name it main according to common convention.

def main():
  image = create_image(640, 400)
  layer = add_layer(image, "background")
  draw_rect(layer, 390, 210, 490, 310)
  draw_text(layer, 200, 180, 20, "Hello")
  lines = [110,90, 120,180, 130,110, 140,150]
  draw_airbrush_lines(layer, 75, lines)
  set_color(255,0,0,1.0)  # Red
  set_line_width(1)
  draw_rect(layer, 420, 240, 520, 340)
  display_image(image)

main()

This is the end of the explanation of the program. The big difference from the general image processing library is that it uses the GIMP app mechanism such as brushes and palettes. If you've used any drawing tools, I think there's nothing difficult about it.

What to do from here

First of all, modify the above program to change the color and line width, change the shape of the figure, change the pen pressure of the airbrush tool, and see how the movement changes.

After that, please see the API reference etc. and make a lot of more interesting code. You may also find Python help () and dir () useful.

I didn't explain it this time, but you can also incorporate the script you created into GIMP as a plugin. If you get used to scripting to some extent, please give it a try.

reference

-API Reference

--Procedure browser (pdb reference) --Menu bar >> Help >> Start by selecting Procedure Browser

help () and dir ()

You can use the built-in help () and dir () in Python to see the details of Python objects. The usage example is introduced below.

You can use the help () function to get help for Python objects.

>>> help(gimp)
Help on module gimp:

NAME
    gimp - This module provides interfaces to allow you to write gimp plugins

FILE
    /Users/.../Applications/GIMP/GIMP.app/Contents/Resources/lib/gimp/2.0/python/gimp.so

CLASSES
    __builtin__.object
        Display
        Image
        Item
            Drawable
                Channel
                Layer
                    GroupLayer
            Vectors
        Parasite
        PixelFetcher
        PixelRgn
        Tile
    exceptions.RuntimeError(exceptions.StandardError)
        error
    VectorsStroke(__builtin__.object)
        VectorsBezierStroke
...

You can use the dir () function to see the members of a Python object.

>>> for i in dir(gimp.Layer):
...   print i
... 
ID
__class__
__cmp__
__delattr__
__doc__
__format__
__getattribute__
__hash__
__init__
__new__
__reduce__
__reduce_ex__
__repr__
__setattr__
__sizeof__
__str__
__subclasshook__
add_alpha
add_mask
apply_mask
attach_new_parasite
bpp
children
copy
create_mask
edit_mask
fill
...

Summary

So far, we've covered the steps to get started with Python-Fu, the scripting interface for GIMP extensions. I hope you find it useful.

__ End __

Recommended Posts

Start in 5 minutes GIMP Python-Fu
[Gimp] Start scripting in Python
Learn Pandas in 10 minutes
Understand in 10 minutes Selenium
Selenium running in 15 minutes
Let's experience BERT in about 30 minutes.
Scraping with Beautiful Soup in 10 minutes
Start SQLite in a programming language
Make matplotlib Japanese compatible in 3 minutes