Gimp Python scripts work separately but not when combined - gimp

I have a multilayer Gimp XCF template and my goal is to automate inserting JPGs into it and export them from the command line.
I have a first working python-fu plugin for inserting the image, and a second working python-fu plugin for flattening/saving the image (one line of executed code), but I want to combine the two plugins to make them easier to call from the command line. Eventually I also want to automate the opening of the XCF file. For now though I'm just trying to combine the two functions. Both plugins receive "image" and "layer" as input parameters.
My function parameters for the combined plugin are image, layer, the JPG to insert (file), X and Y offsets for placing the image in the XCF template (x_offset, y_offset), and a place for the export (outputFolder).
When I add the save command (pdb.file_jpeg_save shown near the bottom of my code) to the first working script, it fails. Why would this work on its own but fail here?
My code is shown below.
#!/usr/bin/env python
from gimpfu import *
def add_flatten_save(image, layer, file, x_offset, y_offset, outputFolder):
''' Add image to new layer, flatten, then saveSave the current layer into a PNG file, a JPEG file and a BMP file. '''
# Indicates that the process has started.
gimp.progress_init("Opening '" + file + "'...")
try:
# Open file.
fileImage = None
if(file.lower().endswith(('.jpeg', '.jpg'))):
fileImage = pdb.file_jpeg_load(file, file)
# Create new layer.
newLayer = gimp.Layer(image, "New Layer Name", layer.width, layer.height, layer.type, layer.opacity, layer.mode)
# the +1 adds it behind the top layer
image.add_layer(newLayer, +1)
# Put image into the new layer.
fileLayer = fileImage.layers[0]
pdb.gimp_edit_copy(fileLayer)
floating = pdb.gimp_edit_paste(newLayer, True)
# Update the new layer.
newLayer.flush()
newLayer.merge_shadow(True)
newLayer.update(0, 0, newLayer.width, newLayer.height)
# Flatten + offset floating layer, then flatten image
pdb.gimp_floating_sel_to_layer(floating)
pdb.gimp_layer_set_offsets(floating, x_offset, y_offset)
pdb.gimp_image_flatten(image)
# Export JPG of flattened image
pdb.file_jpeg_save(image, layer, outputFolder + "/" + layer.name + ".jpg", "raw_filename", 0.9, 0, 0, 0, "Creating with GIMP", 0, 0, 0, 0)
else:
gimp.message("The image could not be opened since it is not an image file.")
except Exception as err:
gimp.message("Unexpected error: " + str(err))
register(
"python_fu_add_flatten_save",
"Add image to layer",
"Add image to layer and flatten.",
"Tim B.",
"Tim B.",
"2021",
"<Image>/Filters/Tim/Add, flatten, save",
"*",
[
(PF_FILE, "file", "File to open", ""),
(PF_INT, "x_offset", "X offset", ""),
(PF_INT, "y_offset", "Y offset", ""),
(PF_DIRNAME, "outputFolder", "Output directory", ""),
],
[],
add_flatten_save)
main()

The fundamental problem is that when you flatten the image, the layer "layer" doesn't exist anymore.
Try adding layer = pdb.gimp_image_get_active_layer(image) before you save.

Related

Gimp python script from current image

I'm trying to get to grips with image manipulation using GIMP and I'm failing at the first hurdle:
With an image loaded in GIMP, I want to run a registered script to run a function - simply rotate the whole image by 90 degrees and then display a message.
#!/usr/bin/env python
import os
import sys
import time
from gimpfu import *
def simple_test():
num = 90
image = gimp.pdb # not sure if this is calling the active image
drawable = pdb.gimp_image_get_active_layer(image)
rotate_it(image, 90)
def rotate_it(image, deg):
msg = "simple_test!! " + str(deg) + "\n"
pdb.gimp_image_rotate(gimp.pdb, num)
gimp.message(msg)
register(
"simple_test",
"A simple Python-Fu plug-in",
"When run this plug-in rotates an image 90 degrees",
"Ghoul Fool",
"Ghoul Fool",
"2020",
"simple test",
"",
[],
[],
simple_test,
menu="<Image>/Filters/simple-test",
)
main()
More importantly is trying to get some error message/log/console output to find out where I'm going wrong - only that doesn't seem to display by default.
it definitely looks like you are calling the current image wrongly. Perhaps this example script can help you out:
#!/usr/bin/env python
# Tutorial available at: https://www.youtube.com/watch?v=nmb-0KcgXzI
# Feedback welcome: jacksonbates#hotmail.com
from gimpfu import *
def hello_warning(image, drawable):
pdb.gimp_message("Hello world!")
register(
"python-fu-hello-warning",
"SHORT DESCRIPTION",
"LONG DESCRIPTION",
"Jackson Bates", "Jackson Bates", "2015",
"Hello warning",
"", # type of image it works on (*, RGB, RGB*, RGBA, GRAY etc...)
[
(PF_IMAGE, "image", "takes current image", None),
(PF_DRAWABLE, "drawable", "Input layer", None)
],
[],
hello_warning, menu="<Image>/File") # second item is menu location
main()
I would also suggest this guy's video series about gimp python fu: https://www.youtube.com/watch?v=nmb-0KcgXzI. Unfortunately, the official documentation (in my opinion) lacks beginner friendliness considering the debugging.
The image is always the first parameter of the function of your plug-in and it will be derived from the context so you don't need it to get it before, as paddy.exe showed your plug-ing should have it as the first argument:
def hello_warning(image, drawable):
pdb.gimp_message("Hello world!")
For getting the image if you want to do some testing using the console you should use:
image = gimp.image_list()[0]

How to change text layer in GIMP?

I have a gimp file that I'm using as a template.
I'm trying to find a way to script something so that I can easily replace the template text in that file to something that I specify.
Cheers
To get you started:
The information of a text layer (text, fonts and other options) is kept in a "parasite". This "parasite" is created when the image is saved (no such parasite on a freshly created text layer). It can be retrieved and the information reused. IMHO it will be easier to recreate a new layer anyway. In Python:
def text_info(img,layer):
parasites=None
try:
parasites=layer.parasite_list()
except Exception as e:
pass;
if parasites and 'gimp-text-layer' in parasites:
data=layer.parasite_find('gimp-text-layer').data
pdb.gimp_message('Text layer "%s": %s' % (layer.name,data))
else:
pdb.gimp_message('No text information found for layer "%s"' % layer.name)
Code lifted from the text-info script/plugin that you'll find here
Text layer "TEXT ...": (text "TEXT\nEXAMPLE")
(font "Roboto Heavy")
(font-size 60)
(font-size-unit pixels)
(antialias yes)
(language "en")
(base-direction ltr)
(color (color-rgb 0 0 0))
(justify center)
(box-mode dynamic)
(box-unit pixels)
(hinting yes)

Batch save all opened files in GIMP .xcf

I have a series of manually edited images and layers in GIMP, each set is in a single tab. All want to save all of them into different .xcf's.
I am aware of some scripts to export them as images (like this one), but I want to save them as .xcf, not export the images. Moreover, I would like to have them in a single folder, so that I can load them all in the future.
Is there any script to do this?
You can save all projects using this code bellow
dirname = “Path of file”
path = “File name”
imgs = gimp.image_list();
num = 0;
for img in imgs:
for layer in img.layers:
fullpath = os.path.join(path, dirname+str(num)+'.xcf');
pdb.gimp_xcf_save(0, img, layer, fullpath, fullpath);
num += 1;
Or, if you can install complete plugin in https://github.com/Tushn/GIMP-Plugins/blob/master/src/saveproject.py
Instructions for install in https://github.com/Tushn/GIMP-Plugins
If you want open all file, so it’s enough that you mark all xcf in directory and enter in GIMP (click right buttom mouse, case your GIMP is not default file).

Can I create a script for GIMP to carry out a number of processes?

I want to process images before I send them to Tesseract for OCR.
For example:
Resize the image
Change the resolution to 300 dpi
Threshold (B&W image)
Sharpen image
How can I automate this process?
I've just put together an answer (https://graphicdesign.stackexchange.com/questions/53919/editing-several-hundred-images-gimp/53965#53965 ) on graphicdesign, which is intended as an GIMP automation primer for people with no programing skills -
it should be nice for understanding Python-fu as well.
On the very same answer, there are links to the official documentation, and one example of how to create a small script. You should them brose GIMP's PDB to findout about the exact proceeds you want.
But, all in all, you can create a Python file like this:
from gimpfu import *
import glob
def auto():
for filename in glob(source_folder + "/*.png"):
img = pdb.gimp_file_load(source_folder + filename, source_folder + filename)
# place the PDB calls to draw on the image before your interation here
#disp = pdb.gimp_display_new(img)
pdb.gimp_image_merge_visible_layers(img, CLIP_TO_IMAGE)
pdb.gimp_file_save(img, img.layers[0], dest_folder + filename, dest_folder + filename)
# pdb.gimp_display_delete(disp)
pdb.gimp_image_delete(img) # drops the image from gimp memory
register("batch_process_for_blah",
"<short dexcription >Batch Process for Bla",
"<Extended description text>",
"author name",
"license text",
"copyright note",
"menu label for plug-in",
"", # image types for which the plug-in apply - "*" for all, blank for plug-in that opens image itself
[(PF_DIRNAME, "source_folder", "Source Folder", None),
(PF_DIRNAME, "dest_folder", "Dest Folder", None)], # input parameters -
[], # output parameters
menu="<Image>/File", # location of the entry on the menus
)
main()
To find the wanted operations inside the for loop, go to Help->Procedure Browser - or better yet, Filters->Python->Console and hit Browse - it is almost the same, but with an "apply" button that makes it easy to test the call, and copy it over to your plug-in code.

How to copy guide lines in The Gimp?

Is it possible to copy guide lines from one image to another?
I need this because I have several images that need exactly the same composition, so I want to use the guide lines for this.
There's no option to select & copy a guide line, so I must add them manually.
It would be nice, if there's a little script-fu script.
Okay, there are some interesting functions I found:
(gimp-image-find-next-guide image index)
(gimp_image_add_hguide image xposition)
(gimp_image_add_vguide image yposition)
(gimp_image_get_guide_orientation image guide)
(gimp_image_get_guide_position image guide)
Thanks in advance!
I'd really like to help you but I'm not sure I understand what you are trying to do. Could you edit the question to provide more details?
At a guess (pending more information) are you looking for something like this?
guide = 0
while guide = gimp_image_find_next_guide (image_1,guide) != 0
position = gimp_image_get_guide_position (image_1,guide)
if gimp_image_get_guide_orientation (image_1,guide) == 0
gimp_image_add_hguide (image_2,position)
else
gimp_image_add_vguide (image_2,position)
Note that this is pseudo-code, since the functions you mentioned seem to be part of an API that is using a syntax other than scheme-ish script fu.
But the first question is what are you trying to accomplish? -- after that we can worry about the details of how.
Having been wanting to learn Gimp Scripts (PythonFu) for a while and requiring this functionality I used the Pseudo code provided by MarkusQ and this handy tutorial https://jacksonbates.wordpress.com/python-fu-gimp-scripting-tutorial-pages/ to create a script to copy guidelines from one image to another.
#!/usr/bin/env python
from gimpfu import *
def CopyGuidelines(image_1, drawable, image_2):
guide = pdb.gimp_image_find_next_guide(image_1, 0)
while guide != 0 :
position = pdb.gimp_image_get_guide_position (image_1,guide)
if pdb.gimp_image_get_guide_orientation (image_1,guide) == 0:
pdb.gimp_image_add_hguide (image_2,position)
else:
pdb.gimp_image_add_vguide (image_2,position)
guide = pdb.gimp_image_find_next_guide (image_1,guide)
register(
"python-fu-CopyGuidelines",
"Copy Guidelines",
"Copy Guidelines from one image to another",
"Anthony", "JustAGuyCoding", "2017",
"Copy Guidelines",
"", # type of image it works on (*, RGB, RGB*, RGBA, GRAY etc...)
[
(PF_IMAGE, "image_1", "takes current image", None),
(PF_DRAWABLE, "drawable", "Input layer", None),
(PF_IMAGE, "image_2", "takes other image", None)
],
[],
CopyGuidelines, menu="<Image>/Tools")
main()
You'll need to copy this in to a CopyGuidelines.py file and put it your Gimp's plugin directory (See Preferences > Folders ) and restart Gimp to see the CopyGuideline option under Tools. Then open up the two images, select the one with the Guidelines and select CopyGuidelines to run the script.

Resources