Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang image ColorModel()

Tags:

image

colors

go

I am teaching myself Go. I decided to try some computer vision stuff. First things first I was going to make an image histogram. I'm trying to get the color model so I know the intensity range of the pixels. When I print image.ColorModel() it gives me a cryptic hexidecimal output: color model: &{0x492f70} I couldn't find any explanation in the docs. I was expecting some sort of enum type thing that would map to a color model like, NRGBA, RGBA, etc.

What does that hexidecimal mean? What does the ampersand curly braces &{...} mean? Also what is the "N" in NRGBA I can't find anything about it.

like image 529
noel Avatar asked Dec 11 '22 10:12

noel


2 Answers

To extend putu's answer, comparing the returned color model to the "prepared" models of the image package only works if one of those models is used, else all comparison will result in false. Also it is quite inconvenient to list and compare to all possible models.

Instead to find out a talkative form of the color model, we may use this little trick: try to convert any color using the color model of the image. A concrete color model converts all color values (implementations) to the color type / implementation used by the image. Printing the type of the resulting color will tell you what you are looking for.

Example:

col := color.RGBA{} // This is the "any" color we convert
var img image.Image

img = &image.NRGBA{}
fmt.Printf("%T\n", img.ColorModel().Convert(col))

img = &image.Gray16{}
fmt.Printf("%T\n", img.ColorModel().Convert(col))

img = &image.NYCbCrA{}
fmt.Printf("%T\n", img.ColorModel().Convert(col))

img = &image.Paletted{}
fmt.Printf("%T\n", img.ColorModel().Convert(col))

Output (try it on the Go Playground):

color.NRGBA
color.Gray16
color.NYCbCrA
<nil>

As can be seen, an image of type *image.NRGBA models colors using color.NRGBA, an image of type *image.Gray16 models colors using color.Gray16 etc. As a last example I used *image.Paletted, where the result was nil, because the image's palette was empty.

To quickly fix the nil palette, let's provide an initial palette:

img = &image.Paletted{Palette: []color.Color{color.Gray16{}}}
fmt.Printf("%T\n", img.ColorModel().Convert(col))

Now the output will be (try this on the Go Playground):

color.Gray16
like image 155
icza Avatar answered Dec 17 '22 18:12

icza


An Image is declared as an interface having the following method sets:

type Image interface {
    ColorModel() color.Model
    Bounds() Rectangle
    At(x, y int) color.Color
}

Method ColorModel() returns an interface named color.Model which is declared as:

type Model interface {
    Convert(c Color) Color
}

Since the ColorModel returns an interface, you can't dereference it using *. What you see as &{0x492f70} is the underlying data structure which implements color.Model interface, and in this case, it is a pointer which points to address 0x492f70. Usually, it doesn't matter how ColorModel's underlying data is implemented (any type is valid as long as it has Convert(c Color) Color method), but if you're curious, the models for several standard color types are implemented as a pointer to unexported struct declared as:

type modelFunc struct {
    f func(Color) Color
}

What you got when you print the ColorModel is a pointer to this struct. Try print it using fmt.Printf("%+v\n", img.ColorModel()), you will see an output likes &{f:0x492f70}, in which f denotes the field name in the above struct.

In the documentation, there are several models for the standard color types, e.g. color.NRGBAModel, color.GrayModel, etc. If you want to detect the image's color model, you can compare it to these standard models, e.g.

if img.ColorModel() == color.RGBAModel {
    //32-bit RGBA color, each R,G,B, A component requires 8-bits
} else if img.ColorModel() == color.GrayModel {
    //8-bit grayscale
}
//...
like image 26
putu Avatar answered Dec 17 '22 19:12

putu