Page 1 of 1
How do I make a new image with a transparent background?
Posted: 2008-09-07T13:51:19-07:00
by bobp
Hi,
I'm trying to use the MagickWand API to create an image that's composed of multiple layers. The first layer should have an opaque background but all layers after that should have transparent backgrounds.
This is more or less how the code looks:
Code: Select all
MagickWand *mw1 = NewMagickWand();
PixelWand *bgw1 = NewPixelWand();
MagickNewImage(mw1, 100, 100, bgw1); // this image should have an opaque background
//... paint on the image
// now create another layer
MagickWand mw2 = NewMagickWand();
PixelWand *bgw2 = NewPixelWand();
MagickNewImage(mw2, 100, 100, bgw2); // this image should have a transparent background
// ... paint on the second image
// create the final image
MagickAddImage(mw1, mw2);
MagickWand *merged = MagickMergeImageLayers(mw1, MergeLayer);
MagickWriteImage(merged, "foo.png");
The problem is that the image from the second wand completely hides the image from the first wand because of its opaque background. I'm trying to make it so only the strokes from the second image are visible, but not the background, which should be transparent. I tried setting the opacity value of bgw2 to 0 to no effect. I'm not sure what else I can do to. Any help is appreciated.
Thanks,
Bob
Re: How do I make a new image with a transparent background?
Posted: 2008-09-07T14:03:37-07:00
by el_supremo
Hi Bob:
You aren't setting the pixelwand's colour.
After this statement:
PixelWand *bgw2 = NewPixelWand();
add this:
PixelSetColor(bgw2,"none");
If the Merge doesn't work try MagickFlattenImages(mw1) instead.
Pete
Re: How do I make a new image with a transparent background?
Posted: 2008-09-07T14:12:45-07:00
by bobp
Hi Pete,
Thanks for the reply! I tried following your suggestions but unfortunately it didn't work. Setting the color to "none" is equivalent to setting it to black. And using MagicFlattenImages() didn't make a difference. I also tried calling PixelSetOpacity(bgw2, 0) and it didn't help.
Any other ideas?
Thanks again,
Bob
Re: How do I make a new image with a transparent background?
Posted: 2008-09-07T14:40:49-07:00
by el_supremo
My bad, MagickFlattenImages is deprecated in favour of MagickMergeImageLayers.
This code creates two separate magickwands, writes text on them and then merges them into one image.
The first image has a red background and the second has a transparent background ("none" is the same as "transparent");
Code: Select all
MagickWand *mw1 = NewMagickWand();
PixelWand *bgw1 = NewPixelWand();
DrawingWand *dw1 = NewDrawingWand();
MagickWand *mw2 = NewMagickWand();
PixelWand *bgw2 = NewPixelWand();
DrawingWand *dw2 = NewDrawingWand();
MagickWand *merged;
MagickWandGenesis();
PixelSetColor(bgw1,"red");
MagickNewImage(mw1, 100, 100, bgw1); // this image should have an opaque background
//... paint on the image
PixelSetColor(bgw1,"white");
DrawSetFillColor(dw1,bgw1);
DrawSetFontSize(dw1,12);
DrawSetFont(dw1,"Times-New-Roman");
MagickAnnotateImage(mw1,dw1,0,15,0.0,"Hello");
// now create another layer
PixelSetColor(bgw2,"none");
MagickNewImage(mw2, 100, 100, bgw2); // this image should have a transparent background
// ... paint on the second image
PixelSetColor(bgw2,"red");
DrawSetFillColor(dw2,bgw1);
DrawSetFontSize(dw2,12);
DrawSetFont(dw2,"Times-New-Roman");
MagickAnnotateImage(mw2,dw2,0,50,0.0,"Magick");
// create the final image
MagickAddImage(mw1, mw2);
merged = MagickMergeImageLayers(mw1, MergeLayer);
MagickWriteImage(merged, "foo.png");
merged = DestroyMagickWand(merged);
mw1 = DestroyMagickWand(mw1);
mw2 = DestroyMagickWand(mw2);
bgw1 = DestroyPixelWand(bgw1);
bgw2 = DestroyPixelWand(bgw2);
dw1 = DestroyDrawingWand(dw1);
dw2 = DestroyDrawingWand(dw2);
Pete
Re: How do I make a new image with a transparent background?
Posted: 2008-09-07T15:10:13-07:00
by bobp
Ok, I think I realize what I did wrong. I was calling 'MagickSetImageOpacity(mw2, 0.5)' before MagickAddImage(mw1, mw2). I thought this would only affect the opacity of the foreground strokes, but not the background. Apparently, calling MagickSetImageOpacity() sets the value for both the foreground and the background. So, if previously your background was transparent, calling MagickSetImageOpacity(mw2, 0.5) would make it semi transparent. This was overwriting the value I set previously for the background transparency.
This leads to the following question: is it possible to set the opacity only for the image's foreground, but not the background? I basically want to paint a bunch of strokes on the second image and then apply the alpha value to the whole image, not to each stroke individually. I also want the background to stay transparent. Is this possible?
Re: How do I make a new image with a transparent background?
Posted: 2008-09-07T15:11:07-07:00
by bobp
By the way, thanks again for the reply! I really appreciate your help.
Re: How do I make a new image with a transparent background?
Posted: 2008-09-07T17:26:10-07:00
by el_supremo
is it possible to set the opacity only for the image's foreground, but not the background?
I'm sure it can be done but at the moment I can't think how to do it when you've already created the second image.
If you can change the colours involved in the painting, you can just specify the opacity when the second image is painted. In my code you can replace this:
// ... paint on the second image
PixelSetColor(bgw2,"red");
DrawSetFillColor(dw2,bgw1);
with this (which corrects a bug in the original):
// ... paint on the second image
PixelSetColor(bgw2,"rgba(0,0,100%,0.4)");
DrawSetFillColor(dw2,bgw2);
This will draw with blue but also with the alpha set to 0.4 so that you will have a partial transparency when it is merged with the first magickwand.
Pete
Re: How do I make a new image with a transparent background?
Posted: 2008-09-07T22:29:44-07:00
by anthony
Please note the differences between methods
FlattenLayers, MosaicLayers, and MergeLayers.
The difference is how they handle multiple image layers with offsets.
See IM examples, Layering Images, Flatten
http://www.imagemagick.org/Usage/#flatten
for details of their differences.
For a plain no-offset image the result should be the same though.
Re: How do I make a new image with a transparent background?
Posted: 2008-09-08T13:11:52-07:00
by el_supremo
I haven't figured out how to merge the two wands using only MagickWand but by calling one MagickCore function the Dissolve (or Blend) composite operator can be used to combine the two wands.
First add this include:
#include <wand/magick-wand-private.h>
Then replace these three statements:
MagickAddImage(mw1, mw2);
merged = MagickMergeImageLayers(mw1, MergeLayer);
MagickWriteImage(merged, "foo.png");
with this:
// Fudge to set the geometry of the second magickwand
(void) CloneString(&mw2->images->geometry,"30x100+0+0");
// Dissolve the second image over the first
MagickCompositeImage(mw1,mw2,DissolveCompositeOp,0,0);
MagickWriteImage(mw1, "foo.png");
This combines mw2 (30%) and mw1 (100%) and leaves the result in mw1 so the "merged" MagickWand isn't needed any more.
@magick: Is there a way to do the composite command's -dissolve and -blend using only MagickWand? If not, can a mechanism be added?
Pete
Pete
Re: How do I make a new image with a transparent background?
Posted: 2008-09-08T17:24:38-07:00
by anthony
'Dissolve' and 'Blend' is really just multiplying the 'alpha' channel values by the percentages given, then, composing them using 'Over' or 'Plus' respectively. You should be able to do this using a channel restricted '-evaluate multiply' onto each of the images.
Note I am not a MagickWand user, But I know the Magickcore, and command line, so know what should be possible.
Re: How do I make a new image with a transparent background?
Posted: 2008-09-08T19:46:21-07:00
by el_supremo
It works! Multiply the alpha channel of mw2 by 0.3 and then composite with Over.
MagickEvaluateImageChannel(mw2,AlphaChannel,MultiplyEvaluateOperator,0.3);
MagickCompositeImage(mw1,mw2, OverCompositeOp,0,0);
Thanks Anthony
Pete