pythonwand

Unable to recreate python wand composite command in wand which works in imagemagick composite


I am trying to composite a small overlay image in middle of screen vertically, but at a fixed position down from top.

It works fine with imagemagick

base.png

over.png

composite --version
Version: ImageMagick 6.9.13-12 Q16 x86_64 18420 https://legacy.imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC Modules OpenMP(4.5) 
Delegates (built-in): bzlib djvu fftw fontconfig freetype heic jbig jng jp2 jpeg lcms lqr ltdl lzma openexr pangocairo png raw tiff webp wmf x xml zlib


composite -gravity north -geometry +0+50  over.png base.png output.png

then it works and i get an image like following

composite

However, if i try it in wand, my code looks like

pip list | grep Wand
Wand    0.6.13

def main():
    with Image(filename ="over.png") as o:
        original = o.clone()

    with Image(filename ="base.png") as b:
        base = b.clone()

    base.composite( operator="over", image=original, gravity='north', arguments="+0+50")

    final = base.clone()
    final.save(filename='output.png')

The geometry in arguments is simply ignored, and the overlay is north, without any offset.

overlay bad

i have read extensively the imagemagick, wand documentation and tried to read the wand code, or find examples online of people using it, but i am not clearer why imagemagick is not picking up the geometry arguments.


Solution

  • This works in Python Wand 0.6.13

    But see the error message when gravity='north' is added.

    So do the following to compute the offset equivalent to gravity=north:

    #!/bin/python3.12.9
    
    from wand.image import Image
    from wand.display import display
    
    
    # adding gravity produces the following error message:
    # TypeError: Can not use gravity if top & left are given
    # So do the following
    
    with Image(filename='green.png') as bimg:
        bwidth = bimg.width
        with Image(filename='red.png') as fimg:
            fwidth = fimg.width
            xoff = int((bwidth - fwidth)/2)
            bimg.composite_channel('all_channels', fimg, 'over', xoff, 50)
            bimg.save(filename='red_over_green_composite1.png')
            display(bimg)
    
    # OR
    
    with Image(filename='green.png') as bimg2:
        bwidth2 = bimg2.width
        with Image(filename='red.png') as fimg2:
            fwidth2 = fimg2.width
            xoff2 = int((bwidth2 - fwidth2)/2)
            bimg2.composite_channel('all_channels', fimg2, operator='over', left=xoff2, top=50)
            bimg2.save(filename='red_over_green_composite2.png')
            display(bimg2)
    
    
    Results from either:
    

    enter image description here

    ADDITION

    Courtesy of Eric McConville:

    "There's a secret hidden method for calculating gravity.
    `BaseImage._gravity_to_offset(gravity, width, height)`
    The documentation software will not show any methods
    that start with a `_` underscore, but we can still use it."

    #!/bin/python3.12.9
    
    from wand.image import Image
    from wand.display import display
    
    
    # adding gravity produces the following error message:
    # TypeError: Can not use gravity if top & left are given
    # So do the following using hidden ._gravity_to_offset to compute offsets
    
    with Image(filename='green.png') as bimg:
        with Image(filename='red.png') as fimg:
            xoff = 0
            yoff = 50
            t, l = bimg._gravity_to_offset('north', fimg.width, fimg.height)
            bimg.composite(
                operator='over', 
                image=fimg, 
                left=l+xoff, 
                top=t+yoff
                )
            bimg.save(filename='red_over_green_composite1.png')
            display(bimg)