How can I fill a primitive with an image using DrawingWand

Questions and postings pertaining to the development of ImageMagick, feature enhancements, and ImageMagick internals. ImageMagick source code and algorithms are discussed here. Usage questions which are too arcane for the normal user list should also be posted here.
Post Reply
fisheggs

How can I fill a primitive with an image using DrawingWand

Post by fisheggs »

The convert command

Code: Select all

convert -size 64x64 xc:blue -tile tile_weave.gif -draw 'circle 32,32 8,32' out.png
Will make an image like this: Image How can I do the same using the MagickWand/DrawingWand API?

The "-size 64x64 xc:blue" and "-draw 'circle 32,32 8,32'" bits are easy, it's the "-tile tile_weave.gif" I'm having problems with.
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: How can I fill a primitive with an image using DrawingWand

Post by el_supremo »

I've never used it but I think it's MagickTextureImage:

MagickWand *MagickTextureImage(MagickWand *wand, const MagickWand *texture_wand)
% MagickTextureImage() repeatedly tiles the texture image across and down the
% image canvas.

Pete
fisheggs

Re: How can I fill a primitive with an image using DrawingWand

Post by fisheggs »

Thanks for the suggestion Pete,

but that tiles on the canvas, rather than fill-tiling on the primitive so I get
Image rather than Image

It looks like MagickTextureImage() is the equivalent to the "-texture" operator, eg

Code: Select all

montage -texture tile_weave.gif rose: out.png
looks like Image
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: How can I fill a primitive with an image using DrawingWand

Post by el_supremo »

I figured out how to do it but, as far as I can determine, there isn't a way to do it directly with Magick/DrawingWand.

I used different filenames, colours, sizes, etc. and this code is a mixture of MagickCore and Magick/DrawingWand but I think it does what you want:

Code: Select all

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <wand/magick_wand.h>
#include <wand/magick-wand-private.h>

void test_wand(LPTSTR lpCmdLine)
{
	MagickWand *m_wand = NULL;
	PixelWand *p_wand;
	DrawingWand *d_wand;

	ImageInfo *read_info;

	DrawInfo *draw_info;

	ExceptionInfo exception;

	GetExceptionInfo(&exception);
//	unsigned long i_num;
//	char msg[512];

	MagickWandGenesis();

	m_wand = NewMagickWand();
	p_wand = NewPixelWand();
	d_wand = NewDrawingWand();

// Create a new image
	PixelSetColor(p_wand,"blue");
	MagickNewImage(m_wand,640,640,p_wand);

// Draw the circle
	DrawCircle(d_wand,320,320,320,600);

// Now "peek" at the wand
	draw_info = PeekDrawingWand(d_wand);
	read_info=CloneImageInfo(NULL);

// Put the name of the tile into the read_info
    (void) CopyMagickString(read_info->filename,"zssa_p015_tile.png",MaxTextExtent);

// and then read the tile in to the fill_pattern
	draw_info->fill_pattern = ReadImage(read_info,&exception);
	read_info=DestroyImageInfo(read_info);

// Now draw the whole thing 
	DrawImage(m_wand->images,draw_info);

	MagickWriteImage(m_wand,"zssa_tile_c.png");

	/* Destroy everything */
	DestroyExceptionInfo(&exception);
	m_wand = DestroyMagickWand(m_wand);
	p_wand = DestroyPixelWand(p_wand);
	d_wand = DestroyDrawingWand(d_wand);
	MagickWandTerminus();
}


Pete
fisheggs

Re: How can I fill a primitive with an image using DrawingWand

Post by fisheggs »

Thanks Pete,
you pointed me to the right place to look.

I have found out how to do it with just the MagickWand API (and without touching <wand/magick-wand-private.h>).

Code: Select all

# without declarations or error checks

i_wand=NewMagickWand()  # base image
t_wand=NewMagickWand()  # image to tile with
d_wand=NewDrawingWand()
p_wand=NewPixelWand()

PixelSetColor(p_wand, "blue")
MagickNewImage(i_wand, 64, 64, p_wand)      # base image, 64x64 blue
MagickReadImage(t_wand, "tile_weave.gif")   # tile image

#
# *THIS* is the bit I couldn't figure out
#
DrawPushPattern(d_wand, "pick-a-name-any-name", 0, 0, 16, 16)  # tile_weave is 16x16
DrawComposite(d_wand, SrcOverCompositeOp, 0, 0, 0, 0, t_wand)
DrawPopPattern(d_wand)
DrawSetFillPatternURL(d_wand, "#pick-a-name-any-name")  # as above but with a '#'

# now draw circle
DrawCircle(d_wand, 32, 32, 8, 32)
MagickDrawImage(i_wand, d_wand)

# and write image
MagickWriteImages(i_wand, "64x64_blue_tile_wand_circle.png", 1)
I think I overlooked DrawSetFillPatternURL() because of the 'URL' in the name.

Anyway the result is Image compared to the convert generated Image so I'm happy.

(And off to log a bug against DrawSetFillPatternURL() which ALLWAYS returns MagickFalse.)

Thanks again
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: How can I fill a primitive with an image using DrawingWand

Post by el_supremo »

Well done :-)
I tried DrawSetFillPatternURL but couldn't get it to work.

Pete
Post Reply