image/png
| Language | Go (standard library) |
|---|---|
| License | BSD 3-Clause |
| Repository | go.googlesource.com/go |
| Documentation | pkg.go.dev/image/png |
| Depends on | nothing (pure Go) |
| Read / write | yes / yes, all color types and bit depths; no text chunks, no APNG |
image/png is part of the Go standard library. It decodes every PNG color type (including 16-bit and palette images with transparency) into the matching image.Image type, and encodes any image.Image. Importing it also registers PNG with image.Decode, so a program can open PNG, JPEG and GIF files with the same call.
It ignores ancillary chunks: there is no API to read or write text (tEXt, iTXt), pHYs or color profiles, and APNG files decode as their first frame. For resizing and cropping use imaging or golang.org/x/image/draw.
Installation#
Nothing to install, image/png comes with Go.
Basic usage: read and write a PNG#
package main
import (
"fmt"
"image"
"image/color"
"image/draw"
"image/png"
"log"
"os"
)
func main() {
f, err := os.Open("in.png")
if err != nil {
log.Fatal(err)
}
defer f.Close()
img, err := png.Decode(f)
if err != nil {
log.Fatal(err)
}
b := img.Bounds()
fmt.Printf("%d x %d, %T\n", b.Dx(), b.Dy(), img) // e.g. *image.NRGBA
// copy to an editable RGBA image and draw a red square
rgba := image.NewRGBA(b)
draw.Draw(rgba, b, img, b.Min, draw.Src)
red := image.NewUniform(color.RGBA{255, 0, 0, 255})
draw.Draw(rgba, image.Rect(0, 0, 20, 20), red, image.Point{}, draw.Src)
out, err := os.Create("out.png")
if err != nil {
log.Fatal(err)
}
defer out.Close()
if err := png.Encode(out, rgba); err != nil {
log.Fatal(err)
}
}
How to get PNG width and height without decoding#
png.DecodeConfig reads only the header:
f, err := os.Open("in.png")
if err != nil {
log.Fatal(err)
}
defer f.Close()
cfg, err := png.DecodeConfig(f)
if err != nil {
log.Fatal(err)
}
fmt.Println(cfg.Width, "x", cfg.Height)
How to set PNG compression level#
enc := png.Encoder{CompressionLevel: png.BestCompression}
// other levels: png.DefaultCompression, png.NoCompression, png.BestSpeed
if err := enc.Encode(out, img); err != nil {
log.Fatal(err)
}
When you encode many images, set Encoder.BufferPool to reuse buffers between calls.
How to open PNG, JPEG or GIF with one function#
Import the decoders for their side effect, then use image.Decode:
import (
"image"
_ "image/gif"
_ "image/jpeg"
_ "image/png"
)
img, format, err := image.Decode(f) // format is "png", "jpeg" or "gif"
How to convert PNG to JPEG#
JPEG has no alpha. Draw the PNG on a white background, then encode:
import (
"image"
"image/color"
"image/draw"
"image/jpeg"
"io"
)
func pngToJPEG(src image.Image, out io.Writer) error {
b := src.Bounds()
dst := image.NewRGBA(b)
draw.Draw(dst, b, image.NewUniform(color.White), image.Point{}, draw.Src)
draw.Draw(dst, b, src, b.Min, draw.Over)
return jpeg.Encode(out, dst, &jpeg.Options{Quality: 85})
}
Tips#
- The encoder picks the color type from the image type:
*image.Graygives a grayscale PNG,*image.Paletteda palette PNG,*image.NRGBA64a 16-bit PNG. - To limit memory for untrusted uploads, check
DecodeConfigdimensions before callingDecode. - For a smaller file, convert to
*image.Paletted(e.g. withdraw.FloydSteinbergand a palette) before encoding.