Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Gimp Python script file load question
#1
I have a working Gimp plugin that takes an open XCF, adds a new layer to it, positions the new layer, and then exports a JPG. 

However, the plugin only works if I'm in the Gimp UI and the XCF file is already open. I want to run it from the command line and some how call pdb.gimp_xcf_load somewhere top open the XCF, but I can't get the file open or command line to work. 

What is the best way to do this? Should I have a wrapper script that opens the XCF and then calls my working script?  Or can I both open the XCF and the JPEG in a single plugin? Is there a best practice?
Reply
#2
Is this the same plugin that I answered a question about on Stackoverflow?: https://stackoverflow.com/questions/6664...n-combined

If not, can you post the code you have so far. It should certainly be possible to do what you ask.
Reply
#3
Hi Kevin. Yes that is me. My latest plugin is shown below. Everything works in the GIMP UI, but when I add my call for pdb.gimp_xcf_load(0, infileA, infileA) and introduce infileA into the definition and parameters, it fails. 

I think there may be a problem because the image object isn't explicitly linked to my XCF or JPG. It would be great to avoid a file wrapper for opening the XCF, but if I need to I understand. 

Below is my command line calls (two options I tried) and my plugin. These are the errors I get when I use these command line calls:

First command line call: "Error: eval: unbound variable: open_add_flatten_export"

Second command line call:

GIMP-Error: Failed to save data:

You have a writable data folder configured (/Users/TBradley/Library/Application Support/GIMP/2.10/gradients), but this folder does not exist. Please create the folder or fix your configuration in the Preferences dialog's 'Folders' section.

/Applications/GIMP-2.10.app/Contents/MacOS/gimp: GEGL-WARNING: (../../../../gtk/source/gegl-0.4.26/gegl/buffer/gegl-tile-handler-cache.c:1076):gegl_tile_cache_destroy: runtime check failed: (g_queue_is_empty (&cache_queue))
EEEEeEeek! 9 GeglBuffers leaked
To debug GeglBuffer leaks, set the environment variable GEGL_DEBUG to "buffer-alloc"

Quote:First command line call:

gimp -i -b '(open_add_flatten_export "/Users/TimB/Desktop/xcf_template.xcf" "/Users/TimB/Desktop/jpg_to_add.jpg" "2060" "410" "/Users/TimB/Desktop")' -b '(gimp-quit 0)'


Second command line call: 

gimp -i --batch-interpreter python-fu-eval -b pdb.python_fu_open_add_flatten_export "/Users/TimB/Desktop/xcf_template.xcf" "/Users/TimB/Desktop/jpg_to_add.jpg" "2060" "410" "/Users/TimB/desktop" -b 'pdb.gimp_quit(0)'


Here's my plugin:

Code:
#!/usr/bin/env python

from gimpfu import *

def open_add_flatten_export(image, layer, infileA, infileB, x_offset, y_offset, outputFolder):
 
   # Open XCF template
   pdb.gimp_xcf_load(0, infileA, infileA)

   try:
       # Open file.
       fileImage = None

       if(infileB.lower().endswith(('.jpeg', '.jpg'))):
           fileImage = pdb.file_jpeg_load(infileB, infileB)

           # 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
           layer = pdb.gimp_image_get_active_layer(image)
           pdb.file_jpeg_save(image, layer, outputFolder + "/" + "export.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_open_add_flatten_export",
   "Open XCF, add image to layer, flatten, and export",
   "Open XCF, add image to layer, flatten, and export",
   "Tim B.",
   "Tim B.",
   "2021",
   "<Image>/Filters/Tim/Open, add, flatten, export",
   "*",
   [
       (PF_FILE, "infileA", "XCF template", ""),
       (PF_FILE, "infileB", "JPG to add", ""),
       (PF_INT, "x_offset", "X offset", ""),
       (PF_INT, "y_offset", "Y offset", ""),
       (PF_DIRNAME, "outputFolder", "Output directory", ""),
   ],
   [],
   open_add_flatten_export)

main()
Reply
#4
You have a mismatch between your command line and the code AND internally in the code.

The command line is trying to call open_add_flatten_save and the code is defining open_add_flatten_export

And in the register block you have the parameters infileA infileB x_offset y_offset outputFolder BUT the definition of the function is
image, layer, infileA, infileB, x_offset, y_offset, outputFolder


Also, you need assign image = pdb.gimp_xcf_load(infileA, infileA) and then find the active layer in image

As you're on MacOS, I can't be sure what your command line should look like, but Ofnuts will be along later to tell you what it needs to look like.
Reply
#5
Btw, if you areusing the script only in batch, there is no need to register it as a plugin.

See https://stackoverflow.com/questions/4443...0#44435560
Reply
#6
(03-18-2021, 05:30 PM)Ofnuts Wrote: Btw, if you areusing the script only in batch, there is no need to register it as a plugin.

See https://stackoverflow.com/questions/4443...0#44435560

Thanks guys. I didn't realize you had responded and I fixed some things in my initial post (including the mismatch) and also tried a different command line call before seeing your responses. 

I will remove the definition and also assign image as Kevin suggests and I'll report back.
Reply
#7
(03-18-2021, 05:40 PM)TimorousMe Wrote:
(03-18-2021, 05:30 PM)Ofnuts Wrote: Btw, if you areusing the script only in batch, there is no need to register it as a plugin.

See https://stackoverflow.com/questions/4443...0#44435560

Thanks guys. I didn't realize you had responded and I fixed some things in my initial post (including the mismatch) and also tried a different command line call before seeing your responses. 

I will remove the definition and also assign image as Kevin suggests and I'll report back.

I removed the definition part of my plugin as Ofnuts suggested, and then added the import language from the Stack Overflow post (as I cannot just call the function name now because it's not registered). I also followed Kevin's suggestion by assigning image = pdb.gimp_xcf_load(infileA, infileA) and then finding the active layer in image. The command line fails with the response below. 

Plugin (renamed batch.py for simplicity)
Code:
#!/usr/bin/env python

import sys
from gimpfu import *

def open_add_flatten_export(infileA, infileB, x_offset, y_offset, outputFolder):
 
   # Open XCF template
   image = pdb.gimp_xcf_load(0, infileA, infileA)
   layer = pdb.gimp_image_get_active_layer(image)

   try:
       # Open file.
       fileImage = None

       if(infileB.lower().endswith(('.jpeg', '.jpg'))):
           fileImage = pdb.file_jpeg_load(infileB, infileB)

           # Create new layer.
           newLayer = gimp.Layer(image, "Added JPG", 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
           layer = pdb.gimp_image_get_active_layer(image)
           pdb.file_jpeg_save(image, layer, outputFolder + "/" + "export.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))

Command line command + arguments (modeled after Stack Overflow post)

Code:
gimp -idf --batch-interpreter python-fu-eval -b 'import sys;sys.path=['.']+sys.path;import batch;batch.run("/Users/TimB/Desktop/xcf_template.xcf" "/Users/TimB/Desktop/jpg_to_add.jpg" "2060" "410" "/Users/TimB/desktop")' -b 'pdb.gimp_quit(1)'

Response from command line:

Quote:GIMP is started as MacOS application
2021-03-18 21:10:18.605 gimp[2940:40051] *** WARNING: Method userSpaceScaleFactor in class NSView is deprecated on 10.7 and later. It should not be used in new applications. Use convertRectToBacking: instead. 
/Applications/GIMP-2.10.app/Contents/MacOS/gimp: LibGimpBase-WARNING: gimp: gimp_wire_read(): error
gimp_check_updates_callback: loading of https://www.gimp.org/gimp_versions.json failed: Operation not supported
Traceback (most recent call last):
  File "/Applications/GIMP-2.10.app/Contents/Resources/lib/gimp/2.0/python/gimpfu.py", line 827, in _run
    return apply(func, params[1:])
  File "/Applications/GIMP-2.10.app/Contents/Resources/lib/gimp/2.0/plug-ins/python-eval.py", line 25, in code_eval
    exec code in globals()
  File "<string>", line 1, in <module>
AttributeError: 'module' object has no attribute 'run'
batch command experienced an execution error
GIMP-Error: Failed to save data:

You have a writable data folder configured (/Users/TimB/Library/Application Support/GIMP/2.10/gradients), but this folder does not exist. Please create the folder or fix your configuration in the Preferences dialog's 'Folders' section.
Reply
#8
  • Your code doesn't define a run function but a open_add_flatten_export() one.
  • I don't know how numeric arguments (your X, Y positions) are passed, you may receive them as string and have to explicitly convert them to int before using them.
  • Not convinced that your copy/paste is going to work as it is, you are using plenty of calls that I have never used and they likely don't do what you think. The best way to copy a layer between the two images is to do a layer_copy = pdb.gimp_layer_new_from_drawable(fileImage.active_layer, image), and then do  pdb.gimp_image_add_layer(image, layer_copy,1)
Reply
#9
(03-19-2021, 08:18 AM)Ofnuts Wrote:
  • Your code doesn't define a run function but a open_add_flatten_export() one.
  • I don't know how numeric arguments (your X, Y positions) are passed, you may receive them as string and have to explicitly convert them to int before using them.
  • Not convinced that your copy/paste is going to work as it is, you are using plenty of calls that I have never used and they likely don't do what you think. The best way to copy a layer between the two images is to do a layer_copy = pdb.gimp_layer_new_from_drawable(fileImage.active_layer, image), and then do  pdb.gimp_image_add_layer(image, layer_copy,1)

Great advice from Ofnuts. It simplified my code (which I tested in the UI minus the file operation and it works great). My failure is either occuring because of how I try to open the XCF, or how I'm passing command line args. The command line seems to think it's getting 1 argument even though all 5 are listed. I tried other syntaxes, like comma delimited, semi-colon delimited, etc. Can you guys think of anything else to try?

Command line output:
Code:
Traceback (most recent call last):
 File "/Applications/GIMP-2.10.app/Contents/Resources/lib/gimp/2.0/python/gimpfu.py", line 827, in _run
   return apply(func, params[1:])
 File "/Applications/GIMP-2.10.app/Contents/Resources/lib/gimp/2.0/plug-ins/python-eval.py", line 25, in code_eval
   exec code in globals()
 File "<string>", line 1, in <module>
TypeError: open_add_flatten_export() takes exactly 5 arguments (1 given)
batch command experienced an execution error
GIMP-Error: Failed to save data:


Command line arguments:
Code:
gimp -idf --batch-interpreter python-fu-eval -b 'import sys;sys.path=["."]+sys.path;import OAFE;OAFE.open_add_flatten_export("/Users/TimB/Desktop/xcftemplate.xcf" "/Users/TimB/Desktop/jpg_to_add.jpg" "2060" "410" "/Users/TimB/desktop")' -b 'pdb.gimp_quit(1)'


Plugin without definition, which I'm not using here. Filename is OAFE.py
Code:
#!/usr/bin/env python

import os, sys
from gimpfu import *

def open_add_flatten_export(infileXCF, infileJPG, x_offset, y_offset, outputFolder):
   
   # Open XCF template
   image = pdb.gimp_xcf_load(infileXCF, infileXCF)
   drawable = pdb.gimp_image_get_active_layer(image)

   # Load new JPG, and copy its contents into "layer_copy"
   fileImage = None
   fileImage = pdb.file_jpeg_load(infileJPG, infileJPG)
   layer_copy = pdb.gimp_layer_new_from_drawable(fileImage.active_layer, image)
           
   # Add layer_copy to XCF template, move it to desired position, and flatten
   pdb.gimp_image_add_layer(image, layer_copy, 1)
   pdb.gimp_layer_set_offsets(layer_copy, x_offset, y_offset)
   pdb.gimp_image_flatten(image)

   # Export JPG of flattened image
   layer = pdb.gimp_image_get_active_layer(image)
   pdb.file_jpeg_save(image, layer, outputFolder + "/" + "Export.jpg", "raw_filename", 0.9, 0, 0, 0, "Creating with GIMP", 0, 0, 0, 0)
Reply
#10
Code:
OAFE.open_add_flatten_export("/Users/TimB/Desktop/xcftemplate.xcf" "/Users/TimB/Desktop/jpg_to_add.jpg" "2060" "410" "/Users/TimB/desktop")

This is indeed a single argument. If you want several arguments, you have to use commas (remember that everything between the single quotes is actually python source code, not shell code. Also if you put quotes around your number, they will be string args. Without quotes, they are likely to be the integers you need.

Code:
OAFE.open_add_flatten_export("/Users/TimB/Desktop/xcftemplate.xcf", "/Users/TimB/Desktop/jpg_to_add.jpg", 2060, 410, "/Users/TimB/desktop")
Reply


Forum Jump: