Page 1 of 1

MagicWand ImageComposite Question

Posted: 2016-06-13T16:52:57-07:00
by harry.whitehouse
I have what should be a simple mission to draw B&W labels. I've been successful drawing lines and annotating with text using the API. Now I'd like to drop one or more arbitrary images on my canvas and the ImageComposite() call is throwing exceptions like this:

ComposeImage: MagickCore/composite.c:559: CompositeImage: Assertion `image->signature == 0xabacadabUL' failed.

I'm suspicious that I have to cast (Image *) in the CompositeImage call and that leads me to belive I may be passing the wrong objects. And perhaps I should be using another API call instead.

Can anyone offer me some guidance?

Code: Select all

void test_wand(void)
{
	MagickWand *mw = NULL;
	PixelWand *c_wand = NULL;
       DrawingWand *d_wand = NULL;

	MagickWandGenesis();

	/* Create a wand */
	mw = NewMagickWand();
	d_wand = NewDrawingWand();
	c_wand = NewPixelWand();

	// create a new canvas
	PixelSetColor(c_wand,"white");
	MagickNewImage(mw, 1000,1000, c_wand);
	DrawSetStrokeOpacity(d_wand,1);
	
	// Draw a line on the canvas
	PixelSetColor(c_wand,"rgb(0,0,1)");
       DrawSetFillColor(d_wand,c_wand);
       DrawSetStrokeWidth(d_wand,3);
       DrawLine(d_wand, 10, 10, 300, 300);
    
    MagickDrawImage(mw,d_wand);

	/* Read an external image */
    MagickWand *mw2 = NewMagickWand();
	MagickReadImage(mw2,"logo:");
	 	
	CompositeOperator MyOp= OverCompositeOp;	
	CompositeImage((Image *) mw, MyOp, (Image *) mw2, 10, 10);
	
	/* write it */
	[quote][/quote]MagickWriteImage(mw,"logo.jpg");

	/* Tidy up */
	if(mw) mw = DestroyMagickWand(mw);

	MagickWandTerminus();
	
	
} 

Re: MagicWand ImageComposite Question

Posted: 2016-06-13T17:45:59-07:00
by snibgo
A wand isn't an image. An image isn't a wand. A wand does contain images. The wand structure contains an element called "image" or something similar, which points to the first image in a list.

"CompositeImage" is a MagickCore function. At the MagickWand level, the function you want is probably MagickCompositeImage(), but I don't use Wand much, so don't quote me on that.

Re: MagicWand ImageComposite Question

Posted: 2016-06-14T17:08:34-07:00
by harry.whitehouse
Thank you Shibgo!! You helped me get back on track!

I've modified my code to call the Magick version of composite. I have one wand with a hand drawn image with a white background and a single diagonal line. I have a second wand where I read in the IM logo (the wizard!). You'll note that I tried both a composite and merge.

COMPOSITE.PNG just shows the 1000x1000 white background with the line. The MERGED.PNG just shows our wizard friend in 640 x 480 with no sign of the line or white background.

I'm sure I'm stuck on a newbie mistake. I simply want to be able to position images at various positions on a white canvas. I don't need any fancy effects -- it's really a simple drawing mission.

Any further thoughts?

Code: Select all

MagickWand *mw = NULL;
	PixelWand *c_wand = NULL;
    DrawingWand *d_wand = NULL;

	MagickWandGenesis();

	/* Create a wand */
	mw = NewMagickWand();
	d_wand = NewDrawingWand();
	c_wand = NewPixelWand();

	// create a new canvas
	PixelSetColor(c_wand,"white");
	MagickNewImage(mw, 1000,1000, c_wand);
	DrawSetStrokeOpacity(d_wand,1);
	
	// Draw a line on the canvas
	PixelSetColor(c_wand,"rgb(0,0,1)");
    DrawSetFillColor(d_wand,c_wand);
    DrawSetStrokeWidth(d_wand,3);
    DrawLine(d_wand, 10, 10, 900, 900);
    int w1 = MagickGetImageWidth(mw);
	int h1 = MagickGetImageHeight(mw);
	printf("Image width and height for w1 = %d %d\n",w1,h1);
    
    MagickDrawImage(mw,d_wand);
    MagickSetImageFilename(mw,"Base Canvas");
    printf("Image 1 file name is %s\n",MagickGetImageFilename(mw));
    
	/* Read an external image */
    MagickWand *mw2 = NewMagickWand();
	MagickReadImage(mw2,"logo:");
	int w2 = MagickGetImageWidth(mw2);
	int h2 = MagickGetImageHeight(mw2);
	printf("Image 2 file name is %s\n",MagickGetImageFilename(mw2));
	printf("Image width and height for w2 = %d %d\n",w2,h2);	
		
	CompositeOperator MyOp= OverCompositeOp;	
	MagickCompositeImage(mw, mw2, MyOp, 10, 10);
	                		
	/* write it */
	MagickSetImageFormat(mw, "PNG");
	MagickWriteImage(mw,"composite.png");
	
    MagickAddImage(mw, mw2);
    MagickWand *merged = MagickMergeImageLayers(mw, MergeLayer);
    MagickSetImageFormat(merged, "PNG");
    MagickWriteImage(merged, "merged.png");

	/* Tidy up */
	if(mw) mw = DestroyMagickWand(mw);
    if(mw2) mw2 = DestroyMagickWand(mw2);
	MagickWandTerminus();

Re: MagicWand ImageComposite Question

Posted: 2016-06-14T18:11:36-07:00
by snibgo
You might prefer "DrawSetStrokeColor(d_wand,c_wand)" to "DrawSetFillColor(d_wand,c_wand)".

As the logo image is mostly white, I suggest you make your line image anything other than white, say, "pink". This may help you see what is happening.

MagickMergeImageLayers merges layers (as the in-code documentation in magick-image.c says) from the current image onwards. After you have added an image, which image is the current image? Answer: the last one, so merging doesn't do much. You need MagickSetFirstIterator(mw) or similar before the merge.

Re: MagicWand ImageComposite Question

Posted: 2016-06-14T21:14:34-07:00
by harry.whitehouse
That was it Shibgo!!! Here's a few of the lines modified as per your instructions. I also tried resizing and repositioning which both worked well!

Code: Select all

MagickReadImage(mw2,"logo:");
	int w2 = MagickGetImageWidth(mw2);
	int h2 = MagickGetImageHeight(mw2);
	printf("Image 2 file name is %s\n",MagickGetImageFilename(mw2));
	printf("Image width and height for w2 = %d %d\n",w2,h2);
	MagickResizeImage(mw2, h2 * 0.80, w2 * 0.60, LanczosFilter, 1.0);
	//PixelSetColor(c_wand,"white");
	//MagickRotateImage(mw2, c_wand,45.0);
	long unsigned int width, height;
	long int x, y;
	MagickGetImagePage(mw2, &width, &height, &x, &y);
	printf("width %lu height %lu x %ld  y %ld\n",width, height, x, y);
	MagickSetImagePage(mw2,width,height,500,500);	

    MagickAddImage(mw, mw2);
    MagickSetFirstIterator(mw);
    MagickWand *merged = MagickMergeImageLayers(mw, MergeLayer);
    MagickSetImageFormat(merged, "PNG");   
    MagickWriteImage(merged, "merged.png");
Many, many thanks for your help!!!

Harry