Slow gif generation

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

Slow gif generation

Post by erwin.cuppens » 2015-06-26T02:57:18-07:00

Hello,

I'm trying to generate a 60 seconds gif representing a countdown timer.
Generating the frames is done using the following code:

Code: Select all

for (int i = 0; i < numberOfFrames; ++i)
{
    DateTime dt = processingDateTime.AddSeconds(i);

    MagickImage magickImage = new MagickImage(frameGenerator.Generate(dt))
    {
        AnimationDelay = 100
    };

    /* handle transparency if needed*/
    if (this.contentDefinitionCountdown.TransparentBackground)
    {
        magickImage.SetAttribute("dispose", "background");
        magickImage.Transparent(frameGenerator.TransparentColor);
    }

    yield return magickImage;
}
Once the frames are generated, I add them to a MagickImageCollection and generate the resulting bytes using the following code:

Code: Select all

using (MagickImageCollection collection = new MagickImageCollection())
{
    collection.AddRange(this.GenerateFrames(processingDateTime, numberOfFrames));
    collection.Coalesce();
    result = collection.ToByteArray(MagickFormat.Gif);
}

Now the issue:

When using no background in my frames, the frame size is rather small (about 420 x 30 pixels) and the generation of the gif takes about 3 seconds which is not very fast but acceptable in our case. (If anyone has suggestion to speed up this process, do not hesitate to comment)

When using a background in the frames, the countdown text is rendered upon that background and the frames size is (800 x 600). In this case the generation of the animated gif takes about 15 seconds, which is not acceptable for our use case.

Now, as far as we can see there might be 2 solutions to this:
  • Speed up the generation of the animated gif in some way
  • Generate the animated gif without the background and somehow merge the resulting gif with the background image afterwards.
Doen anyone have any pointers that can help us with our problem?
Can we do something to speed up the gif generation?
Is it possible to generate a small gif and afterwards combine it with the background image?

Regards,

Erwin Cuppens

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

Re: Slow gif generation

Post by dlemstra » 2015-06-26T03:54:42-07:00

Why are you calling Coalesce? You don't need to do that. This is only necessary when you want to extract all the frames from a gif animation (http://www.imagemagick.org/script/comma ... p#coalesce)
.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: Slow gif generation

Post by erwin.cuppens » 2015-06-26T04:00:47-07:00

Isn't this required to handle the dispose attribute?
Well, nevertheless, removing this option does not influence the processing time.

Regards,

Erwin

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

Re: Slow gif generation

Post by dlemstra » 2015-06-26T04:05:27-07:00

Does your background contain more then 255 colors? It is possible that the number of colors needs to be reduced and this can take quite a while. It will probably help if you reduce the number of colors in that image before you draw your text on it.
.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: Slow gif generation

Post by erwin.cuppens » 2015-06-26T05:20:15-07:00

Hi,

You suggestion indeed works.
When using a background-image with high colors and reducing it to 255 colors before starting to generate the frames, the time required for the gif generation goes from 22 to 18 seconds.
Unfortunately, the original image that we were using was only 1 bit (just a single color background of 800x600) so the original issue remains.

Thanks for you answer!

Regards,

Erwin

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

Re: Slow gif generation

Post by dlemstra » 2015-06-26T05:24:23-07:00

Are you able to create a small sample project that I could use to reproduce the issue? You cannot attach that here, you will have to put it on something like DropBox/OneDrive.
.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: Slow gif generation

Post by erwin.cuppens » 2015-06-26T06:08:32-07:00

I've sent you a private message with the code attached to it.

Regards,

Erwin

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

Re: Slow gif generation

Post by dlemstra » 2015-06-26T06:22:22-07:00

Attachments in PM's don't seem to work. I could e-mail you if you prefer to not share it publicly.
.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: Slow gif generation

Post by erwin.cuppens » 2015-06-26T07:19:30-07:00

You can email me on <snip/>
I'll reply with the code attached.

Regards,

Erwin

ProfessorYaffle
Posts: 4
Joined: 2015-08-27T03:03:57-07:00
Authentication code: 1151

Re: Slow gif generation

Post by ProfessorYaffle » 2015-08-27T03:21:00-07:00

Hi,

Bizarrely I'm encountering the exact same problem, trying to do the exact same thing; building a dynamically generated countdown GIF image.
Currently it's taking about 3.5 seconds to generate and present to the browser and is around 20kb when downloaded.

- Was there any further solution to this problem with regards to speeding up the generation process?

- Is there anyway to further optimise the resulting file (if, for example, I load the gif into an editor and resave it with 'lossy' optimisation the file size drops to 13kb)

Thanks for your help,
Russ.

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

Re: Slow gif generation

Post by dlemstra » 2015-08-27T05:02:59-07:00

Are you using the latest version of Magick.NET? Can you share your input images and a small code example on something like DropBox so I can reproduce this?
.NET + ImageMagick = Magick.NET https://github.com/dlemstra/Magick.NET, @MagickNET, Donate

ProfessorYaffle
Posts: 4
Joined: 2015-08-27T03:03:57-07:00
Authentication code: 1151

Re: Slow gif generation

Post by ProfessorYaffle » 2015-08-27T07:41:33-07:00

Hi,

So I'm using version 7.0.0.0017 of the Magick.NET-Q8-x64 package from Nuget, which I assume is the latest?
I've built a cut down version of the application and added it to a simple mvc site: https://www.dropbox.com/s/z21ukzw03915v ... t.zip?dl=0
(this is a visual studio project

Take a look in classes->CountdownGifAnimation.cs - this is where the frames collection is being built and optimised.

Many thanks for your help
Russ.

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

Re: Slow gif generation

Post by dlemstra » 2015-08-27T14:44:42-07:00

I just took a quick look at the code inside CountdownGifAnimation.cs and I have a few remarks and questions about the code.

1. You don't need to use the Bitmap classes to write text on an image. Magick.NET can do this with the Drawable classes or by reading a label image:

Code: Select all

using (MagickImage image = new MagickImage())
{
  image.Font = "YourFont";
  image.FontPointsize = 50;
  image.Read("label:00");
}
If you prefer to stay with Bitmaps make sure you Dispose() the Bitmap on line 40. That dispose might also be gone because you 'stripped' the code. You should also change the block starting at line 27:

Code: Select all

using (MagickImageCollection frames = CreateFrameCollection())
{
  return GetFileStreamResult(frames);
}
Magick.NET has unmanaged memory so it is really important that you make sure that Dispose is called as soon as possible.

2. Why do you quantize the image to 8 colors? This is most likely that part that is causing the delay.

3. collection.Optimize() should reduce the size of the file. Can you add a link to the original and the optimized image so I can compare them?
.NET + ImageMagick = Magick.NET https://github.com/dlemstra/Magick.NET, @MagickNET, Donate

ProfessorYaffle
Posts: 4
Joined: 2015-08-27T03:03:57-07:00
Authentication code: 1151

Re: Slow gif generation

Post by ProfessorYaffle » 2015-08-28T01:33:44-07:00

Thanks for getting back to me, in answer to your questions:

1. Originally I was using the imageMagick annotate function to add text to an image, but as an experiment and to see if I could narrow down what was causing the slow processing, I decided to used a different technique - this didn't change the filesize or processing time at all, and I just left it in. Could you point me to the location of the drawable class documentation? .. All the docs I've found for the .net wrapper are basically this page: http://magick.codeplex.com/documentatio ... Title=Home , which clearly doesn't include the range of functionality available!

2. So this was another experiment: I'm reducing the image to 8 colours which has an effect of reducing the file size, but doesn't seem to make much impact on the processing time:
without quantize/ without optimise: size: 29.7Kb / processing time 4.07s
without quantize/with optimise: size = 29.7Kb / processing time = 4.44s
with quantize/with optimise: size: 21.7Kb / processing time = 4.99s
(times and sizes as reported by chrome dev tools->network tab)

3. I've added these images to drop box here : https://www.dropbox.com/s/lmnqvpozfxtnf ... s.zip?dl=0

Thanks,
Russ.

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

Re: Slow gif generation

Post by dlemstra » 2015-08-28T14:30:21-07:00

Yes that is all the documentation that is available. I am the only developer of Magick.NET and I don't have enough time to create proper documentation. I will try to add more documentation but I also want to add new features and improve the library so it's not that easy to make time for that.

I did some experimentation and it turns out that the Quantize part is the slowest part. This will also be called when you write the image so removing it doesn't really help as you also discovered. But I found a trick that will make sure the quantize part is skipped. When you call Posterize on the frame the number of colors doesn't need to be reduced anymore. I created a simple program that can be found here: https://www.dropbox.com/s/42625qgglwfup ... am.cs?dl=0. The output from the program is this on my machine:

Frame creation: 207 (207)
Optimize: 23 (230)
Writing: 6 (236)

So it takes 236ms on my machine in total and the output image is 21kb.
.NET + ImageMagick = Magick.NET https://github.com/dlemstra/Magick.NET, @MagickNET, Donate

Post Reply