使用Java或Python将8位(16色调色板)PNG转换为适当的4位(16色调色板)?

时间:2011-09-23 23:05:57

标签: java python png pypng

我有一堆图像,许多人手工做的是16色8位PNG格式,我需要16位格式,它们都有相同的调色板。

我正在搜索Google以寻找最好的图书馆,但我对这个具体问题并没有太多了解,所以我希望能够找到一些更有针对性的解决方案。

我正在尝试使用基于other answers I have found here的PIL,但没有运气。

img = Image.open('DownArrow_focused.png')
img = img.point(lambda i: i * 16, "L")
img.save('DownArrow_focused.png', 'PNG')

但这给了我一张灰度图像,而不是我想要的。

PIL无法正常工作,尝试使用PyPNG。 GIMP做到了这一点,但我有数百个这样的东西我需要批量处理它们。并获得批量转换,所以这不是一次性的事情。

基于Java的解决方案也是可以接受的,几乎任何我可以在Linux / OSX机器上从命令行运行的东西都是可以接受的。

2 个答案:

答案 0 :(得分:1)

在PNG中,调色板始终存储在RGB8中(每个索引=颜色为3个字节),具有任意(最多256个)条目数。如果您当前有一个带有16色调色板的8位图像(总共16个条目),则不需要更改托盘,只需重新打包像素字节(每个字节两个索引)。如果是这样,我认为您可以使用此代码(未经测试)PNGJ来执行此操作:

public static void reencode(String orig, String dest) {
    PngReader png1 = FileHelper.createPngReader(new File(orig));
    ImageInfo pnginfo1 = png1.imgInfo;
    ImageInfo pnginfo2 = new ImageInfo(pnginfo1.cols, pnginfo1.rows, 4, false,false,true);  
    PngWriter png2 = FileHelper.createPngWriter(new File(dest), pnginfo2, false);
    png2.copyChunksFirst(png1, ChunksToWrite.COPY_ALL);
    ImageLine l2 = new ImageLine(pnginfo2);
    for (int row = 0; row < pnginfo1.rows; row++) {
        ImageLine l1 = png1.readRow(row);
        l2.tf_pack(l1.scanline, false);
        l2.setRown(row);
        png2.writeRow(l2);
    }
    png1.end();
    png2.copyChunksLast(png1, ChunksToWrite.COPY_ALL);
    png2.end();
    System.out.println("Done");
}

在其他地方,如果您当前的调色板有16种“使用过的”颜色(但由于它包含未使用的颜色,其长度更长),您需要做一些工作,修改调色板块(但也可以这样做)。

答案 1 :(得分:0)

致电Netpbm计划 http://netpbm.sourceforge.net/ 使用以下命令从Python脚本开始:

$ pngtopnm test.png | pnmquant 16 | pnmtopng > test16.png

$ file test16.png
test16.png: PNG image data, 700 x 303, 4-bit colormap, non-interlaced

GIMP报告test16.png为Color space: Indexed color (16 colors), 我想这就是你想要的。

这不是纯粹的Python解决方案,但PIL也不是纯Python,也依赖于共享库。我认为你无法避免依赖某些外部图像软件。