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.
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.
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.
Anything is fine, so I've used drawing tools, and it's enough to write some Python.
I'm sorry if there is a mistake somewhere.
Download and install the binaries for your OS from here.
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.
This time, I will show you how to execute a Python-Fu script from the Python-Fu console.
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.
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.
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.
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.
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.
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.
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.
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)
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")
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
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)
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)
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.
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.
http://developer.gimp.org/api/2.0/
https://www.gimp.org/docs/python/
http://gimpbook.com/scripting/
--Procedure browser (pdb reference) --Menu bar >> Help >> Start by selecting Procedure Browser
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
...
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