MagickWand DisplaceCompositeOp incorrect

Post any defects you find in the released or beta versions of the ImageMagick software here. Include the ImageMagick version, OS, and any command-line required to reproduce the problem. Got a patch for a bug? Post it here.
Post Reply
Danack
Posts: 73
Joined: 2013-10-14T10:00:25-07:00
Authentication code: 6789

MagickWand DisplaceCompositeOp incorrect

Post by Danack »

Hi,

It looks like there is a bug when using composite displace through the MagickWand interface. It almost seems as if the 'sign' of the displacement is incorrect.

Two example questions on SO

http://stackoverflow.com/questions/1323 ... -with-mask
http://stackoverflow.com/questions/2602 ... hrough-php

A reproduction of the second question in C and using it's images in the code below. The output is http://i.stack.imgur.com/fiLXj.png rather than the desired output like http://i.stack.imgur.com/QiJ4L.png :

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wand/MagickWand.h>


void ThrowWandException(MagickWand *wand) {
    char *description; 
    ExceptionType severity; 
    description = MagickGetException(wand, &severity); 
    (void) fprintf(stderr,"%s %s %lu %s\n",GetMagickModule(),description); 
    description=(char *) MagickRelinquishMemory(description); 
    exit(-1); 
}


PixelWand *makePixelWand(char *string) {

	PixelWand *pixel_wand;
	pixel_wand = NewPixelWand();

	if (PixelSetColor (pixel_wand, string) == MagickFalse) {
		printf("Failed to set color");
		exit(-1);
	}

	return pixel_wand;
}


int main(int argc,char **argv) {
    
    MagickBooleanType status;
    PixelWand *pixelWand;

    MagickWand *magick_wand_a;
    MagickWand *magick_wand_b;
    MagickWand *magick_wand_c;

    MagickWandGenesis();
    
//    $a = new Imagick('../a.png');
//    $b = new Imagick('../b.png');
//    $c = new Imagick('../c.png');


    magick_wand_a = NewMagickWand();
    status = MagickReadImage(magick_wand_a, "./displaceCompositeA.png");
    if (status == MagickFalse) {
        ThrowWandException(magick_wand_a);
    }
    
    magick_wand_b = NewMagickWand();
    status = MagickReadImage(magick_wand_b, "./displaceCompositeB.png");
    if (status == MagickFalse) {
        ThrowWandException(magick_wand_b);
    }
        
        
    magick_wand_c = NewMagickWand();
    status = MagickReadImage(magick_wand_c, "./displaceCompositeC.png");
    if (status == MagickFalse) {
        ThrowWandException(magick_wand_c);
    }

    // $a->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_TRANSPARENT);
    MagickSetImageVirtualPixelMethod(magick_wand_a, TransparentVirtualPixelMethod);


    // $a->setImageBackgroundColor(new ImagickPixel('none'));
    pixelWand = makePixelWand("none");
    status = MagickSetImageBackgroundColor(magick_wand_a, pixelWand);

    //    $a->setOption('compose:args', '300x53.033');
    MagickSetOption(magick_wand_a, "compose:args", "300x53.033");

    // $a->compositeImage($c, Imagick::COMPOSITE_DSTIN, 0, 0, Imagick::CHANNEL_ALPHA);
    // "COMPOSITE_DSTIN", DstInCompositeOp);
    status = MagickCompositeImageChannel(magick_wand_a, AlphaChannel, magick_wand_c, DstInCompositeOp, 0, 0);
    if (status == MagickFalse) {
        printf("Failed to composite image b");
        exit(-1); 
    }

    // $a->compositeImage($b, Imagick::COMPOSITE_DISPLACE, 0, 0);
    // "COMPOSITE_DISPLACE", DisplaceCompositeOp);
    status = MagickCompositeImage(magick_wand_a, magick_wand_b, DisplaceCompositeOp, 0, 0);
    if (status == MagickFalse) {
        printf("Failed to composite image b");
        exit(-1); 
    }
    
      
    status = MagickWriteImages(magick_wand_a, "displaceOutput.png", MagickTrue);

    // magick_wand = DestroyMagickWand(magick_wand);
    MagickWandTerminus();
    
    printf("Finished - please compare displaceOutput.png with the result of:\n\n");
    
    printf("convert ./displaceCompositeA.png ./displaceCompositeB.png ./displaceCompositeC.png  -virtual-pixel transparent -channel rgba -alpha on -background transparent -define compose:args=300x53.033 -compose displace -composite ./displaceFinal.png\n");
    
    
    return(0);
}


snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: MagickWand DisplaceCompositeOp incorrect

Post by snibgo »

Displacing at the command line needs one or two masks. Using two masks, the command on StackOverflow is correct. Windows BAT syntax:

Code: Select all

convert ^
  compa.png ^
  compb.png ^
  compc.png ^
  -virtual-pixel transparent ^
  -channel rgba -alpha on -background transparent ^
  -define compose:args=300x53.033 ^
  -compose displace -composite ^
  final.png
The two masks can be combined into one. For this, use "-combine", not DstIn:

Code: Select all

convert ^
  compb.png ^
  compc.png ^
  +clone ^
  -combine ^
  mask2.png

convert ^
  compa.png ^
  mask2.png ^
  -virtual-pixel transparent ^
  -channel rgba -alpha on -background transparent ^
  -define compose:args=300x53.033 ^
  -compose displace -composite ^
  final2.png
Hope this helps.
snibgo's IM pages: im.snibgo.com
Danack
Posts: 73
Joined: 2013-10-14T10:00:25-07:00
Authentication code: 6789

Re: MagickWand DisplaceCompositeOp incorrect

Post by Danack »

> Hope this helps.

Erm - not really.

To be clear, the issue is that the result of the image generated programatically through the MagickWand functions is not the same as the result generated from the equivalent command line version, which doesn't seem to be addressed by your answer.
marcospassos
Posts: 13
Joined: 2014-09-26T08:23:47-07:00
Authentication code: 6789

Re: MagickWand DisplaceCompositeOp incorrect

Post by marcospassos »

I can reproduce this bug using:

Code: Select all

Version: ImageMagick 6.8.9-7 Q16 x86_64 2014-09-24 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2014 ImageMagick Studio LLC
Features: DPC Modules
Delegates: bzlib freetype jng jpeg lcms ltdl lzma png tiff xml zlib
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: MagickWand DisplaceCompositeOp incorrect

Post by snibgo »

Danack wrote:... the image generated programatically through the MagickWand functions is not the same as the result generated from the equivalent command line version ...
But they are not equivalent. Your MagickWand code does a composite with DstIn. The command line doesn't, because it would be wrong.
snibgo's IM pages: im.snibgo.com
Post Reply