octu0 / go-libjpeg-turbo

Go bindings for libjpeg-turbo

Home Page:https://pkg.go.dev/github.com/octu0/go-libjpeg-turbo

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

go-libjpeg-turbo

License GoDoc Go Report Card Releases

Go bindings for libjpeg-turbo

Requirements

requires libjpeg-turbo install on your system

Usage

Decode

package main

import (
	"fmt"
	"image"
	"image/png"
	"io"
	"os"

	"github.com/octu0/go-libjpeg-turbo"
)

func main() {
	data, err := readFile(“/path/to/image.jpg”)
	if err != nil {
		panic(err)
	}

	// create Decoder
	decoder, err := turbojpeg.CreateDecoder()
	if err != nil {
		panic(err)
	}
	defer decoder.Close()

	// decode Header only
	header, err := decoder.DecodeHeader(data)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%+v\n", header)
	// => {Width:320 Height:240 Subsampling:4:2:0 ColorSpace:YCbCr}

	// decode JPEG image To RGBA
	imgRef, err := decoder.DecodeToRGBA(data)
	if err != nil {
		panic(err)
	}
	defer imgRef.Close()

	saveImage(imgRef.Image)

	// or Decode with PixelFormat
	img, err := decoder.Decode(data, turbojpeg.PixelFormatRGBA)
	if err != nil {
		panic(err)
	}
	defer img.Close()

	rgba := &image.RGBA{
		Pix:    img.Bytes(),   // decoded image
		Stride: img.Width * 4, // 4 = r + g + b + a
		Rect:   image.Rect(0, 0, img.Width, img.Height),
	}

	saveImage(rgba)
}

func readFile(path string) ([]byte, error) {
	f, err := os.Open("./testdata/src.jpg")
	if err != nil {
		return nil, err
	}
	defer f.Close()

	data, err := io.ReadAll(f)
	if err != nil {
		return nil, err
	}
	return data, nil
}

func saveImage(img *image.RGBA)  {
	out, err := os.CreateTemp("/tmp", "out*.png")
	if err != nil {
		panic(err)
	}
	defer out.Close()

	if err := png.Encode(out, rgba); err != nil {
		panic(err)
	}
	fmt.Println("png out =", out.Name())
}

Encode

package main

import (
	"fmt"
	"image"
	"image/color"
	"image/png"
	"io"
	"os"

	"github.com/octu0/go-libjpeg-turbo"
)

func main() {
	rgba, err := readFileRGBA("./testdata/src.png")
	if err != nil {
		panic(err)
	}

	out, err := os.CreateTemp("/tmp", "out*.jpg")
	if err != nil {
		panic(err)
	}
	defer out.Close()

	// create Encoder
	encoder, err := turbojpeg.CreateEncoder()
	if err != nil {
		panic(err)
	}
	defer encoder.Close()

	// encode jpeg From *image.RGBA
	if _, err := encoder.EncodeRGBA(out, rgba, 85); err != nil {
		panic(err)
	}

	fmt.Println("jpg out =", out.Name())
}

func readFileRGBA(path string) (*image.RGBA, error) {
	f, err := os.Open("./testdata/src.png")
	if err != nil {
		return nil, err
	}
	defer f.Close()

	rgba, err := PNGToRGBA(f)
	if err != nil {
		return nil, err
	}
	return rgba, nil
}

func PNGToRGBA(r io.Reader) (*image.RGBA, error) {
	img, err := png.Decode(r)
	if err != nil {
		return nil, err
	}
	if i, ok := img.(*image.RGBA); ok {
		return i, nil
	}

	b := img.Bounds()
	rgba := image.NewRGBA(b)
	for y := b.Min.Y; y < b.Max.Y; y += 1 {
		for x := b.Min.X; x < b.Max.X; x += 1 {
			c := color.RGBAModel.Convert(img.At(x, y)).(color.RGBA)
			rgba.Set(x, y, c)
		}
	}
	return rgba, nil
}

Benchmark

Decode

~3x faster than image/jpeg.Decode

goos: darwin
goarch: amd64
pkg: github.com/octu0/go-libjpeg-turbo
cpu: Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz
BenchmarkJpegDecode
BenchmarkJpegDecode/image/jpeg.Decode
BenchmarkJpegDecode/image/jpeg.Decode-8         	     654	   1781690 ns/op	  136976 B/op	      19 allocs/op
BenchmarkJpegDecode/turbojpeg.Decode
BenchmarkJpegDecode/turbojpeg.Decode-8          	    2103	    558031 ns/op	     775 B/op	      19 allocs/op
BenchmarkJpegDecode/turbojpeg.DecodeToRGBA
BenchmarkJpegDecode/turbojpeg.DecodeToRGBA-8    	    2178	    558487 ns/op	     920 B/op	      23 allocs/op
PASS

Encode

~9x faster than image/jpeg.Encode

goos: darwin
goarch: amd64
pkg: github.com/octu0/go-libjpeg-turbo
cpu: Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz
BenchmarkJpegEncode
BenchmarkJpegEncode/image/jpeg.Encode
BenchmarkJpegEncode/image/jpeg.Encode-8         	     560	   2110825 ns/op	    4400 B/op	       4 allocs/op
BenchmarkJpegEncode/turbojpeg.Encode
BenchmarkJpegEncode/turbojpeg.Encode-8          	    4915	    236213 ns/op	     343 B/op	       8 allocs/op
PASS

About

Go bindings for libjpeg-turbo

https://pkg.go.dev/github.com/octu0/go-libjpeg-turbo

License:BSD 3-Clause "New" or "Revised" License


Languages

Language:Go 77.9%Language:C 22.1%