I need to load an image and search for colors and replace them. For example on an image I need to search for all red pixels and convert them to purple.
I am doing the following (img
is a valid .png
image):
func colorize(img image.Image) {
b := image.NewRGBA(img.Bounds())
draw.Draw(b, b.Bounds(), img, image.ZP, draw.Src)
for x := 0; x < b.Bounds().Dx(); x++ {
for y := 0; y < b.Bounds().Dy(); y++ {
log.Println(b.At(x, y).RGBA())
}
}
}
Thing is img.At().RGBA()
doesn't seem to return the proper R, G, B, A codes? I am getting numbers bigger than 255 for example.
So how should I read all the image pixels while being able to know the x and y position of them?
img.At().RGBA()
is Color.RGBA()
. Quoting its doc:
// RGBA returns the alpha-premultiplied red, green, blue and alpha values
// for the color. Each value ranges within [0, 0xffff], but is represented
// by a uint32 so that multiplying by a blend factor up to 0xffff will not
// overflow.
//
// An alpha-premultiplied color component c has been scaled by alpha (a),
// so has valid values 0 <= c <= a.
Components returned by RGBA()
are in range 0..0xffff
, not 0..0xff
, and they are also alpha-premultiplied.
One way to get back the red, green, blue components in the 0..255
range is to shift right by 8 for example:
r, g, b, a := b.At(x, y).RGBA()
r, g, b, a = r>>8, g>>8, b>>8, a>>8
log.Println(r, g, b) // Now in range 0..255
color.RGBA
Another way is to convert the color to color.RGBA
which is a struct, containing the components plain and simple:
type RGBA struct {
R, G, B, A uint8
}
Since you are using image.NewRGBA()
which returns an image of type image.RGBA
, the colors returned by the Image.At()
method will be of dynamic type color.RGBA
, so you can simply use a type assertion:
rgbacol := b.At(x, y).(color.RGBA)
log.Println(rgbacol.R, rgbacol.G, rgbacol.B, rgbacol.A)
In general (if image is not of type image.RGBA
), Image.At()
may or may not be of concrete type color.RGBA
.
So in the general case you need to convert the color to a value of type color.RGBA
. Conversions between color models are modeled by color.Model
, and the image/color
package has predefined converters. What you need is color.RGBAModel
. color.RGBAModel.Convert()
will return a color.Color
value whose dynamic type is surely color.RGBA
.
Example using color.RGBAModel
:
var c color.Color
c = color.Gray{160}
rgbacol := color.RGBAModel.Convert(c).(color.RGBA)
fmt.Println(rgbacol.R, rgbacol.G, rgbacol.B, rgbacol.A)
Output (try it on the Go Playground):
160 160 160 255
So in your loop do:
rgbacol := color.RGBAModel.Convert(b.At(x, y).(color.RGBA)
// rgbacol is a struct of type color.RGBA, components are in range 0..255
Note:
Above solutions still give you back the alpha pre-multiplied components. If you want to undo the alpha pre-multiplication, you may use color.NRGBAModel
converter (instead of color.RGBAModel
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With