imaging
| Language | Go |
|---|---|
| License | MIT |
| Repository | github.com/disintegration/imaging |
| Documentation | pkg.go.dev/github.com/disintegration/imaging |
| Depends on | golang.org/x/image (pure Go) |
| Read / write | yes / yes (through image/jpeg); reads the Exif orientation |
imaging provides the image operations the standard library lacks: resize with several filters (Lanczos, CatmullRom, Linear, Box, NearestNeighbor), fit, fill, crop, rotate, flip, blur, sharpen and color adjustments. Its Open and Decode functions can read the Exif orientation tag of a JPEG and rotate the image upright, which image/jpeg alone doesn’t do. Processing uses all CPU cores.
Encoding and decoding go through the standard image/jpeg, so the same limits apply: baseline output, no metadata in the saved file. The last release (v1.6.2) is from 2019; the package is stable and widely used, but issues aren’t actively fixed.
Installation#
go get github.com/disintegration/imaging
Basic usage: open a photo upright, resize and save#
package main
import (
"fmt"
"log"
"github.com/disintegration/imaging"
)
func main() {
// AutoOrientation applies the Exif orientation tag
img, err := imaging.Open("photo.jpg", imaging.AutoOrientation(true))
if err != nil {
log.Fatal(err)
}
fmt.Println(img.Bounds().Dx(), "x", img.Bounds().Dy())
small := imaging.Resize(img, 1200, 0, imaging.Lanczos) // 0 = keep aspect ratio
if err := imaging.Save(small, "out.jpg", imaging.JPEGQuality(85)); err != nil {
log.Fatal(err)
}
}
Save picks the format from the file extension (.jpg, .png, .gif, .tif, .bmp).
How to make square thumbnails from JPEG photos#
Fill resizes and crops to the exact size; Fit keeps the whole image inside a box:
thumb := imaging.Fill(img, 200, 200, imaging.Center, imaging.Lanczos)
preview := imaging.Fit(img, 800, 600, imaging.Lanczos)
_ = imaging.Save(thumb, "thumb.jpg", imaging.JPEGQuality(80))
_ = imaging.Save(preview, "preview.jpg")
How to encode a JPEG to a byte slice or HTTP response#
import (
"bytes"
"image"
"net/http"
"github.com/disintegration/imaging"
)
func serveThumb(w http.ResponseWriter, img image.Image) {
var buf bytes.Buffer
if err := imaging.Encode(&buf, imaging.Thumbnail(img, 300, 300, imaging.Box), imaging.JPEG, imaging.JPEGQuality(80)); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "image/jpeg")
w.Write(buf.Bytes())
}
How to crop and rotate#
cropped := imaging.CropAnchor(img, 600, 400, imaging.Center)
rotated := imaging.Rotate90(cropped) // counter-clockwise
tilted := imaging.Rotate(img, 15, color.White) // any angle (import "image/color"), fill corners with white
Tips#
imaging.Boxis the fastest filter for big reductions;Lanczosis the sharpest.- Decode from an
io.Readerwithimaging.Decode(r, imaging.AutoOrientation(true)). - For large volumes of photos, a libvips binding (bimg, govips) is several times faster and uses less memory.