Page 1 of 1

How to fill a primitive with a gradient color?

Posted: 2017-04-20T12:35:57-07:00
by Airon65
Is there a way to fill a primitive with a gradient color?

Re: How to fill a primitive with a gradient color?

Posted: 2017-04-20T13:01:54-07:00
by snibgo
Not directly. It can be made transparent, and the image then composited over a gradient image.

Re: How to fill a primitive with a gradient color?

Posted: 2017-04-21T08:11:59-07:00
by Airon65
snibgo wrote:
2017-04-20T13:01:54-07:00
Not directly. It can be made transparent, and the image then composited over a gradient image.
Such an interesting technique. You mean I can draw a primitive with a transparent fill and put that primitive over the gradient image? Do I need to have a white background outside the primitive? Then how to draw two or more primitives with different gradients on the same image?

Re: How to fill a primitive with a gradient color?

Posted: 2017-04-21T10:01:57-07:00
by snibgo
An example may clarify.

Code: Select all

%IM%convert ^
  ( ^
    -size 300x300 gradient:red-blue ^
    ( +clone -fill Black -colorize 100 ^
      -fill White -draw "polygon 50,50 250,50 200,200" ^
    ) ^
    -alpha off ^
    -compose CopyOpacity -composite ^
  ) ^
  ( ^
    -size 300x300 gradient:#f80-#08f ^
    ( +clone -fill Black -colorize 100 ^
      -fill White -draw "polygon 50,150 250,150 200,300" ^
    ) ^
    -alpha off ^
    -compose CopyOpacity -composite ^
  ) ^
  -compose Over -composite ^
  grad_shapes.png
Image

This makes a gradient, then a same-size image with a white polygon (a triangle) on black background, and this is applied as opacity to the gradient. The result is a gradient triangle of transparent background.

We repeat this with a second triangle.

Then we composite the second triangle over the first.

I expect there are other ways of doing this.

Re: How to fill a primitive with a gradient color?

Posted: 2017-04-21T13:20:59-07:00
by Airon65
Wow that works really cool but how to convert it to Magick++ format? :)

The first problem is with the colorize function. I see two definitions of colorize function:

Code: Select all

// Colorize image with pen color, using specified percent alpha.
void colorize(const unsigned int alpha_,const Color &penColor_);

// Colorize image with pen color, using specified percent alpha
// for red, green, and blue quantums
void colorize(const unsigned int alphaRed_,const unsigned int alphaGreen_,
   const unsigned int alphaBlue_,const Color &penColor_);
how to properly do that step?

Code: Select all

-colorize 100

Re: How to fill a primitive with a gradient color?

Posted: 2017-04-21T14:15:10-07:00
by snibgo
"-fill Black -colorize 100" simply makes all the pixels opaque black. It's a slightly clumsy way of doing it at the command line. In the C APIs, there are cleaner ways. I don't use Magick++, but "erase" looks likely, after setting the background colour.

Re: How to fill a primitive with a gradient color?

Posted: 2017-04-21T15:22:24-07:00
by Airon65
1. What do the "-alpha off" command do? Is it just remove the alpha channel from an image?

2. I try to convert it to C++ so I did:

Code: Select all

Magick::Image gradImg( Magick::Geometry( 500, 500 ), Magick::Color( "white" ) );
gradImg.read( "gradient:red-blue" );

Magick::Image testImg( Magick::Geometry( 500, 500 ), Magick::Color( "black" ) );

testImg.strokeWidth( 0 );
testImg.fillColor( Magick::Color( QuantumRange, QuantumRange, QuantumRange, QuantumRange ) ); // white color!

float centerX = 250, centerY = 250;
float xr = 150, yr = 150;
testImg.draw( Magick::DrawableEllipse( centerX, centerY, xr, yr, 0, 360 ) );

gradImg.composite( testImg, gradImg.columns() / 2 - testImg.columns() / 2, gradImg.rows() / 2 - testImg.rows() / 2, Magick::ColorizeCompositeOp );

gradImg.write( "images/grad.png" );
testImg.write( "images/test2.png" );
it looks like ColorizeCompositeOp is not the right operator for achieving this goal :) I don't know what's the CopyOpacity operator? In the include.h I see only these compose operators:

Code: Select all

// Composition operations
  using MagickCore::CompositeOperator;
  using MagickCore::AlphaCompositeOp;
  using MagickCore::AtopCompositeOp;
  using MagickCore::BlendCompositeOp;
  using MagickCore::BlurCompositeOp;
  using MagickCore::BumpmapCompositeOp;
  using MagickCore::ChangeMaskCompositeOp;
  using MagickCore::ClearCompositeOp;
  using MagickCore::ColorBurnCompositeOp;
  using MagickCore::ColorDodgeCompositeOp;
  using MagickCore::ColorizeCompositeOp;
  using MagickCore::CopyBlackCompositeOp;
  using MagickCore::CopyBlueCompositeOp;
  using MagickCore::CopyCompositeOp;
  using MagickCore::CopyCyanCompositeOp;
  using MagickCore::CopyGreenCompositeOp;
  using MagickCore::CopyMagentaCompositeOp;
  using MagickCore::CopyAlphaCompositeOp;
  using MagickCore::CopyRedCompositeOp;
  using MagickCore::CopyYellowCompositeOp;
  using MagickCore::DarkenCompositeOp;
  using MagickCore::DarkenIntensityCompositeOp;
  using MagickCore::DifferenceCompositeOp;
  using MagickCore::DisplaceCompositeOp;
  using MagickCore::DissolveCompositeOp;
  using MagickCore::DistortCompositeOp;
  using MagickCore::DivideDstCompositeOp;
  using MagickCore::DivideSrcCompositeOp;
  using MagickCore::DstAtopCompositeOp;
  using MagickCore::DstCompositeOp;
  using MagickCore::DstInCompositeOp;
  using MagickCore::DstOutCompositeOp;
  using MagickCore::DstOverCompositeOp;
  using MagickCore::ExclusionCompositeOp;
  using MagickCore::HardLightCompositeOp;
  using MagickCore::HardMixCompositeOp;
  using MagickCore::HueCompositeOp;
  using MagickCore::InCompositeOp;
  using MagickCore::IntensityCompositeOp;
  using MagickCore::LightenCompositeOp;
  using MagickCore::LightenIntensityCompositeOp;
  using MagickCore::LinearBurnCompositeOp;
  using MagickCore::LinearDodgeCompositeOp;
  using MagickCore::LinearLightCompositeOp;
  using MagickCore::LuminizeCompositeOp;
  using MagickCore::MathematicsCompositeOp;
  using MagickCore::MinusDstCompositeOp;
  using MagickCore::MinusSrcCompositeOp;
  using MagickCore::ModulateCompositeOp;
  using MagickCore::ModulusAddCompositeOp;
  using MagickCore::ModulusSubtractCompositeOp;
  using MagickCore::MultiplyCompositeOp;
  using MagickCore::NoCompositeOp;
  using MagickCore::OutCompositeOp;
  using MagickCore::OverCompositeOp;
  using MagickCore::OverlayCompositeOp;
  using MagickCore::PegtopLightCompositeOp;
  using MagickCore::PinLightCompositeOp;
  using MagickCore::PlusCompositeOp;
  using MagickCore::ReplaceCompositeOp;
  using MagickCore::SaturateCompositeOp;
  using MagickCore::ScreenCompositeOp;
  using MagickCore::SoftLightCompositeOp;
  using MagickCore::SrcAtopCompositeOp;
  using MagickCore::SrcCompositeOp;
  using MagickCore::SrcInCompositeOp;
  using MagickCore::SrcOutCompositeOp;
  using MagickCore::SrcOverCompositeOp;
  using MagickCore::ThresholdCompositeOp;
  using MagickCore::UndefinedCompositeOp;
  using MagickCore::VividLightCompositeOp;
  using MagickCore::XorCompositeOp;

Re: How to fill a primitive with a gradient color?

Posted: 2017-04-21T15:42:22-07:00
by snibgo
For translating between command-line and C (or C++), a very useful source is MagickCore\option.c. This file translates command-line options to the internals. Search that file for "CopyOpacity".

Re: How to fill a primitive with a gradient color?

Posted: 2017-04-21T16:00:49-07:00
by Airon65
snibgo wrote:
2017-04-21T15:42:22-07:00
For translating between command-line and C (or C++), a very useful source is MagickCore\option.c. This file translates command-line options to the internals. Search that file for "CopyOpacity".
Thanks, it's very useful file! :) Didn't know about it. Now I know that ColorizeCompositeOp is the "Magick::CopyAlphaCompositeOp". Now I don't know how to do: "-alpha off" :) Why do you do this step?

Re: How to fill a primitive with a gradient color?

Posted: 2017-04-21T17:54:48-07:00
by snibgo
"CopyOpacity" normally copies the opacity from Src to Dst. If Src is fully opaque, this would make the result white. But if alpha is off, it doesn't copy the opacity; instead, it copies the intensity of Src to the opacity of Dst.

I think "-alpha off" is "MagickSetImageAlphaChannel (wand, OffAlphaChannel)". In v7, traits should probably be used.

Re: How to fill a primitive with a gradient color?

Posted: 2017-04-21T17:57:03-07:00
by Airon65
Oh finally I've got it. You mean simply masks technique. Now I understand what did you mean.
Here is the way for doing this:

Code: Select all

Magick::Image gradImg( Magick::Geometry( 500, 500 ), Magick::Color( "white" ) );
gradImg.read( "gradient:red-blue" );

Magick::Image maskImg( Magick::Geometry( 500, 500 ), Magick::Color( "black" ) );
maskImg.strokeWidth( 0 );
maskImg.fillColor( Magick::Color( "white" ) ); // white color!
maskImg.draw( Magick::DrawableEllipse( 250, 250, 150, 150, 0, 360 ) );

maskImg.alphaChannel( MagickCore::DeactivateAlphaChannel );
gradImg.alphaChannel( MagickCore::DeactivateAlphaChannel );
maskImg.negate();
gradImg.composite( maskImg, 0, 0, Magick::BlendCompositeOp ); // applying a mask

gradImg.write( "images/grad.png" );
maskImg.write( "images/mask.png" );
Looks like all work fine :) Thank you!