4

I recently acquired the NuGet Package Nquant.

I plan to use this to reduce the file size of the bitmap and save it into PNG. But I get this error:

The image you are attempting to quantize does not contain a 32 bit ARGB palette. This image has a bit depth of 8 with 256 colors.

Does anyone here has used Nquant? And have you encountered this error and how did you fix it?

My code for your reference:

var bitmap = new Bitmap(width, jbgsize / height, PixelFormat.Format8bppIndexed);
        ColorPalette pal = bitmap.Palette;
        for (int i = 0; i <= 255; i++)
        {
            // create greyscale color table
            pal.Entries[i] = Color.FromArgb(i, i, i);
        }
        bitmap.Palette = pal; // you need to re-set this property to force the new ColorPalette

        var bitmap_data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
        Marshal.Copy(output, 0, bitmap_data.Scan0, output.Length);
        bitmap.UnlockBits(bitmap_data);
        MemoryStream stream = new MemoryStream();
var quantizer = new WuQuantizer();
        using(var bmp = new Bitmap(bitmap))
        {
            using (var quantized = quantizer.QuantizeImage(bitmap))
            {
                quantized.Save(stream, ImageFormat.Png);
            }
        }

        byteArray = stream.ToArray();
        return byteArray.Concat(output).ToArray();
TerribleDog
  • 1,237
  • 1
  • 8
  • 31
  • The link you provided says that Nquant converts 32 bit images to 8 bit images. The error message you quoted is telling you that the image you're trying to convert is already 8-bit. You probably need to create a 32 bit bitmap on your first line where you create a `new Bitmap`, but you used `PixelFormat.Format8bppIndexed` – zivkan Jan 18 '19 at 00:47
  • Now I get it. I though Nquant can reduce 8bpp images. Do you have something for that? @zivkan – TerribleDog Jan 18 '19 at 02:19
  • You could convert your 8-bit source file to 32-bit, just make sure you upscale to a lossless format like uncompressed bitmap to minimise quality loss. But I've never done anything with images, I just try to answer NuGet questions. I was going to ignore this question since it has nothing to do with NuGet, but the error message seemed obvious enough. – zivkan Jan 18 '19 at 18:15

1 Answers1

1

You can convert your image to Format32bppPArgb and then Quantize it.

This is my working example of that decrease image size for ~3 times.

public static byte[] CompressImageStream(byte[] imageStream)
{
    using (var ms = new MemoryStream(imageStream))
    using (var original = new Bitmap(ms))
    using (var clonedWith32PixelsFormat = new Bitmap(
        original.Width,
        original.Height,
        PixelFormat.Format32bppPArgb))
    {
        using (Graphics gr = Graphics.FromImage(clonedWith32PixelsFormat))
        {
            gr.DrawImage(
                original,
                new Rectangle(0, 0, clonedWith32PixelsFormat.Width, clonedWith32PixelsFormat.Height));
        }

        using (Image compressedImage = new WuQuantizer().QuantizeImage(clonedWith32PixelsFormat))
        {
            return ImageToByteArray(compressedImage);
        }
    }
}

public static byte[] ImageToByteArray(Image image)
{
    if (image == null)
    {
        throw new ArgumentNullException(nameof(image));
    }

    using (var stream = new MemoryStream())
    {
        image.Save(stream, ImageFormat.Png);
        return stream.ToArray();
    }
}
shatulsky
  • 306
  • 2
  • 10