About gif Diffusion Transparency Dithering

The MagickWand interface is a new high-level C API interface to ImageMagick core methods. We discourage the use of the core methods and encourage the use of this API instead. Post MagickWand questions, bug reports, and suggestions to this forum.
Post Reply
beginner
Posts: 15
Joined: 2016-05-12T18:21:50-07:00
Authentication code: 1151

About gif Diffusion Transparency Dithering

Post by beginner »

1.png
Image

convert 1.png -channel RGBA -separate ( +clone -remap pattern:gray50 ) +swap -combine 1.gif

1.gif
Image

If MagickWand APIs is used, what relevant APIs need to be used to implement this function?
please help me.
thanks.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: About gif Diffusion Transparency Dithering

Post by snibgo »

What have you got so far? Which part of the command is causing you difficulty?
snibgo's IM pages: im.snibgo.com
beginner
Posts: 15
Joined: 2016-05-12T18:21:50-07:00
Authentication code: 1151

Re: About gif Diffusion Transparency Dithering

Post by beginner »

I use imagemagick 6.8.9

Below is the code I wrote, but the effect of the generated gif image is not what I expected.

I think it must be wrong to use some APIs.

3.gif:
Image

Code: Select all

MagickWand *mw_rgba = NewMagickWand();
MagickReadImage(mw_rgba, "E:\\temp\\1.png");


MagickWand *mw_red = CloneMagickWand(mw_rgba);
MagickWand *mw_green = CloneMagickWand(mw_rgba);
MagickWand *mw_blue = CloneMagickWand(mw_rgba);
MagickWand *mw_alpha = CloneMagickWand(mw_rgba);

//  -channel RGBA -separate ?
MagickSeparateImageChannel(mw_red, RedChannel);
MagickSeparateImageChannel(mw_green, GreenChannel);
MagickSeparateImageChannel(mw_blue, BlueChannel);
MagickSeparateImageChannel(mw_alpha, AlphaChannel);



// ( +clone -remap pattern:gray50 )

MagickWand *mw_clone = CloneMagickWand(mw_alpha); // +clone ?

MagickRemapImage(mw_clone, mw_rgba, FloydSteinbergDitherMethod); // -remap ?

MagickThresholdImage(mw_clone, QuantumRange * 50.0 / 100); // pattern:gray50 ?


// +swap -combine ?
MagickSetImageAlphaChannel(mw_clone, ActivateAlphaChannel);
//MagickSetImageAlphaChannel(mw_alpha, ActivateAlphaChannel);

MagickCompositeImage(mw_red, mw_green, CopyGreenCompositeOp, 0, 0);
MagickCompositeImage(mw_red, mw_blue, CopyBlueCompositeOp, 0, 0);
MagickCompositeImage(mw_red, mw_clone, CopyOpacityCompositeOp, 0, 0);
//MagickCompositeImage(mw_red, mw_alpha, CopyOpacityCompositeOp, 0, 0);


MagickAutoLevelImage(mw_red);


MagickWriteImage(mw_red, "E:\\temp\\3.gif");

What I need is this effect:
Image
Last edited by beginner on 2018-06-04T07:18:06-07:00, edited 2 times in total.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: About gif Diffusion Transparency Dithering

Post by snibgo »

Your command uses an image "pattern:gray50" but your wand code doesn't create that image.

Your command remaps using colours from the created image "pattern:gray50", but your wand code remaps using colours from the same image, so this has no effect.

Your wand code has a threshold that isn't in your command.
snibgo's IM pages: im.snibgo.com
beginner
Posts: 15
Joined: 2016-05-12T18:21:50-07:00
Authentication code: 1151

Re: About gif Diffusion Transparency Dithering

Post by beginner »

thank you for your reply.

According to your tips, I modified the relevant code:

Code: Select all

MagickWand *mw_rgba = NewMagickWand();
MagickReadImage(mw_rgba, "E:\\temp\\1.png");

MagickWand *mw_red = CloneMagickWand(mw_rgba);
MagickWand *mw_green = CloneMagickWand(mw_rgba);
MagickWand *mw_blue = CloneMagickWand(mw_rgba);
MagickWand *mw_alpha = CloneMagickWand(mw_rgba);

//  -channel RGBA -separate ?
MagickSeparateImageChannel(mw_red, RedChannel);
MagickSeparateImageChannel(mw_green, GreenChannel);
MagickSeparateImageChannel(mw_blue, BlueChannel);
MagickSeparateImageChannel(mw_alpha, AlphaChannel);

// ( +clone -remap pattern:gray50 )
MagickWand *mw_clone = CloneMagickWand(mw_alpha); // +clone ?

MagickWand *mw_gray50 = CloneMagickWand(mw_rgba);
MagickThresholdImage(mw_gray50, QuantumRange * 50.0 / 100); // pattern:gray50 ?

MagickRemapImage(mw_clone, mw_gray50, FloydSteinbergDitherMethod); // -remap ?

// +swap -combine ?
MagickSetImageAlphaChannel(mw_clone, ActivateAlphaChannel);

MagickCompositeImage(mw_red, mw_green, CopyGreenCompositeOp, 0, 0);
MagickCompositeImage(mw_red, mw_blue, CopyBlueCompositeOp, 0, 0);
MagickCompositeImage(mw_red, mw_clone, CopyOpacityCompositeOp, 0, 0);

MagickAutoLevelImage(mw_red);

MagickWriteImage(mw_red, "E:\\temp\\3.gif");
3.gif
Image

The effect is close to expectations, but there are still differences.

Where do I need to improve the code to fully achieve the desired effect ?

---------------------------------------------------------------------------------------------------------------------

convert 1.png -channel RGBA -separate ( +clone -remap pattern:gray50 ) +swap -combine 1.gif

1.gif
Image
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: About gif Diffusion Transparency Dithering

Post by fmw42 »

Try changing the -dither before -remap. See http://www.imagemagick.org/Usage/quantize/#remap
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: About gif Diffusion Transparency Dithering

Post by snibgo »

The default dither method is "Riemersma", not Floyd-Steinberg.
snibgo's IM pages: im.snibgo.com
beginner
Posts: 15
Joined: 2016-05-12T18:21:50-07:00
Authentication code: 1151

Re: About gif Diffusion Transparency Dithering

Post by beginner »

Thank you for your help!

I tried two different methods:

Code: Select all

MagickWand *mw_clone = CloneMagickWand(mw_alpha); // +clone

MagickWand *mw_gray50 = CloneMagickWand(mw_rgba);

MagickThresholdImage(mw_gray50, QuantumRange * 95.0 / 100);

MagickRemapImage(mw_clone, mw_gray50, RiemersmaDitherMethod); // -remap
Image

------------------------------------------------------------------------------------------------------------------

Code: Select all

MagickWand *mw_clone = CloneMagickWand(mw_alpha); // +clone

MagickWand *mw_gray50 = CloneMagickWand(mw_rgba);

MagickThresholdImageChannel(mw_gray50, AlphaChannel, QuantumRange * 50.0 / 100);
MagickOrderedPosterizeImage(mw_gray50, "o8x8,4");

MagickRemapImage(mw_clone, mw_gray50, RiemersmaDitherMethod); // -remap
Image

------------------------------------------------------------------------------------------------------------------

The effect of these two methods is very close to expectations, but there are still differences.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: About gif Diffusion Transparency Dithering

Post by snibgo »

As I have already said, you are not using the same image for remap.

Do you still have auto-level in your wand code but not the CLI version? That won't help.

You can compare the versions by writing intermediate results to disk.
snibgo's IM pages: im.snibgo.com
beginner
Posts: 15
Joined: 2016-05-12T18:21:50-07:00
Authentication code: 1151

Re: About gif Diffusion Transparency Dithering

Post by beginner »

I tried another simple method

Code: Select all

MagickWand *mw_rgba = NewMagickWand();
MagickReadImage(mw_rgba, "E:\\temp\\1.png");

MagickWand *mw_clone = CloneMagickWand(mw_rgba); // +clone ?

MagickWand *mw_gray50 = CloneMagickWand(mw_rgba);

MagickThresholdImageChannel(mw_gray50, AlphaChannel, QuantumRange * 50.0 / 100); // pattern:gray50 ?
MagickOrderedPosterizeImage(mw_gray50, "o8x8,4"); //(50 grey)

MagickRemapImage(mw_clone, mw_gray50, RiemersmaDitherMethod); // -remap ?

MagickSetImageAlphaChannel(mw_clone, ActivateAlphaChannel);
MagickCompositeImage(mw_rgba, mw_clone, CopyOpacityCompositeOp, 0, 0);  // +swap -combine ?

MagickAutoLevelImage(mw_rgba);

MagickWriteImage(mw_rgba, "E:\\temp\\2.gif");
Image

Closer to expected effect.
Post Reply