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

What is the best way to decide if an image has alpha channel?

我需要判断一个图像是否有 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 通道(因为我不能在类型 [=] 中使用 Opaque() 方法14=]直接)。如果图像有 alpha 通道但图像中的所有像素都是不透明的(该图像中所有像素的 RGBA 都像 (*,*,*,255)),则此代码可能 return 错误答案。

在 Golang 中是否有正确或更好的方法来确定图像是否具有 alpha 通道?

您可以使用 type assertion to check if the concrete value stored in the image.Image interface type has an Opaque() bool method, and if so, simply call that and return its result. Note that all concrete image types in the image 包确实有一个 Opaque() 方法,所以这将涵盖大多数情况。

如果图像没有这样的Opaque()方法,遍历图像的所有像素并检查是否有任何像素的alpha值不是0xff,这意味着它不是-不透明。

注意Image.At()有一个通用color.Color接口类型的return类型,只保证一个方法:Color.RGBA()。此 RGBA() 方法 return 是 alpha 预乘 红色、绿色、蓝色和 alpha 分量,因此如果像素具有 0xff alpha 值,则当 "alpha-premultiplied" 时等于 0xffff,所以这就是我们需要比较的内容。

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() 函数将 return true。它 returns false 当且仅当图像具有 alpha 通道并且至少有 1 个像素不是(完全)不透明的。

注意: 如果图像确实有 Opaque() 方法,您可以确定它考虑了现有像素及其 alpha 值,例如 image.RGBA.Opaque() also scans the entire image similarly to what we did above; but we had to do it in a general way, and Opaque() implementations of concrete images may be much more efficient (so it is highly recommended to use the "shipped" Opaque() method if it is available). As an example, implementation of image.YCbCr.Opaque() 是一个简单的 return true 语句,因为 YCbCr 图像没有 alpha 通道。