Issue with transparent text on white background

Magick.NET is an object-oriented C# interface to ImageMagick. Use this forum to discuss, make suggestions about, or report bugs concerning Magick.NET
Post Reply
erwin.cuppens
Posts: 11
Joined: 2015-06-26T02:41:17-07:00
Authentication code: 6789

Issue with transparent text on white background

Post by erwin.cuppens » 2016-10-03T00:09:54-07:00

Hi,

I'm trying to create a countdown GIF using the Magick.Net library.
Although the code is working correct I came up with an issue last week.
When merging some text frames with a transparent background onto a background image, depending on the color of the background image, the result is different.
When adding the text on a white background, the transparency becomes a certain shade of pink, when adding the text frames on a dark background (e.g. blue), the transparency is perfect.
Does anyone have some pointers on this?
  • Is this a known issue/bug?
  • Is this a configuration error
  • ...
I appended my example code. In order to build it you just need to create 2 background images (a white and a blue) and get the correct library version from the NuGet repo. I'm currently using version Magick.NET-Q8-AnyCPU version 7.0.0.18 of the library. I already tried updating but my code does not build anymore with the latest version so I have to find out what changed.

Regards,

Erwin

Code: Select all

namespace GifGenerator
{
    using System.Collections.Generic;
    using System.Drawing;
    using System.Globalization;
    using System.IO;
    using ImageMagick;

    class Program
    {
        static MagickColor textBackgroundColor = MagickColor.Transparent;
        static MagickColor textColor = new MagickColor(Color.Black);
        static MagickGeometry area = new MagickGeometry(10, 10, 20, 20);

        static void Main(string[] args)
        {
            // intialize background images
            MagickImage whiteBackgroundImage = new MagickImage(@"BackgroundImages\White background.png");
            whiteBackgroundImage.Quantize(new QuantizeSettings() { Colors = 255 });

            MagickImage blueBackgroundImage = new MagickImage(@"BackgroundImages\Blue background.png");
            blueBackgroundImage.Quantize(new QuantizeSettings() { Colors = 255 });
            
            File.WriteAllBytes(@"BackgroundIMages\White Background.gif", GenerateGif(whiteBackgroundImage));
            File.WriteAllBytes(@"BackgroundIMages\Blue Background.gif", GenerateGif(blueBackgroundImage));
        }

        private static byte[] GenerateGif(MagickImage backgroundImage)
        {
            MagickImageCollection collection = new MagickImageCollection();
            collection.AddRange(GenerateFrames(backgroundImage, 10));
            byte[] data = collection.ToByteArray(MagickFormat.Gif);
            return data;
        }

        private static IEnumerable<MagickImage> GenerateFrames(MagickImage backgroundImage, int numberOfFrames)
        {
            for (int i = 0; i < numberOfFrames; i++)
            {
                MagickImage textImage = new MagickImage(MagickColor.Transparent, 20, 20);
                WriteText(textImage, i.ToString(), textBackgroundColor, textColor, "Arial", 14);

                // render gif
                MagickImage partialFrame = backgroundImage.Clone(area);
                partialFrame.Composite(textImage, CompositeOperator.Over);
                partialFrame.Alpha(AlphaOption.Off);

                partialFrame.Page = area;
                partialFrame.GifDisposeMethod = GifDisposeMethod.None;
                partialFrame.Quantize(new QuantizeSettings() { Colors = 255 });

                MagickImage frame = new MagickImage(backgroundImage);
                frame.Composite(partialFrame, partialFrame.Page, CompositeOperator.Over);

                yield return frame;
            }
        }

        private static void WriteText(MagickImage image, string text, MagickColor backgroundColor, MagickColor fontColor, string fontFamily, double fontSize)
        {
            image.BackgroundColor = backgroundColor;
            image.FillColor = fontColor;
            image.Font = fontFamily.Replace(" ", "-");
            image.FontPointsize = fontSize * 96.0 / 72.0;
            image.Read(string.Format(CultureInfo.InvariantCulture, "label:{0}", text));
        }
    }
}

User avatar
dlemstra
Posts: 1578
Joined: 2013-05-04T15:28:54-07:00
Authentication code: 6789
Contact:

Re: Issue with transparent text on white background

Post by dlemstra » 2016-10-03T12:07:58-07:00

I cannot reproduce your issue with the latest version of Magick.NET. The following document might help you to change your code to be compatible with the latest version: https://magick.codeplex.com/SourceContr ... Changes.md. Can you upgrade Magick.NET and let me know if you can still reproduce the issue?
.NET + ImageMagick = Magick.NET https://github.com/dlemstra/Magick.NET, @MagickNET, Donate

erwin.cuppens
Posts: 11
Joined: 2015-06-26T02:41:17-07:00
Authentication code: 6789

Re: Issue with transparent text on white background

Post by erwin.cuppens » 2016-10-07T06:58:19-07:00

Hi,

I have tried converting my code to the latest version but I seem to struggle to get it to work again.
My text is black square now.
Since you have tested my code in the latest version, can you please share the code using the latest version of the library so I check which change I missed?

Regards,

Erwin

User avatar
dlemstra
Posts: 1578
Joined: 2013-05-04T15:28:54-07:00
Authentication code: 6789
Contact:

Re: Issue with transparent text on white background

Post by dlemstra » 2016-10-10T02:02:08-07:00

I used the following code:

Code: Select all

namespace GifGenerator
{
  using System.Collections.Generic;
  using System.Drawing;
  using System.Globalization;
  using System.IO;
  using ImageMagick;

  class Program
  {
    static MagickColor textBackgroundColor = MagickColors.Transparent;
    static MagickColor textColor = new MagickColor(Color.Black);
    static MagickGeometry area = new MagickGeometry(10, 10, 20, 20);

    static void Main(string[] args)
    {
      // intialize background images
      MagickImage whiteBackgroundImage = new MagickImage(@"BackgroundImages\White background.png");
      whiteBackgroundImage.Quantize(new QuantizeSettings() { Colors = 255 });

      MagickImage blueBackgroundImage = new MagickImage(@"BackgroundImages\Blue background.png");
      blueBackgroundImage.Quantize(new QuantizeSettings() { Colors = 255 });

      File.WriteAllBytes(@"BackgroundIMages\White Background.gif", GenerateGif(whiteBackgroundImage));
      File.WriteAllBytes(@"BackgroundIMages\Blue Background.gif", GenerateGif(blueBackgroundImage));
    }

    private static byte[] GenerateGif(MagickImage backgroundImage)
    {
      MagickImageCollection collection = new MagickImageCollection();
      collection.AddRange(GenerateFrames(backgroundImage, 10));
      byte[] data = collection.ToByteArray(MagickFormat.Gif);
      return data;
    }

    private static IEnumerable<MagickImage> GenerateFrames(MagickImage backgroundImage, int numberOfFrames)
    {
      for (int i = 0; i < numberOfFrames; i++)
      {
        MagickImage textImage = new MagickImage(MagickColors.Transparent, 20, 20);
        WriteText(textImage, i.ToString(), textBackgroundColor, textColor, "Arial", 14);

        // render gif
        MagickImage partialFrame = backgroundImage.Clone(area);
        partialFrame.Composite(textImage, CompositeOperator.Over);
        //partialFrame.Alpha(AlphaOption.Off);

        partialFrame.Page = area;
        partialFrame.GifDisposeMethod = GifDisposeMethod.None;
        partialFrame.Quantize(new QuantizeSettings() { Colors = 255 });

        MagickImage frame = new MagickImage(backgroundImage);
        frame.Composite(partialFrame, partialFrame.Page.ToPoint(), CompositeOperator.Over);
        frame.Alpha(AlphaOption.Off); // Had to move this line.

        yield return frame;
      }
    }

    private static void WriteText(MagickImage image, string text, MagickColor backgroundColor, MagickColor fontColor, string fontFamily, double fontSize)
    {
      image.BackgroundColor = backgroundColor;
      image.Settings.FillColor = fontColor;
      image.Settings.Font = fontFamily.Replace(" ", "-");
      image.Settings.FontPointsize = fontSize * 96.0 / 72.0;
      image.Read(string.Format(CultureInfo.InvariantCulture, "label:{0}", text));
    }
  }
}
.NET + ImageMagick = Magick.NET https://github.com/dlemstra/Magick.NET, @MagickNET, Donate

erwin.cuppens
Posts: 11
Joined: 2015-06-26T02:41:17-07:00
Authentication code: 6789

Re: Issue with transparent text on white background

Post by erwin.cuppens » 2016-10-11T03:52:39-07:00

Hi,

Thanks for sharing your code. I have updated my code to the latest version and the issue indeed seems to be solved.
However, I noticed that my test-code was a little bit to simple. I tried to optimize my code in order to have smaller frames that should be merged.
The actual code would be as shown below. I only do a full rendering of the first frame, the consecutive frames are smaller and contain only the text.
However, this results in the first frame being as it should be but all consecutive frames are black.
I tried playing with the Alpha function but when only applying it to the first frame the text will not replace but instead overwrite the text in the first frame.
Is there a configuration that can be used to solve this issue?

Code: Select all

private static IEnumerable<MagickImage> GenerateFrames(MagickImage backgroundImage, int numberOfFrames)
{
	for (int i = 0; i < numberOfFrames; i++)
	{
		MagickImage textImage = new MagickImage(MagickColors.Transparent, 20, 20);
		WriteText(textImage, i.ToString(), textBackgroundColor, textColor, "Arial", 14);

		// render gif
		MagickImage partialFrame = backgroundImage.Clone(area);
		partialFrame.Composite(textImage, CompositeOperator.Over);

		partialFrame.Page = area;
		partialFrame.GifDisposeMethod = GifDisposeMethod.None;
		partialFrame.Quantize(new QuantizeSettings() { Colors = 255 });

		MagickImage frame = null;
		if (i == 0)
		{
			frame = new MagickImage(backgroundImage);
			frame.Composite(partialFrame, partialFrame.Page.ToPoint(), CompositeOperator.Over);
		}
		else
		{
			frame = partialFrame.Clone();
		}

		frame.Alpha(AlphaOption.Off);

		yield return frame;
	}
}

erwin.cuppens
Posts: 11
Joined: 2015-06-26T02:41:17-07:00
Authentication code: 6789

Re: Issue with transparent text on white background

Post by erwin.cuppens » 2016-11-03T05:33:34-07:00

Hi dlemstra,

Have you been able to check on my last question?

Regards,

Erwin

User avatar
dlemstra
Posts: 1578
Joined: 2013-05-04T15:28:54-07:00
Authentication code: 6789
Contact:

Re: Issue with transparent text on white background

Post by dlemstra » 2016-11-07T10:59:13-07:00

It appears you found a bug in the method that clones the image. Not sure yet how to fix it properly but this will be resolved in the next version of Magick.NET.
.NET + ImageMagick = Magick.NET https://github.com/dlemstra/Magick.NET, @MagickNET, Donate

erwin.cuppens
Posts: 11
Joined: 2015-06-26T02:41:17-07:00
Authentication code: 6789

Re: Issue with transparent text on white background

Post by erwin.cuppens » 2016-11-23T01:02:32-07:00

Hi,

Thanks for checking on my issue. Seems I have to wait a while before I can upgrade to the latest version then.
Is this bug logged somewhere in order to follow up on the status?

Regards,

Erwin

User avatar
dlemstra
Posts: 1578
Joined: 2013-05-04T15:28:54-07:00
Authentication code: 6789
Contact:

Re: Issue with transparent text on white background

Post by dlemstra » 2016-11-24T15:26:03-07:00

The new version will be published tomorrow or this weekend and this issue has already been fixed in the code of Magick.NET.
.NET + ImageMagick = Magick.NET https://github.com/dlemstra/Magick.NET, @MagickNET, Donate

erwin.cuppens
Posts: 11
Joined: 2015-06-26T02:41:17-07:00
Authentication code: 6789

Re: Issue with transparent text on white background

Post by erwin.cuppens » 2016-12-06T01:56:29-07:00

Hi,

I was able to update to the latest version and the issue has been fixed.
Thank you very much for your help.

Regards,

Erwin

Post Reply