cimg

package module
v1.0.10 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2021 License: BSD-3-Clause Imports: 10 Imported by: 0

README

C++ image library bindings for Go

cimg is a Go wrapper for various C/C++ image libraries, including:

  • libjpeg-turbo
  • stb_image_resize
  • Unrotate image so that natural encoding orientation is same as display orientation
  • Reading and writing EXIF orientation (provided via native Go code)

Why?

There are a host of high-performance C/C++ libraries out there for image manipulation, and it's near impossible to write the same kind of code in Go.

Example: Compress/Decompress with TurboJPEG
import "github.com/bmharper/cimg"

func compressImage(width, height int, rgb []byte) {
	raw := cimg.Image{
		Width: width,
		Height: height,
		Stride: width * 3,
		Pixels: rgb,
	}
	params := cimg.MakeCompressParams(cimg.PixelFormatRGB, cimg.Sampling420, 35, 0)
	jpg, err := cimg.Compress(&raw, params)
}

func decompressImage(jpg []byte) (*Image, error) {
	return cimg.Decompress(jpg)
}
Example: Read and Modify EXIF Orientation
import "github.com/bmharper/cimg"

func inspectOrientation(jpgRaw []byte) {
	// Parse JPEG/JFIF segments, and read EXIF Orientation tag
	jpgExif, err = cimg.LoadExif(jpgRaw)
	fmt.Printf("Orientation: %v\n", jpgExif.GetOrientation())

	// Modify EXIF rotation.
	// If the file contains no EXIF data, then this will create an
	// EXIF "segment".
	err = jpgExif.SetOrientation(3)
	out := bytes.Buffer{}
	err = jpgExif.Save(&out)
}
Example: Resize with stb_image_resize
import "github.com/bmharper/cimg"

// Resize from bytes
func resizeImage(srcWidth, srcHeight int, rgba []byte, dstWidth, dstHeight int) *cimg.Image {
	src := cimg.WrapImage(srcWidth, srcHeight, 4, rgba)
	return cimg.ResizeNew(src, dstWidth, dstHeight)
}
C/C++ compiler optimizations

I was initially worried that I needed to add the directive #cgo CXXFLAGS: -O2, but it looks like cgo compiles with optimizations on by default. You can verify this by adding #cgo CXXFLAGS: -O0 to resize.go, and run go test -bench=.. Compare with -O0 and -O2 and there should be a big difference. Removing the comment entirely should give similar performance to -O2.

System requirements

I have only tested this on Ubuntu 20.04 amd64.

To install the necessary packages:

apt install libturbojpeg0-dev
Testing

Warning! Many of the Go unit tests don't actually validate their results. Instead, they simply write out a JPEG file into the test directory. It's your job to visually see that they look correct.

Documentation

Index

Constants

View Source
const (
	ExifTagOrientation = 0x112 // Photo orientation
)

Variables

This section is empty.

Functions

func Compress

func Compress(img *Image, params CompressParams) ([]byte, error)

Compress compresses an image using TurboJPEG

func Resize

func Resize(src, dst *Image) error

Resize resizes an image into a destination buffer that you provide Assumes sRGB image

Types

type CompressParams

type CompressParams struct {
	PixelFormat PixelFormat
	Sampling    Sampling
	Quality     int // 1 .. 100
	Flags       Flags
}

CompressParams are the TurboJPEG compression parameters

func MakeCompressParams

func MakeCompressParams(pixelFormat PixelFormat, sampling Sampling, quality int, flags Flags) CompressParams

MakeCompressParams returns a fully populated CompressParams struct

type ExifData added in v1.0.1

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

ExifData is a wrapper around github.com/dsoprea/go-exif, with only the tags exposed that I've needed to manipulate

func LoadExif added in v1.0.1

func LoadExif(jpeg []byte) (*ExifData, error)

Load a JPEG file, and parse it into it's JFIF segments. You can then read the existing EXIF data, or alter it. Note that if you modify the EXIF data, then reading that same data back from this data structure will not reflect your changes. You changes will only be reflected if you call Save(), and then reload that file using LoadJpegExif again.

func (*ExifData) GetOrientation added in v1.0.1

func (x *ExifData) GetOrientation() int

See https://www.impulseadventure.com/photo/exif-orientation.html 0th Row 0th Column 1 top left side 2 top right side 3 bottom right side 4 bottom left side 5 left side top 6 right side top 7 right side bottom 8 left side bottom

func (*ExifData) Save added in v1.0.4

func (x *ExifData) Save(w io.Writer) error

Save writes the image file

func (*ExifData) SetOrientation added in v1.0.4

func (x *ExifData) SetOrientation(orient int) error

Set photo orientation (See GetOrientation for meaning of the codes)

type Flags

type Flags C.int
const (
	FlagAccurateDCT   Flags = C.TJFLAG_ACCURATEDCT
	FlagBottomUp      Flags = C.TJFLAG_BOTTOMUP
	FlagFastDCT       Flags = C.TJFLAG_FASTDCT
	FlagFastUpsample  Flags = C.TJFLAG_FASTUPSAMPLE
	FlagNoRealloc     Flags = C.TJFLAG_NOREALLOC
	FlagProgressive   Flags = C.TJFLAG_PROGRESSIVE
	FlagStopOnWarning Flags = C.TJFLAG_STOPONWARNING
)

type Image

type Image struct {
	Width  int
	Height int
	Stride int
	NChan  int
	Pixels []byte
}

Image is the concrete image type that is used by all functions inside cimg.

func Decompress

func Decompress(encoded []byte) (*Image, error)

Decompress decompresses a JPEG image using TurboJPEG, or PNG image using Go's native PNG library The resulting image is RGB for JPEGs, or RGBA/Gray for PNG

func FromImage

func FromImage(src image.Image, allowDeepClone bool) (*Image, error)

Convert a Go image.Image into a turbo.Image If allowDeepClone is true, and the source image is type GRAY, NRGBA, or RGBA, then the resulting Image points directly to the pixel buffer of the source image.

func NewImage

func NewImage(width, height, nchan int) *Image

NewImage creates a new 8-bit image

func ResizeNew

func ResizeNew(src *Image, dstWidth, dstHeight int) *Image

ResizeNew allocates the output image for you and returns it Assumes sRGB image

func UnrotateExif added in v1.0.3

func UnrotateExif(exifOrientation int, src *Image) (*Image, error)

UnrotateExif rewrites the bytes of an image so that the EXIF orientation information can be discarded. In other words, after running UnrotateExif, the encoded image orientation is the same as the natural display image orientation. exifOrientation must be either 3, 6, or 8.

func WrapImage

func WrapImage(width, height, nchan int, pixels []byte) *Image

Wrap an array of bytes into an Image object (do not copy pixels)

func (*Image) AvgColor added in v1.0.5

func (img *Image) AvgColor() []uint8

AvgColor computes the average color of the entire image, per channel The averaging is performed in sRGB space (i.e. not physically correct) If the image has more than 8 channels, then the function will panic

func (*Image) Clone added in v1.0.9

func (img *Image) Clone() *Image

Clone returns a deep clone of the image

func (*Image) CopyImage added in v1.0.7

func (dst *Image) CopyImage(src *Image, dstX1, dstY1 int) error

CopyImage copies src into dst at the location dstX1, dstY1

func (*Image) CopyImageRect added in v1.0.7

func (dst *Image) CopyImageRect(src *Image, srcX1, srcY1, srcX2, srcY2 int, dstX1, dstY1 int) error

CopyImageRect copies src into dst, at dstX1,dstY1. The source imagery is read from the rectangle specified by the 4 source location parameters. All coordinates are clipped prior to drawing. The only error condition is when the two images have a different number of channels

func (*Image) ToImage added in v1.0.9

func (img *Image) ToImage() image.Image

ToImage returns an image from the Go standard library 'image' package

func (*Image) ToRGB added in v1.0.9

func (img *Image) ToRGB() *Image

ToRGB returns a 3 channel image. This is used to remove the alpha channel from an image that was loaded from a PNG, or to turn a gray image into an RGB image. If the image is already a 3 channel image, then a clone is returned

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
	PixelFormatUNKNOWN PixelFormat = C.TJPF_UNKNOWN
)

type Sampling

type Sampling C.int
const (
	Sampling444  Sampling = C.TJSAMP_444
	Sampling422  Sampling = C.TJSAMP_422
	Sampling420  Sampling = C.TJSAMP_420
	SamplingGray Sampling = C.TJSAMP_GRAY
)

Jump to

Keyboard shortcuts

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