使用具有 alpha 的 PNG 改进 Java ImageIO read/write

Improving Java ImageIO read/write with PNG that has alpha

我有一个大的 PNG 图像 (600x600),我的应用程序使图像不透明并写出文件。问题是 ImageIO 的性能很糟糕。还有其他选择吗?我要求图像不透明。以下是我正在做的事情:

    BufferedImage buf = ImageIO.read(localUrl);
    float[] scales = {1f, 1f, 1f, 1f};  // R, G, B, A
    float[] offsets = {0f, 0f, 0f, 1f};   // R, G, B, A
    RescaleOp rescaler = new RescaleOp(scales, offsets, null);
    BufferedImage opaque = rescaler.filter(buf, null);
    File outputfile = new File(localUrl.getPath());
    ImageIO.write(opaque, "png", outputfile);

如果您只是想摆脱透明度,那么在这里使用 RescaleOp 并不是完全必要的。一个更简单的解决方案是在背景上绘制图像,如下所示:

Color bgColor = Color.WHITE;

BufferedImage foreground = ImageIO.read(localUrl);
int width = foreground.getWidth();
int height = foreground.getHeight();
BufferedImage background = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = background.createGraphics();
g.setColor(bgColor);
g.fillRect(0, 0, width, height);
g.drawImage(foreground, 0, 0, null);
g.dispose();
File outputfile = new File(localUrl.getPath());
ImageIO.write(background, "png", outputfile);

这似乎是一种更简单的处理方法,可能需要更少的处理能力,但我怀疑会有很大的不同。如果您对从硬盘驱动器读取/写入图像的速度不满意,您几乎无能为力。

PNGJ:

private static void removeAlpha(File file1,File file2) {
    PngReaderByte reader = new PngReaderByte(file1);
    ImageInfo info = reader.imgInfo;
    PngWriter writer = new PngWriter(file2,info);
    writer.setFilterPreserve(true);
    writer.setCompLevel(6);
    writer.copyChunksFrom(reader.getChunksList(), ChunkCopyBehaviour.COPY_ALL_SAFE);
    if( info.bitDepth != 8 ||info.channels!=4) throw new RuntimeException("expected 8bits RGBA ");
    while(reader.hasMoreRows()) {
        ImageLineByte line = reader.readRowByte();
        byte [] buf = line.getScanlineByte();
        for(int i=0,j=3;i<info.cols;i++,j+=4)
            buf[j]=(byte)255;
        writer.writeRow(line);
    }
    reader.end();
    writer.end();
}

我不确定这是否会提高性能。请记住,(与 Parker Hoyes 的回答相反)这只会杀死 alpha 通道,但它不会与某些背景颜色混合(因此 "original" 颜色将出现在以前透明的现在不透明的区域中).