1

I have a two images And I want to combine them together, similar command for this is convert one.png two.png +clone -combine displaceMask.png. Below is my C Code. I'm not getting the perfect result using C.

#include <stdio.h>
#include "MagickWand/MagickWand.h"
int main(int argc, const char * argv[]) {

  MagickWand *wand1, *wand2, *wand3;

  wand1 = NewMagickWand();
  wand2 = NewMagickWand();
  wand3 = NewMagickWand();

  MagickReadImage(wand1, "one.png");
  MagickReadImage(wand2, "two.png");

  // convert one.png two.png +clone -combine displaceMask.png
  wand3 = CloneMagickWand(wand2);
  MagickAddImage(wand1, wand2);
  MagickAddImage(wand1, wand3);
  MagickCombineImages(wand1,RGBColorspace);
  MagickWriteImage(wand1,"merge.png");

  if(wand1)wand1 = DestroyMagickWand(wand1);
  if(wand2)wand2 = DestroyMagickWand(wand2);
  if(wand3)wand3 = DestroyMagickWand(wand3);
  MagickWandTerminus();

  return 0;
}

These are the images.

one.png

enter image description here two.png

enter image description here finalResultUsingCMd.png

enter image description here

merge.png (This image I'm getting using C code. But I want a above image.) enter image description here

Rahul
  • 1,013
  • 1
  • 10
  • 24
  • Please edit your question to included the expected result or describe how the actual result you have shown is not what you require. – Toby Apr 25 '17 at 13:01
  • 1
    finalResultUsingCMd.png image is the final result I want. Using command I get the image not using C program. – Rahul Apr 25 '17 at 13:07

1 Answers1

1

Updated Answer

In addition to capturing combine results, you'll need to reset the wand iterator before applying the MagickCombineImages. This is because each time you invoke MagickAddImage the internal linked list is pointing to the newly added node. (Hope I explained that clearly.)

Quoting some documents...

After using any images added to the wand using MagickAddImage() or MagickReadImage() will be prepended before any image in the wand.

Also the current image has been set to the first image (if any) in the Magick Wand. Using MagickNextImage() will then set teh current image to the second image in the list (if present).

This operation is similar to MagickResetIterator() but differs in how MagickAddImage(), MagickReadImage(), and MagickNextImage() behaves afterward.

So your example code should look like ...

#include "MagickWand/MagickWand.h"
int main(int argc, const char * argv[]) {

  MagickWand
      *wand1,
      *wand2,
      *wand3,
      *result;

  wand1 = NewMagickWand();
  wand2 = NewMagickWand();

  MagickReadImage(wand1, "one.png");
  MagickReadImage(wand2, "two.png");

  // convert one.png two.png +clone -combine displaceMask.png
  wand3 = CloneMagickWand(wand2);
  MagickAddImage(wand1, wand2);
  MagickAddImage(wand1, wand3);
  MagickSetFirstIterator(wand1);
  result = MagickCombineImages(wand1, MagickGetImageColorspace(wand1));
  MagickWriteImage(result,"merge.png");

  wand1 = DestroyMagickWand(wand1);
  wand2 = DestroyMagickWand(wand2);
  wand3 = DestroyMagickWand(wand3);
  result = DestroyMagickWand(result);
  MagickWandTerminus();

  return 0;
}

copy of merge.png

Original Answer

The MagickCombineImages method should return a pointer MagickWand * containing the result of the combine action. The behavior of this method has changed between version of IM 6 & IM 7, so it's more than possible that a bug exists, or implementation has adjusted. I'm not around IM 7 to verify at the moment, but here's a work around.

// convert one.png two.png +clone -combine displaceMask.png
wand3 = CloneMagickWand(wand2);
MagickCompositeImage(wand1, wand2, CopyGreenCompositeOp, MagickTrue, 0, 0);
MagickCompositeImage(wand1, wand3, CopyBlueCompositeOp,  MagickTrue, 0, 0);
MagickWriteImage(wand1, "merge.png");

merge.png

emcconville
  • 23,800
  • 4
  • 50
  • 66
  • Hello @emcconville, both solution works perfectly. I understood the first approach. Could you explain a bit about second approach? And which one you recommend? – Rahul Apr 26 '17 at 05:02
  • 1
    The composite solution replaces dst color channel by copying src data. This works as expected because your example images are already grayscale images. The combine method would be preferred as it will actually calculate / resolve gray values & apply to all channels w/ respecting color traits – emcconville Apr 26 '17 at 12:20
  • one quick question. Why SetImageGravity is not working with crop? To make it work, I passed the X and Y coordinates in crop function. – Rahul Apr 27 '17 at 11:48
  • 1
    Remember your writing an application in a high level language. You are responsible for handling the math, and don't assume that all behavioral short-cuts from the CLI application apply. I would recommend reading the source code to see how Cristy design the architecture. – emcconville Apr 27 '17 at 12:43