All formats

govips

LanguageGo (cgo)
LicenseMIT (libvips is LGPL-2.1)
Repositorygithub.com/davidbyttow/govips
Documentationpkg.go.dev/github.com/davidbyttow/govips/v2/vips, libvips jp2kload
Depends onlibvips 8.11+ built with OpenJPEG, cgo
Read / writeyes / yes; JP2 and J2K, 8 and 16 bits per sample, tiled output

govips wraps libvips, a fast image processing library that streams images in small regions instead of loading them whole. libvips has JPEG 2000 support through OpenJPEG (the jp2kload and jp2ksave operations), so govips can decode, resize and encode JPEG 2000 with low memory use.

You need libvips installed with OpenJPEG enabled; the packages of most Linux distributions and Homebrew have it. Since it uses cgo, cross-compiling is harder than with pure Go code.

Installation#

Shell
# Debian / Ubuntu
sudo apt install libvips-dev
# macOS
brew install vips pkg-config

go get github.com/davidbyttow/govips/v2/vips

Check that your libvips has JPEG 2000: vips -l | grep jp2k should list VipsForeignLoadJp2kFile and VipsForeignSaveJp2kFile.

Basic usage: convert JPEG 2000 to PNG#

Go
package main

import (
	"fmt"
	"log"
	"os"

	"github.com/davidbyttow/govips/v2/vips"
)

func main() {
	vips.Startup(nil)
	defer vips.Shutdown()

	img, err := vips.NewImageFromFile("in.jp2")
	if err != nil {
		log.Fatal(err)
	}
	defer img.Close()
	fmt.Printf("%d x %d, %d bands, format %s\n", img.Width(), img.Height(), img.Bands(), vips.ImageTypes[img.Format()])

	buf, _, err := img.ExportPng(vips.NewPngExportParams())
	if err != nil {
		log.Fatal(err)
	}
	if err := os.WriteFile("out.png", buf, 0o644); err != nil {
		log.Fatal(err)
	}
}

How to encode JPEG 2000#

Go
img, err := vips.NewImageFromFile("in.png")
if err != nil {
	log.Fatal(err)
}
defer img.Close()

params := vips.NewJp2kExportParams()
params.Quality = 40          // lossy; ignored when Lossless is true
params.Lossless = false
params.TileWidth = 512       // tiles allow fast region decoding later
params.TileHeight = 512
buf, _, err := img.ExportJp2k(params)
if err != nil {
	log.Fatal(err)
}
os.WriteFile("out.jp2", buf, 0o644)

How to load a lower resolution level#

libvips exposes the resolution levels of a JPEG 2000 file as pages: page 0 is full size, page 1 is half size, and so on.

Go
params := vips.NewImportParams()
params.Page.Set(2) // 1/4 width and height
img, err := vips.LoadImageFromFile("big.jp2", params)
if err != nil {
	log.Fatal(err)
}
defer img.Close()

How to make a thumbnail#

NewThumbnailFromFile loads only what it needs and resizes in one step:

Go
thumb, err := vips.NewThumbnailFromFile("big.jp2", 256, 256, vips.InterestingNone)
if err != nil {
	log.Fatal(err)
}
defer thumb.Close()
buf, _, _ := thumb.ExportJpeg(vips.NewJpegExportParams())
os.WriteFile("thumb.jpg", buf, 0o644)

Tips#