GIMP newly adder RGBA layer in Python-Fu, trouble getting new layer added behind source image to be transparent

38 views Asked by At

I have several images that I'm trying to use GIMP Python-Fu to process. What I am trying to do is:

  1. open a *.png with transparency
  2. create a new layer that is transparent and inject it below the existing image
  3. copy the contents of my original layer and paste them into the new one
  4. desaturate the copy and set its lightness to 0
    • Desired effect: get a 100% black effect of the original image, to be a shadow
    • Hue-Chroma was my manual approach, but that appears to be missing from GIMP's Procedures
  5. adjust the background shadow layer so that it is offset by an X and Y amount
  6. Set the alpha/opacity for the shadow to be 50% transparent
  7. render these layers
  8. Persist to a new location

I think that I have the general gist down, but I am stuck with new layers, even those created as RGBA, always having the background color currently set in GIMP. When I flatten these two layers, the resultant *.PNG is filled with the background color rather than transparency that I would expect given the corresponding behaviors from the GIMP UI.

Here is what I have:

import os, glob, sys, time
from gimpfu import *
import gimpcolor

def ie_inventory_shadow(file, x_offset, y_offset, outputFolder):
    #Open the file; size to 64x64; duplicate layer; make black; offset 4, 5; set opacity to 50%; save to output

    print "Opening '" + file + "' ..."

    # Indicates that the process has started.
    gimp.progress_init("Opening '" + file + "' ...")

    try:
        filename = os.path.basename(file)
        # Use slicing to remove the extension
        filename_without_ext = filename[:filename.rindex('.')]


        # Open file.
        fileImage = None
        fileImage = pdb.gimp_file_load(file, file, run_mode=RUN_NONINTERACTIVE)
        print "Opened '" + filename_without_ext + "' ..."

        #resize
        pdb.gimp_context_set_interpolation(2) #INTERPOLATION-CUBIC (2)
        pdb.gimp_image_scale(fileImage, 64, 64)
        layer = fileImage.layers[0]
        print "Resized '" + filename_without_ext + "' ..."

        # Create new layer.
        pdb.gimp_context_set_background((0,255,0))
        #newLayer = pdb.gimp_layer_new(fileImage, layer.width, layer.height, RGBA_IMAGE, "Shadow", layer.opacity, layer.mode) #RGBA-IMAGE (1)
        #pdb.gimp_layer_add_alpha(newLayer)
        #pdb.gimp_drawable_fill(newLayer, 3) #FILL-TRANSPARENT (3)
        pdb.gimp_layer_new_from_visible(fileImage, fileImage, "shadow")
        print "Created New Layer for '" + filename_without_ext + "' ..."
        pdb.gimp_image_insert_layer(fileImage, newLayer, None, +1) # the +1 adds it behind the top layer
        #pdb.gimp_edit_clear(newLayer)
        ##### Fuck my life. The new layer ALWAYS has the background color. But I simply CANNOT figure out how to make this motherfucker transparent.
        print "Inserted New Layer for '" + filename_without_ext + "' ..."

        # Put image into the new layer.
        pdb.gimp_edit_copy(layer)
        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)
        # floating to layer
        pdb.gimp_floating_sel_to_layer(floating)
        print "Duplicated '" + filename_without_ext + "' ..."

        #make layer black
        pdb.gimp_brightness_contrast(newLayer, -127, 127)
        print "Shadowed '" + filename_without_ext + "' ..."

        #move the layer
        pdb.gimp_layer_set_offsets(newLayer, x_offset, y_offset)
        print "Moved '" + filename_without_ext + "' ..."

        #set opacity
        pdb.gimp_layer_set_opacity(newLayer, 50)
        print "Set Opacity on '" + filename_without_ext + "' ..."

        #flatten
        flattened = pdb.gimp_image_flatten(fileImage)
        print "Flattened '" + filename_without_ext + "' ..."

        # Export flattened image
        target = outputFolder + "/" + filename_without_ext + "-s.png"
        print "Saving '" + target + "' ..."
        pdb.file_png_save_defaults(fileImage, flattened, target, target, run_mode=RUN_NONINTERACTIVE)
        #pdb.file_png_save2(fileImage, flattened, target, target, False, 9, True, False, False, True, True, False, False, run_mode=RUN_NONINTERACTIVE)
        print "Saved '" + target + "'!"


    except Exception as err:
        gimp.message("Unexpected error: " + str(err))



def run(directory, x_offset, y_offset, outputFolder):
        print "Run: directory : %s" % directory
        print "Run: outputFolder : %s" % outputFolder
        print "Run: x_offset : %s" % x_offset
        print "Run: y_offset : %s" % y_offset

        start=time.time()
        print "Run: Running on directory \"%s\"" % directory
        globPath = os.path.join(directory, '*.png')

        print "looking at path: %s" % globPath

        for infile in glob.glob(globPath):
                print "Run: found file : %s" % infile
                ie_inventory_shadow(infile, x_offset, y_offset, outputFolder)
        end=time.time()
        print "Finished, total processing time: %.2f seconds" % (end-start)


if __name__ == "__main__":
        print "Running as __main__ with args: %s" % sys.argv
1

There are 1 answers

0
Erik Frantz On

I spend 2 days banging my head against this problem, and found it just minutes after posting...

The problem was the flatten call. The documentation states that flatten will remove the alpha channel:

gimp-image-flatten

[...]

Non-visible layers are discarded, and the resulting image is stripped of its alpha channel.

The solution was to instead use gimp_image_merge_visible_layers:

 #flattened = pdb.gimp_image_flatten(fileImage) # Unintended result
 merged = pdb.gimp_image_merge_visible_layers(fileImage, 0) #EXPAND-AS-NECESSARY (0)