颜色量化结果非常糟糕?

4
我正在尝试让我的应用程序导出动画 GIF,但是一旦颜色超过 256,量化算法就会启动并且出现问题。
这是我要转换的文件以及算法将其转换为的内容:

enter image description here

我正在使用的量化算法 在这里, Quantize.java,显然它是 ImageMagick 中使用的量化的 Java 版本,所以我觉得它应该是可靠的? 我是这样使用它的:
protected int[][] pixels;  // 2D array of RGB pixels of image
protected byte[] indexedPixels;

// ...

/**
 * Analyzes image colors and creates color map.
 */
protected void analyzePixels()
{
    // Quantize the pixels, get reduced color map and indexed array.
    // -------------------------------------------------------------
    colorPalette = Quantize.quantizeImage(pixels, 256);

    // Create indexed pixels array.
    // ----------------------------
    int i = 0;

    for (int x = 0, xSize = pixels.length; x < xSize; ++x)
    {
        for (int y = 0, ySize = pixels[x].length; y < ySize; ++y)
            indexedPixels[i++] = (byte) pixels[x][y];
    }
}

注意 - 当我将 static final boolean QUICK 设置为 false 时,算法将转换为以下内容:

enter image description here

它看起来不同了,但还是不对。 我真的希望能让这个算法运行起来,因为它比其他替代方案(NeuQuant)更快且生成的文件更小。我是否做得正确,或者这就是算法的工作方式?

你认为这行代码indexedPixels[i++] = (byte) pixels[x][y];会做什么? - Douglas Zare
1
@DouglasZare 这行代码 colorPalette = Quantize.quantizeImage(pixels, 256); 将 pixels[][] 的内容转换为 colorMap[] 中的索引,从而将每个像素指向 colorMap[] 中的一种颜色。你所提到的那行代码只是将其从二维数组中清空,并放入一个一维字节数组中,因为这是我正在使用的 LZWEncoder 所期望的格式。 - yesbutmaybeno
哇,quantizeImage 的副作用真的很大啊。你说的 colorMap[] 是指 colorPalette 吗?你确定要撤销每个索引从 int 到 byte 的转换,而不是简单地将其转换回 int 吗?例如,颜色编号 200(作为 int)变成了 -56(作为 byte)。 - Douglas Zare
@DouglasZare 看起来你的回答很棒。我刚试了一下(完全摆脱了字节,只用整数),但结果完全相同。不过现在 indexedPixels[] 数组看起来更正确了,没有负数,内容从 0-255。 - yesbutmaybeno
2个回答

0

我最终放弃了Quantize.java,找到了Java Imaging Utilities(http://sourceforge.net/projects/jiu/),它提供了一些不错的颜色/图像量化选项。虽然结果并不完美,但还是可以接受的。


0

你需要添加一个抖动算法.. 可以谷歌一下.. 我相信Java内置了一些算法,但是我从维基百科上找到的一个纯Java示例对我很有用。因为我想要通过操作原始字节数组和整型数组来提高效率,而不仅仅使用getPixel/setPixel。


我没有试过这个,但是一个抖动算法会防止图像变成红色(如OP中的第一个例子)?那似乎不对。看起来我正在使用的量化算法有问题,因为NeuQuant确实足够精确地工作,但是速度慢5倍,文件大小大3倍。 - yesbutmaybeno

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接