bimg

package module
v0.1.24 Latest Latest
Warning

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

Go to latest
Published: Mar 1, 2016 License: MIT Imports: 10 Imported by: 0

README

bimg Build Status GoDoc Go Report Card Coverage Status

Small Go package for fast high-level image processing using libvips via C bindings, providing a simple, elegant and fluent programmatic API.

bimg was designed to be a small and efficient library supporting a common set of image operations such as crop, resize, rotate, zoom or watermark. It can read JPEG, PNG, WEBP and TIFF formats and output to JPEG, PNG and WEBP, including conversion across them.

bimg uses internally libvips, a powerful library written in C for image processing which requires a low memory footprint and it's typically 4x faster than using the quickest ImageMagick and GraphicsMagick settings or Go native image package, and in some cases it's even 8x faster processing JPEG images.

If you're looking for an HTTP based image processing solution, see imaginary.

bimg was heavily inspired in sharp, its homologous package built for node.js.

Contents

Supported image operations

  • Resize
  • Enlarge
  • Crop
  • Rotate (with auto-rotate based on EXIF orientation)
  • Flip (with auto-flip based on EXIF metadata)
  • Flop
  • Zoom
  • Thumbnail
  • Extract area
  • Watermark (text only)
  • Gaussian blur effect
  • Custom output color space (RGB, grayscale...)
  • Format conversion (with additional quality/compression settings)
  • EXIF metadata (size, alpha channel, profile, orientation...)

Prerequisites

  • libvips v7.40.0+ (7.42.0+ recommended)
  • C compatible compiler such as gcc 4.6+ or clang 3.0+
  • Go 1.3+

Installation

go get -u gopkg.in/h2non/bimg.v0
libvips

Run the following script as sudo (supports OSX, Debian/Ubuntu, Redhat, Fedora, Amazon Linux):

curl -s https://raw.githubusercontent.com/lovell/sharp/master/preinstall.sh | sudo bash -

If you wanna take the advantage of OpenSlide, simply add --with-openslide to enable it:

curl -s https://raw.githubusercontent.com/lovell/sharp/master/preinstall.sh | sudo bash -s --with-openslide

The install script requires curl and pkg-config

For platform specific installations, see Mac OS tips or Windows tips

Performance

libvips is probably the faster open source solution for image processing. Here you can see some performance test comparisons for multiple scenarios:

Benchmark

Tested using Go 1.5.1 and libvips-7.42.3 in OSX i7 2.7Ghz

BenchmarkRotateJpeg-8     	      20	  64686945 ns/op
BenchmarkResizeLargeJpeg-8	      20	  63390416 ns/op
BenchmarkResizePng-8      	     100	  18147294 ns/op
BenchmarkResizeWebP-8     	     100	  20836741 ns/op
BenchmarkConvertToJpeg-8  	     100	  12831812 ns/op
BenchmarkConvertToPng-8   	      10	 128901422 ns/op
BenchmarkConvertToWebp-8  	      10	 204027990 ns/op
BenchmarkCropJpeg-8       	      30	  59068572 ns/op
BenchmarkCropPng-8        	      10	 117303259 ns/op
BenchmarkCropWebP-8       	      10	 107060659 ns/op
BenchmarkExtractJpeg-8    	      50	  30708919 ns/op
BenchmarkExtractPng-8     	    3000	    595546 ns/op
BenchmarkExtractWebp-8    	    3000	    386379 ns/op
BenchmarkZoomJpeg-8       	      10	 160005424 ns/op
BenchmarkZoomPng-8        	      30	  44561047 ns/op
BenchmarkZoomWebp-8       	      10	 126732678 ns/op
BenchmarkWatermarkJpeg-8  	      20	  79006133 ns/op
BenchmarkWatermarPng-8    	     200	   8197291 ns/op
BenchmarkWatermarWebp-8   	      30	  49360369 ns/op

Examples

import (
  "fmt"
  "os"
  "gopkg.in/h2non/bimg.v0"
)
Resize
buffer, err := bimg.Read("image.jpg")
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}

newImage, err := bimg.NewImage(buffer).Resize(800, 600)
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}

size, err := bimg.NewImage(newImage).Size()
if size.Width == 400 && size.Height == 300 {
  fmt.Println("The image size is valid")
}

bimg.Write("new.jpg", newImage)
Rotate
buffer, err := bimg.Read("image.jpg")
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}

newImage, err := bimg.NewImage(buffer).Rotate(90)
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}

bimg.Write("new.jpg", newImage)
Convert
buffer, err := bimg.Read("image.jpg")
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}

newImage, err := bimg.NewImage(buffer).Convert(bimg.PNG)
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}

if bimg.NewImage(newImage).Type() == "png" {
  fmt.Fprintln(os.Stderr, "The image was converted into png")
}
Force resize

Force resize operation without perserving the aspect ratio:

buffer, err := bimg.Read("image.jpg")
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}

newImage, err := bimg.NewImage(buffer).ForceResize(1000, 500)
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}
  
size := bimg.Size(newImage)
if size.Width != 1000 || size.Height != 500 {
  fmt.Fprintln(os.Stderr, "Incorrect image size")
}
Custom colour space (black & white)
buffer, err := bimg.Read("image.jpg")
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}

newImage, err := bimg.NewImage(buffer).Colourspace(bimg.INTERPRETATION_B_W)
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}
  
colourSpace, _ := bimg.ImageInterpretation(newImage)
if colourSpace != bimg.INTERPRETATION_B_W {
  fmt.Fprintln(os.Stderr, "Invalid colour space")
}
Custom options

See Options struct to discover all the available fields

options := bimg.Options{
  Width:        800,
  Height:       600,
  Crop:         true,
  Quality:      95,
  Rotate:       180,
  Interlace:    true,
}

buffer, err := bimg.Read("image.jpg")
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}

newImage, err := bimg.NewImage(buffer).Process(options)
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}

bimg.Write("new.jpg", newImage)
Watermark
buffer, err := bimg.Read("image.jpg")
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}

watermark := bimg.Watermark{
  Text:       "Chuck Norris (c) 2315",
  Opacity:    0.25,
  Width:      200,
  DPI:        100,
  Margin:     150,
  Font:       "sans bold 12",
  Background: bimg.Color{255, 255, 255},
}

newImage, err := bimg.NewImage(buffer).Watermark(watermark)
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}

bimg.Write("new.jpg", newImage)
Fluent interface
buffer, err := bimg.Read("image.jpg")
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}

image := bimg.NewImage(buffer)

// first crop image
_, err := image.CropByWidth(300)
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}

// then flip it
newImage, err := image.Flip()
if err != nil {
  fmt.Fprintln(os.Stderr, err)
}

// save the cropped and flipped image
bimg.Write("new.jpg", newImage)

Debugging

Run the process passing the DEBUG environment variable

DEBUG=bimg ./app 

Enable libvips traces (note that a lot of data will be written in stdout):

VIPS_TRACE=1 ./app 

You can also dump a core on failure, as John Cuppit said:

g_log_set_always_fatal(
                G_LOG_FLAG_RECURSION |
                G_LOG_FLAG_FATAL |
                G_LOG_LEVEL_ERROR |
                G_LOG_LEVEL_CRITICAL |
                G_LOG_LEVEL_WARNING );

Or set the G_DEBUG environment variable:

export G_DEBUG=fatal-warnings,fatal-criticals

API

See godoc reference for detailed API documentation.

Credits

People who recurrently contributed to improve bimg in some way.

Thank you!

License

MIT - Tomas Aparicio

views

Documentation

Index

Constants

View Source
const (
	QUALITY  = 80
	MAX_SIZE = 16383
)
View Source
const HasMagickSupport = int(C.VIPS_MAGICK_SUPPORT) == 1
View Source
const Version = "0.1.24"
View Source
const VipsVersion = string(C.VIPS_VERSION)

Current libvips version

View Source
const WATERMARK_FONT = "sans 10"

Variables

View Source
var ColorBlack = Color{0, 0, 0}

Shortcut to black RGB color representation

View Source
var ImageTypes = map[ImageType]string{
	JPEG:   "jpeg",
	PNG:    "png",
	WEBP:   "webp",
	TIFF:   "tiff",
	MAGICK: "magick",
}

Pairs of image type and its name

Functions

func ColourspaceIsSupported

func ColourspaceIsSupported(buf []byte) (bool, error)

Check in the image colourspace is supported by libvips

func DetermineImageTypeName

func DetermineImageTypeName(buf []byte) string

Determines the image type format by name (jpeg, png, webp or tiff)

func ImageTypeName

func ImageTypeName(t ImageType) string

func Initialize

func Initialize()

Explicit thread-safe start of libvips. Only call this function if you previously shutdown libvips

func IsTypeNameSupported

func IsTypeNameSupported(t string) bool

Check if a given image type name is supported

func IsTypeSupported

func IsTypeSupported(t ImageType) bool

Check if a given image type is supported

func Read

func Read(path string) ([]byte, error)

func Resize

func Resize(buf []byte, o Options) ([]byte, error)

func Shutdown

func Shutdown()

Thread-safe function to shutdown libvips. You can call this to drop caches as well. If libvips was already initialized, the function is no-op

func VipsDebugInfo

func VipsDebugInfo()

Output to stdout vips collected data. Useful for debugging

func Write

func Write(path string, buf []byte) error

Types

type Angle

type Angle int
const (
	D0   Angle = 0
	D90  Angle = 90
	D180 Angle = 180
	D270 Angle = 270
)

type Color

type Color struct {
	R, G, B uint8
}

Color represents a traditional RGB color scheme

type Direction

type Direction int

type GaussianBlur

type GaussianBlur struct {
	Sigma   float64
	MinAmpl float64
}

type Gravity

type Gravity int
const (
	CENTRE Gravity = iota
	NORTH
	EAST
	SOUTH
	WEST
)

type Image

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

Image encapsulates the whole image buffer

func NewImage

func NewImage(buf []byte) *Image

Creates a new image

func (*Image) Colourspace

func (i *Image) Colourspace(c Interpretation) ([]byte, error)

Colour space conversion

func (*Image) ColourspaceIsSupported

func (i *Image) ColourspaceIsSupported() (bool, error)

Check if the current image has a valid colourspace

func (*Image) Convert

func (i *Image) Convert(t ImageType) ([]byte, error)

Convert image to another format

func (*Image) Crop

func (i *Image) Crop(width, height int, gravity Gravity) ([]byte, error)

Crop the image to the exact size specified

func (*Image) CropByHeight

func (i *Image) CropByHeight(height int) ([]byte, error)

Crop an image by height (auto width)

func (*Image) CropByWidth

func (i *Image) CropByWidth(width int) ([]byte, error)

Crop an image by width (auto height)

func (*Image) Enlarge

func (i *Image) Enlarge(width, height int) ([]byte, error)

Enlarge the image by width and height. Aspect ratio is maintained

func (*Image) EnlargeAndCrop

func (i *Image) EnlargeAndCrop(width, height int) ([]byte, error)

Enlarge the image by width and height with additional crop transformation

func (*Image) Extract

func (i *Image) Extract(top, left, width, height int) ([]byte, error)

Extract area from the by X/Y axis

func (*Image) Flip

func (i *Image) Flip() ([]byte, error)

Flip the image about the vertical Y axis

func (*Image) Flop

func (i *Image) Flop() ([]byte, error)

Flop the image about the horizontal X axis

func (*Image) ForceResize

func (i *Image) ForceResize(width, height int) ([]byte, error)

Force resize with custom size (aspect ratio won't be maintained)

func (*Image) Image

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

Get image buffer

func (*Image) Metadata

func (i *Image) Metadata() (ImageMetadata, error)

Get image metadata (size, alpha channel, profile, EXIF rotation)

func (*Image) Process

func (i *Image) Process(o Options) ([]byte, error)

Transform the image by custom options

func (*Image) Resize

func (i *Image) Resize(width, height int) ([]byte, error)

Resize the image to fixed width and height

func (*Image) ResizeAndCrop

func (i *Image) ResizeAndCrop(width, height int) ([]byte, error)

Resize the image to fixed width and height with additional crop transformation

func (*Image) Rotate

func (i *Image) Rotate(a Angle) ([]byte, error)

Rotate the image by given angle degrees (0, 90, 180 or 270)

func (*Image) Size

func (i *Image) Size() (ImageSize, error)

Get image size

func (*Image) Thumbnail

func (i *Image) Thumbnail(pixels int) ([]byte, error)

Thumbnail the image by the a given width by aspect ratio 4:4

func (*Image) Type

func (i *Image) Type() string

Get image type format (jpeg, png, webp, tiff)

func (*Image) Watermark

func (i *Image) Watermark(w Watermark) ([]byte, error)

Add text as watermark on the given image

func (*Image) Zoom

func (i *Image) Zoom(factor int) ([]byte, error)

Zoom the image by the given factor. You should probably call Extract() before

type ImageMetadata

type ImageMetadata struct {
	Orientation int
	Channels    int
	Alpha       bool
	Profile     bool
	Type        string
	Space       string
	Colourspace string
	Size        ImageSize
}

ImageMedatada represents the basic metadata fields

func Metadata

func Metadata(buf []byte) (ImageMetadata, error)

Extract the image metadata (size, type, alpha channel, profile, EXIF orientation...)

type ImageSize

type ImageSize struct {
	Width  int
	Height int
}

ImageSize represents the image width and height values

func Size

func Size(buf []byte) (ImageSize, error)

Get the image size by width and height pixels

type ImageType

type ImageType int
const (
	UNKNOWN ImageType = iota
	JPEG
	WEBP
	PNG
	TIFF
	MAGICK
)

func DetermineImageType

func DetermineImageType(buf []byte) ImageType

Determines the image type format (jpeg, png, webp or tiff)

type Interpolator

type Interpolator int
const (
	BICUBIC Interpolator = iota
	BILINEAR
	NOHALO
)

func (Interpolator) String

func (i Interpolator) String() string

type Options

type Options struct {
	Height         int
	Width          int
	AreaHeight     int
	AreaWidth      int
	Top            int
	Left           int
	Extend         int
	Quality        int
	Compression    int
	Zoom           int
	Crop           bool
	Enlarge        bool
	Embed          bool
	Flip           bool
	Flop           bool
	Force          bool
	NoAutoRotate   bool
	NoProfile      bool
	Interlace      bool
	Rotate         Angle
	Background     Color
	Gravity        Gravity
	Watermark      Watermark
	Type           ImageType
	Interpolator   Interpolator
	Interpretation Interpretation
	GaussianBlur   GaussianBlur
	Sharpen        Sharpen
}

Supported image transformation options

type Sharpen

type Sharpen struct {
	Radius int
	X1     float64
	Y2     float64
	Y3     float64
	M1     float64
	M2     float64
}

type VipsMemoryInfo

type VipsMemoryInfo struct {
	Memory          int64
	MemoryHighwater int64
	Allocations     int64
}

func VipsMemory

func VipsMemory() VipsMemoryInfo

Get memory info stats from vips (cache size, memory allocs...)

type Watermark

type Watermark struct {
	Width       int
	DPI         int
	Margin      int
	Opacity     float32
	NoReplicate bool
	Text        string
	Font        string
	Background  Color
}

Text-based watermark configuration

Jump to

Keyboard shortcuts

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