image defines the Image interface and the concrete pixel-buffer types (RGBA, NRGBA, Gray, Paletted) every Go image works with. image/png and image/jpeg add format-specific encoding and decoding; image/draw adds compositing one image onto another.
image.NewRGBA allocates a blank canvas from a Rectangle. Set writes one pixel; At reads one back, both through the same color.Color interface.
img := image.NewRGBA(image.Rect(0, 0, 4, 4))
img.Set(1, 1, color.RGBA{R: 255, A: 255})
fmt.Println(img.Bounds())
fmt.Println(img.At(1, 1))Bounds reports the canvas as a half-open rectangle, (0,0)-(4,4) for 4x4 pixels. The pixel just set reads back as {255 0 0 255}: red, no green, no blue, fully opaque.
(0,0)-(4,4)
{255 0 0 255}Examples
NewRGBA allocates a blank canvas; Set writes one pixel at a time. png.Encode is lossless, so the same pixels come back byte-for-byte on decode.
img := image.NewRGBA(image.Rect(0, 0, 100, 100))
for y := 0; y < 100; y++ {
for x := 0; x < 100; x++ {
img.Set(x, y, color.RGBA{R: uint8(x * 2), G: uint8(y * 2), B: 120, A: 255})
}
}
f, err := os.Create("gradient.png")
if err != nil {
log.Fatal(err)
}
defer f.Close()
if err := png.Encode(f, img); err != nil {
log.Fatal(err)
}
fmt.Println("wrote", "gradient.png")wrote gradient.pngimage.Decode picks the format automatically by sniffing the header, but only formats registered by an imported package are recognized. image/png and image/jpeg register themselves in their own init functions, so a blank import is enough when the decoded value itself isn't needed by name.
import (
"image"
_ "image/jpeg"
_ "image/png"
)
f, err := os.Open("photo.png")
if err != nil {
log.Fatal(err)
}
defer f.Close()
img, format, err := image.Decode(f)
if err != nil {
log.Fatal(err)
}
fmt.Println(format, img.Bounds())png (0,0)-(1200,800)Any image.Image decoded from one format can be re-encoded in another; the decode step doesn't care which package produced the bytes. A small, sharp-edged image like this gradient can end up larger as JPEG than PNG, since JPEG's block-based compression has a fixed per-block cost that a photograph's noise usually hides.
img, format, err := image.Decode(pngFile)
if err != nil {
log.Fatal(err)
}
fmt.Println("decoded format:", format)
out, err := os.Create("converted.jpg")
if err != nil {
log.Fatal(err)
}
defer out.Close()
jpeg.Encode(out, img, &jpeg.Options{Quality: 80})decoded format: pngdraw.Src overwrites the destination outright; draw.Over alpha-blends instead, the standard way to layer a translucent shape onto an existing image. color.NRGBA takes R/G/B/A as independent values; color.RGBA's fields are already alpha-premultiplied, so setting them directly like this Over example would produce broken colors.
base := image.NewRGBA(image.Rect(0, 0, 100, 60))
draw.Draw(base, base.Bounds(), &image.Uniform{C: color.RGBA{30, 30, 40, 255}}, image.Point{}, draw.Src)
overlay := &image.Uniform{C: color.NRGBA{R: 255, G: 200, B: 0, A: 120}}
box := image.Rect(20, 15, 80, 45)
draw.Draw(base, box, overlay, image.Point{}, draw.Over)
fmt.Println(base.At(10, 10)) // outside the box: untouched
fmt.Println(base.At(40, 30)) // inside the box: blended{30 30 40 255}
{136 110 21 255}No library draws a fractal directly; the image is just a canvas colored one pixel at a time by escape-time iteration, the same At/Set primitives as any other image.
img := image.NewRGBA(image.Rect(0, 0, 320, 200))
for py := 0; py < 200; py++ {
y := (float64(py)/200)*2.4 - 1.2
for px := 0; px < 320; px++ {
x := (float64(px)/320)*3.2 - 2.2
img.Set(px, py, mandelbrotColor(complex(x, y)))
}
}
f, _ := os.Create("mandelbrot.png")
defer f.Close()
png.Encode(f, img)wrote mandelbrot.png
Output of the Mandelbrot set example above.
image package core
| Function | Description |
|---|---|
type Image interface{ ColorModel() color.Model; Bounds() Rectangle; At(x, y int) color.Color } | The interface every image type satisfies: a color model, a bounding rectangle, and per-pixel lookup. |
type Point struct{ X, Y int } | A single coordinate. |
Pt(X, Y int) Point image.Pt(10, 20) | Shorthand for Point{X, Y}. |
type Rectangle struct{ Min, Max Point } | A rectangle spanning [Min, Max), Max exclusive on both axes. |
Rect(x0, y0, x1, y1 int) Rectangle image.Rect(0, 0, 100, 60) | Shorthand for a Rectangle with Min{x0,y0} and Max{x1,y1}. |
(Rectangle) Dx() int / Dy() int | The rectangle's width and height in pixels. |
(Rectangle) In(r Rectangle) bool | Reports whether the rectangle is entirely within r. |
NewRGBA(r Rectangle) *RGBA image.NewRGBA(image.Rect(0, 0, 100, 60)) | An in-memory, alpha-premultiplied 8-bit-per-channel canvas. |
NewNRGBA(r Rectangle) *NRGBA | Like NewRGBA, but channels aren't alpha-premultiplied. |
| |
NewGray(r Rectangle) *Gray | An 8-bit grayscale canvas. |
NewPaletted(r Rectangle, p color.Palette) *Paletted | A canvas backed by a fixed color palette; what GIF frames use. |
(*RGBA) Set(x, y int, c color.Color) img.Set(1, 1, color.RGBA{R: 255, A: 255}) | Writes a pixel, converting c to the image's own color model. |
type Uniform struct{ C color.Color } | An infinite image of one solid color, useful as a fill source for image/draw. |
Decode(r io.Reader) (Image, string, error) | Decodes an image in any registered format, returning the format name. |
DecodeConfig(r io.Reader) (Config, string, error) | Reads only the header: dimensions and color model, without decoding pixel data. |
RegisterFormat(name, magic string, decode func(io.Reader) (Image, error), decodeConfig func(io.Reader) (Config, error)) | Registers a format's decoder; called by each format package's own init, e.g. image/png's. |
type Config struct{ ColorModel color.Model; Width, Height int } | An image's dimensions and color model without its pixel data. |
ErrFormat error | Returned by Decode when no registered format recognizes the input. |
image/color
| Function | Description |
|---|---|
type Color interface{ RGBA() (r, g, b, a uint32) } | The interface every color type satisfies; values are alpha-premultiplied and scaled to 16 bits. |
type Model interface{ Convert(c Color) Color } | Converts an arbitrary Color into one image's own color representation. |
type RGBA struct{ R, G, B, A uint8 } | 8-bit color, alpha-premultiplied. |
| |
type NRGBA struct{ R, G, B, A uint8 } | 8-bit color, not alpha-premultiplied; the type to reach for when specifying R/G/B independently of A. |
type Gray struct{ Y uint8 } | 8-bit grayscale. |
type Alpha struct{ A uint8 } | 8-bit alpha only, no color. |
RGBAModel, NRGBAModel, GrayModel, AlphaModel Model color.GrayModel.Convert(c) | Predefined Models matching each color type above. |
type Palette []Color | An ordered set of colors, e.g. the fixed palette a GIF frame draws from. |
(Palette) Index(c Color) int | Returns the palette entry closest to c. |
(Palette) Convert(c Color) Color | Returns the closest palette entry itself, not just its index. |
image/png
| Function | Description |
|---|---|
Encode(w io.Writer, m image.Image) error | Writes m to w as a PNG. Lossless; output size depends only on compression, not a quality setting. |
Decode(r io.Reader) (image.Image, error) | Decodes a PNG. |
DecodeConfig(r io.Reader) (image.Config, error) | Reads a PNG's dimensions and color model without decoding pixel data. |
type Encoder struct{ CompressionLevel CompressionLevel } | Use Encoder.Encode instead of the package-level Encode to control compression. |
DefaultCompression, NoCompression, BestSpeed, BestCompression CompressionLevel | The CompressionLevel values Encoder.CompressionLevel accepts. |
image/jpeg
| Function | Description |
|---|---|
Encode(w io.Writer, m image.Image, o *Options) error jpeg.Encode(w, img, &jpeg.Options{Quality: 80}) | Writes m to w as a JPEG; a nil Options uses the default quality. |
type Options struct{ Quality int } | Quality from 1 to 100; higher keeps more detail at a larger file size. |
Decode(r io.Reader) (image.Image, error) | Decodes a JPEG. The concrete type is usually *image.YCbCr, JPEG's native color model. |
DecodeConfig(r io.Reader) (image.Config, error) | Reads a JPEG's dimensions and color model without decoding pixel data. |
type FormatError string | The error type Decode returns for malformed JPEG data. |
image/draw
| Function | Description |
|---|---|
Draw(dst Image, r Rectangle, src image.Image, sp Point, op Op) draw.Draw(dst, r, src, sp, draw.Over) | Copies src onto dst within r, aligning src's sp to r's top-left corner. |
Src, Over Op | Src overwrites dst outright; Over alpha-blends src on top of dst's existing pixels. |
type Image interface{ image.Image; Set(x, y int, c color.Color) } | The mutable subset of image.Image that Draw requires as a destination. |
DrawMask(dst Image, r Rectangle, src image.Image, sp Point, mask image.Image, mp Point, op Op) | Like Draw, but mask's alpha channel scales src's contribution per pixel. |
type Drawer interface{ Draw(dst Image, r Rectangle, src image.Image, sp Point) } | The interface FloydSteinberg and other ditherers implement. |
Gotchas
image.Decodeonly recognizes formats registered by an imported package. Forgetting_ "image/jpeg"or_ "image/png"makes it fail withimage: unknown formateven on a well-formed file.image.Imagehas noSetmethod, onlyAt. Mutating pixels needs a concrete type like*image.RGBA, or the narrowerdraw.Imageinterface that addsSetback.- JPEG is lossy. Decoding a JPEG, editing it, and re-encoding it degrades quality further each round trip; PNG round-trips losslessly.
jpeg.Decodeusually returns a*image.YCbCr, not*image.RGBA, since that's JPEG's native color model. CallingAtstill works through theImageinterface either way.