确定图像是否具有Alpha通道的最佳方法是什么?

时间:2017-05-22 05:52:36

标签: image go alpha

我需要判断图像是否有alpha通道,所以我写这样的代码。

var HaveAlpha = func(Image image.Image) bool {
    switch Image.ColorModel() {
    case color.YCbCrModel, color.CMYKModel:
        return false
    case color.RGBAModel:
        return !Image.(*image.RGBA).Opaque()
    }
    // ...
    return false
}

因此,我需要列出所有ColorModel类型并使用Opaque()来确定图片是否具有Alpha通道(因为我无法在类型{{1}中使用Opaque()方法直接)。如果图像具有Alpha通道但图像中的所有像素都是不透明的(该图像中的所有RGBA像素都像image.Image),则此代码可能会返回错误的答案。

在Golang中是否有正确或更好的方法来判断图片是否有alpha通道?

1 个答案:

答案 0 :(得分:2)

您可以使用type assertion来检查image.Image接口类型中存储的具体值是否具有Opaque() bool方法,如果是,则只需调用它并返回其结果。请注意,image包中的所有具体图像类型都有Opaque()方法,因此这将涵盖大多数情况。

如果图像没有这样的Opaque()方法,则循环图像的所有像素,并检查是否有任何像素具有除0xff以外的alpha值,这意味着它' s不透明。

请注意,Image.At()具有一般color.Color接口类型的返回类型,它只保证单个方法:Color.RGBA()。此RGBA()方法返回 alpha-premultiplied 红色,绿色,蓝色和alpha分量,因此如果某个像素具有0xff alpha值,则该值等于0xffff时" alpha-premultiplied",这就是我们需要比较的内容。

func Opaque(im image.Image) bool {
    // Check if image has Opaque() method:
    if oim, ok := im.(interface {
        Opaque() bool
    }); ok {
        return oim.Opaque() // It does, call it and return its result!
    }

    // No Opaque() method, we need to loop through all pixels and check manually:
    rect := im.Bounds()
    for y := rect.Min.Y; y < rect.Max.Y; y++ {
        for x := rect.Min.X; x < rect.Max.X; x++ {
            if _, _, _, a := im.At(x, y).RGBA(); a != 0xffff {
                return false // Found a non-opaque pixel: image is non-opaque
            }
        }

    }
    return true // All pixels are opaque, so is the image
}

如果图片没有Alpha通道,则上述Opaque()函数将返回true,或者它具有所有像素都是不透明的。当且仅当图像具有Alpha通道并且至少有一个像素不是(完全)不透明时,它才会返回false

注意:如果图片确实有Opaque()方法,您可以确定它需要考虑现有像素及其alpha值,例如image.RGBA.Opaque()与我们上面所做的相似,扫描整个图像;但我们必须以一般方式进行,并且具体图像的Opaque()实现可能更有效(因此强烈建议使用&#34;运送&#34; Opaque()方法它是可用的)。例如,image.YCbCr.Opaque()的实现是一个简单的return true语句,因为YCbCr图像没有Alpha通道。