image.Image接口中ColorModel()方法的目的是什么?

时间:2017-10-02 19:30:56

标签: go

Go image.Image界面有三种方法:Bounds(显然是确定图像大小所必需的),At(返回每个像素的实际颜色)和ColorModel。最后一个方法返回color.Model,它能够将任何模型的颜色转换为该图像使用的表示。

为什么ColorModel是此界面的一部分? image.Image类型的消费者如何使用它?如果我有一个图像img,而我对其底层表示一无所知,那么img.ColorModel()对我有什么好处?我可以将任何颜色转换为合适的模型,但我不知道我可以使用这种转换颜色;另外两种与图像交互的方式AtBounds,不要将颜色作为参数。

我错过了什么吗?是否有任何标准库函数调用ColorModel的{​​{1}}方法,以及用于什么?

2 个答案:

答案 0 :(得分:1)

我不确定我是否完全理解你的问题,但我不认为ColorModel()的目的是改变颜色。它只是为了获得颜色模型。

标准库主要在编码图像时使用它,就像在png包中一样:

switch m.ColorModel() {
case color.GrayModel:
    e.cb = cbG8
case color.Gray16Model:
    e.cb = cbG16
case color.RGBAModel, color.NRGBAModel, color.AlphaModel:
    if opaque(m) {
        e.cb = cbTC8
    } else {
        e.cb = cbTCA8
    }
default:
    if opaque(m) {
        e.cb = cbTC16
    } else {
        e.cb = cbTCA16
    }
}

可以在jpeg / writer中找到关于它的预期用途的另一个暗示:

// TODO(wathiede): switch on m.ColorModel() instead of type.

答案 1 :(得分:1)

扩大接受的答案:

虽然color.Model能够将颜色转换为不同的颜色类型,但如the docs中所述:

  

界面ColorModel描述了图像的颜色模型。

即。不是像素的颜色模型。它看起来很相似,但后者暗示图像可能包含具有不同颜色模型的像素。

注意image表示均匀颜色的矩形网格,即所有像素具有相同的颜色模型。理解image颜色模型后,将image投射到特定的具体图像类型会更好,更有效,然后直接在该特定图像上工作。以下片段说明了这个想法:

switch img.ColorModel() {
case color.RGBAModel:
    // Try to cast to RGBA first
    m, ok := img.(*image.RGBA)
    if !ok {
        //not an RGBA image, do generic/custom processing,
        //e.g. using interface exposed by image.Image
        return
    }

    //Direct pixel access for performance
    for y := m.Rect.Min.Y; y < m.Rect.Max.Y; y++ {
        yp := (y - m.Rect.Min.Y) * m.Stride
        for x := m.Rect.Min.X; x < m.Rect.Max.X; x++ {
            rgba := m.Pix[yp+(x-m.Rect.Min.X)*4:] //[]byte{r, g, b, a}
            //get rgba component
            r, g, b, a := rgba[0], rgba[1], rgba[2], rgba[3]

            //set r channel to RED
            rgba[0] = 255

            //...           
        }
    }
}
与以下代码相比,

更有效

// Less efficient image processing
// a type-switch on the color returned by the `At` method
b := img.Bounds()
for y := b.Min.Y; y < b.Max.Y; y++ {
    for x := b.Min.X; x < b.Max.X; x++ {
        col := img.At(x, y)
        switch col := col.(type) {
        case color.RGBA:
            //do something with pixel
        }
    }
}