dlemstra / Magick.NET

The .NET library for ImageMagick
Apache License 2.0
3.47k stars 415 forks source link

Color issue when using map operation with no dithering. #133

Closed tinggit closed 6 years ago

tinggit commented 6 years ago

Hi there,

I was wondering if anyone has come across any issues with inaccurate colors when using map operation with no dithering. I have an image that contains a large percentage of sand color. When I use a palette that covers a wide range of colors, it should be able to produce an image that closely resemble the original image. However, it seems that the sand colors are replaced with greys.

Strangely, when I used dithering (Riemersma or others) it produced an image that contain the missing sand colors, albeit with some hints of green colors in the image.

I am using Magick.NET-Q16-AnyCPU v7.2.1.

To illustrate this issue, please see the images below.

original image original

pallete pallete

mapped image without dithering mapped

mapped image with Riemersma dithering mappedriemersma

Are there any configurations I can apply to make the map operation (with no dithering) perform better in this case?

By the way, this is an awesome product!! Great work!!

Thanks

dlemstra commented 6 years ago

Could you post a small code sample that I could use to test this issue?

tinggit commented 6 years ago

Thanks for the quick reply.

Using the original and the palette images from above, please find below the sample code:

        var settingsNoDither = new QuantizeSettings() { DitherMethod = DitherMethod.No };
        var settingsRiemersma = new QuantizeSettings() { DitherMethod = DitherMethod.Riemersma };
        var mapped1 = new MagickImage("original.gif");
        var mapped2 = new MagickImage("original.gif");
        var palette1 = new MagickImage("palette.gif");
        var palette2 = new MagickImage("palette.gif");

        mapped1.Map(palette1, settingsNoDither);
        mapped2.Map(palette2, settingsRiemersma);

        mapped1.Write("mapped.gif");
        mapped2.Write("mappedRiemersma.gif");

Thanks!

dlemstra commented 6 years ago

Your pallette contains a lot of gray colors so I chose a different approach. I get an image that has the same colors with the following command:

using (var image = new MagickImage(@"i:\original.gif"))
{
    using (var pallette = image.UniqueColors())
    {
        var settingsNoDither = new QuantizeSettings() { DitherMethod = DitherMethod.No };
        image.Map(pallette, settingsNoDither);
    }

    image.Write(@"i:\mapped.gif");
}

But as you might have noticed your image contains less than 256 different colors per channel so you should get the same pixels. I am not sure what you will need to do when you have more than 256 different colors. Do you also need to do this with other images that have more different colors?

tinggit commented 6 years ago

Thanks for looking into this. Your suggestion gave me some ideas for the solution. I do not have any control over the images chosen, but I think the solution would be to provide a wider array of colors for the palette. Cheers!