使用 NQUANT 的图像量化误差

Posted

技术标签:

【中文标题】使用 NQUANT 的图像量化误差【英文标题】:Error in Quantization of Image using NQUANT 【发布时间】:2019-06-11 07:01:35 【问题描述】:

我最近获得了 NuGet 包Nquant。

我打算使用它来减小位图的文件大小并将其保存为 PNG。但我得到这个错误:

您尝试量化的图像不包含 32 位 ARGB 调色板。此图像的位深度为 8,有 256 种颜色。

这里有人用过Nquant吗?您是否遇到过这个错误,您是如何解决的?

我的代码供你参考:

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();

【问题讨论】:

您提供的链接说 Nquant 将 32 位图像转换为 8 位图像。您引用的错误消息告诉您,您尝试转换的图像已经是 8 位的。您可能需要在创建new Bitmap 的第一行创建一个 32 位位图,但您使用了PixelFormat.Format8bppIndexed 现在我明白了。我虽然 Nquant 可以减少 8bpp 图像。你有什么东西吗? @zivkan 您可以将您的 8 位源文件转换为 32 位文件,只需确保您升级为无损格式(如未压缩位图)以最大程度地减少质量损失。但我从未对图像做过任何事情,我只是尝试回答 NuGet 问题。我打算忽略这个问题,因为它与 NuGet 无关,但错误消息似乎很明显。 【参考方案1】:

您可以将图像转换为 Format32bppPArgb,然后对其进行量化。

这是我将图像尺寸减小约 3 倍的工作示例。

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();
    

【讨论】:

以上是关于使用 NQUANT 的图像量化误差的主要内容,如果未能解决你的问题,请参考以下文章

不同量化电平数对信号有啥影响

误差逆传播(error BackPropagation, BP)算法推导及向量化表示

(LSB: Least Significant Bit)

量化(减少图像的颜色)

有效的 gif/图像颜色量化?

学习向量量化在matlab中效果不佳