turbojpeg

package module
v0.0.0-...-38ee9ce Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 14, 2023 License: BSD-3-Clause Imports: 10 Imported by: 0

README

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

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ColorSpace

type ColorSpace C.int
const (
	ColorSpaceRGB   ColorSpace = C.TJCS_RGB
	ColorSpaceYCbCr ColorSpace = C.TJCS_YCbCr
	ColorSpaceGray  ColorSpace = C.TJCS_GRAY
	ColorSpaceCMYK  ColorSpace = C.TJCS_CMYK
	ColorSpaceYCCK  ColorSpace = C.TJCS_YCCK
)

func (ColorSpace) String

func (c ColorSpace) String() string

type Decoder

type Decoder struct {
	// contains filtered or unexported fields
}

func CreateDecoder

func CreateDecoder() (*Decoder, error)

func CreateDecoderWithPool

func CreateDecoderWithPool(p cgobytepool.Pool) (*Decoder, error)

func (*Decoder) Close

func (d *Decoder) Close()

func (*Decoder) Decode

func (d *Decoder) Decode(data []byte, format PixelFormat) (*Image, error)

func (*Decoder) DecodeHeader

func (d *Decoder) DecodeHeader(data []byte) (Header, error)

func (*Decoder) DecodeToRGBA

func (d *Decoder) DecodeToRGBA(data []byte) (*ImageRGBARef, error)

type Encoder

type Encoder struct {
	// contains filtered or unexported fields
}

func CreateEncoder

func CreateEncoder() (*Encoder, error)

func CreateEncoderWithPool

func CreateEncoderWithPool(p cgobytepool.Pool) (*Encoder, error)

func (*Encoder) Close

func (e *Encoder) Close()

func (*Encoder) EncodeRGBA

func (e *Encoder) EncodeRGBA(out io.Writer, img *image.RGBA, quality int) (int, error)
type Header struct {
	Width       int
	Height      int
	Subsampling Subsampling
	ColorSpace  ColorSpace
}

type Image

type Image struct {
	Header
	Format PixelFormat
	// contains filtered or unexported fields
}

func (*Image) Bytes

func (i *Image) Bytes() []byte

func (*Image) Close

func (i *Image) Close()

type ImageRGBARef

type ImageRGBARef struct {
	Header
	Format PixelFormat
	Image  *image.RGBA
	// contains filtered or unexported fields
}

func (*ImageRGBARef) Close

func (i *ImageRGBARef) Close()

type PixelFormat

type PixelFormat C.int
const (
	PixelFormatRGB  PixelFormat = C.TJPF_RGB
	PixelFormatBGR  PixelFormat = C.TJPF_BGR
	PixelFormatRGBX PixelFormat = C.TJPF_RGBX
	PixelFormatBGRX PixelFormat = C.TJPF_BGRX
	PixelFormatXBGR PixelFormat = C.TJPF_XBGR
	PixelFormatXRGB PixelFormat = C.TJPF_XRGB
	PixelFormatGray PixelFormat = C.TJPF_GRAY
	PixelFormatRGBA PixelFormat = C.TJPF_RGBA
	PixelFormatBGRA PixelFormat = C.TJPF_BGRA
	PixelFormatABGR PixelFormat = C.TJPF_ABGR
	PixelFormatARGB PixelFormat = C.TJPF_ARGB
	PixelFormatCMYK PixelFormat = C.TJPF_CMYK
)

func (PixelFormat) String

func (p PixelFormat) String() string

type Subsampling

type Subsampling C.int
const (
	Subsampling444  Subsampling = C.TJSAMP_444
	Subsampling422  Subsampling = C.TJSAMP_422
	Subsampling420  Subsampling = C.TJSAMP_420
	SubsamplingGray Subsampling = C.TJSAMP_GRAY
	Subsampling440  Subsampling = C.TJSAMP_440
	Subsampling411  Subsampling = C.TJSAMP_411
)

func (Subsampling) String

func (s Subsampling) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL