【问题标题】:Java ImageIO: check if a PNG with alpha is opaque?Java ImageIO:检查带有 alpha 的 PNG 是否不透明?
【发布时间】:2020-05-08 02:49:40
【问题描述】:

我试图弄清楚如何检测带有 alpha 通道的 PNG 是否不透明。如果它是不透明的,则所有像素都有一个 100% 的透明度通道,因此应该可以转换为不支持透明度的 JPEG 等格式。

This answer 展示了如何检测 Alpha 通道,但如果图像不透明,则不会。

ImageMagick can apparently do it-format %[opaque],但我希望能够在纯 Java 中完成。

您知道是否可以使用 ImageIO 执行这种不透明检测?

【问题讨论】:

  • 在 ImageMagick 中,我通过获取 0 到 1(或 0 到 255)范围内的 alpha 通道的平均值(平均值)来做到这一点。如果平均值恰好为 1(或等效为 255),则它是完全不透明的。否则,图像会有一些透明度。

标签: java javax.imageio


【解决方案1】:

一种可能的方法是使用BufferedImage#getData 并蛮力检查所有像素并检查它们的alpha。如果一个像素没有 alpha 1.0,则图像不是不透明的。 Here 您可以找到一个很好的方法示例,但直接使用BufferedImage 而不是首先获得Raster

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class DetectImageTransparency {

    public static void main(String... args) throws IOException {

        File pngInput = new File("/tmp/duke.png");
        BufferedImage pngImage = ImageIO.read(pngInput);
        checkTransparency(pngImage);

        File jpgInput = new File("/tmp/duke.jpg");
        BufferedImage jpgImage = ImageIO.read(jpgInput);
        checkTransparency(jpgImage);
    }

    private static void checkTransparency(BufferedImage image){
        if (containsAlphaChannel(image)){
            System.out.println("image contains alpha channel");
        } else {
            System.out.println("image does NOT contain alpha channel");
        }

        if (containsTransparency(image)){
            System.out.println("image contains transparency");
        } else {
            System.out.println("Image does NOT contain transparency");
        }
    }

    private static boolean containsAlphaChannel(BufferedImage image){
        return image.getColorModel().hasAlpha();
    }

    private static boolean containsTransparency(BufferedImage image){
        for (int i = 0; i < image.getHeight(); i++) {
            for (int j = 0; j < image.getWidth(); j++) {
                if (isTransparent(image, j, i)){
                    return true;
                }
            }
        }
        return false;
    }

    public static boolean isTransparent(BufferedImage image, int x, int y ) {
        int pixel = image.getRGB(x,y);
        return (pixel>>24) == 0x00;
    }
}

注意:这不是我的工作。我添加了代码以使答案独立于链接。 Here 是对源的引用。

【讨论】:

  • 我尝试了你提到的第一种方法,但它返回 TRANSLUCENT 而 ImageMagick 说它是不透明的。
  • @Gauthier 是的,你是对的。我再次检查,返回值取决于图像格式,而不是实际图像数据。无论如何,我添加了一个链接,其中解释了如何检查像素并检查透明度。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-07
  • 2012-11-14
  • 2010-12-30
  • 2012-04-30
  • 1970-01-01
  • 2017-03-13
相关资源
最近更新 更多