A lightning fast image processing and resizing library for Go

govips

GoDoc Go Report Card GitHub release (latest SemVer) License Build Status Coverage Status

A lightning fast image processing and resizing library for Go

This package wraps the core functionality of libvips image processing library by exposing all image operations on first-class types in Go.

Libvips is generally 4-8x faster than other graphics processors such as GraphicsMagick and ImageMagick. Check the benchmark: Speed and Memory Use

The intent for this is to enable developers to build extremely fast image processors in Go, which is suited well for concurrent requests.

Requirements

  • libvips 8.10+
  • C compatible compiler such as gcc 4.6+ or clang 3.0+
  • Go 1.14+

Dependencies

MacOS

Use homebrew to install vips and pkg-config:

brew install vips pkg-config

Ubuntu

You need at least libvips 8.10.2 to work with govips. Groovy (20.10) repositories have the latest version. However on Bionic (18.04) and Focal (20.04), you need to install libvips and dependencies from a backports repository:

sudo add-apt-repository ppa:tonimelisma/ppa

Then:

sudo apt -y install libvips-dev

Windows

The recommended approach on Windows is to use Govips via WSL and Ubuntu.

If you need to run Govips natively on Windows, it's not difficult but will require some effort. We don't have a recommended environment or setup at the moment. Windows is also not in our list of CI/CD targets so Govips is not regularly tested for compatibility. If you would be willing to setup and maintain a robust CI/CD Windows environment, please open a PR, we would be pleased to accept your contribution and support Windows as a platform.

Installation

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

MacOS note

On MacOS, govips may not compile without first setting an environment variable:

export CGO_CFLAGS_ALLOW="-Xpreprocessor"

Example usage

package main

import (
	"fmt"
	"io/ioutil"
	"os"

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

func checkError(err error) {
	if err != nil {
		fmt.Println("error:", err)
		os.Exit(1)
	}
}

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

	image1, err := vips.NewImageFromFile("input.jpg")
	checkError(err)

	// Rotate the picture upright and reset EXIF orientation tag
	err = image1.AutoRotate()
	checkError(err)

	ep := vips.NewDefaultJPEGExportParams()
	image1bytes, _, err := image1.Export(ep)
	err = ioutil.WriteFile("output.jpg", image1bytes, 0644)
	checkError(err)

}

See examples/ folder for more examples.

Running tests

$ make test

Contributing

Feel free to file issues or create pull requests. See this guide on contributing for more information.

Credits

Thanks to:

License

MIT - David Byttow

Owner
David Byttow
Tech Villain. Currently at Bridgewater. Formerly worked at Snapchat, Postmates, Google, Square, Secret, Amazon Game Studio, etc
David Byttow
Comments
  • Add Transform ICC Profile API

    Add Transform ICC Profile API

    I previously asked about adding support for transforming images between ICC profiles and it was suggested that suggested I make a pull request. I was able to get the vips_icc_transform function working with an ICC profile that I supplied externally. If you have a Mac, the built-in color profiles are located at /System/Library/ColorSync/Profiles/.

    I was able to take an image with an embedded Display P3 color profile and transform it to both an sRGB version and a Display P3 version without breaking it.

    Please let me know what you think and if you have any feedback!

  • Improved exif extraction

    Improved exif extraction

    This PR adds several APIs that exist already at the libvips layer but were not exposed by govips which allow us to read and write EXIF fields. For images like JPEGs which support regular EXIF data, the exif-data image field can be read out as a blob or the individual fields can be parsed via their respective field names. For images like TIFFs without direct EXIF support, you can also extract the newer XMP metadata as a blob.

    Also while I was testing with TIFF images I found a bug where TIFF images always defaulted to a resolution 1.0 Pixels-Per-Millimeters (about 25PPI). The resolution doesn't really affect the image itself -- just how large it should be printed. The canonical way to change this with libvips is to copy the image changing the xres / yres fields to the desired value. I removed the strange TIFF behavior so that the original resolution (different than pixel dimensions) will be preserved and it can be set to the desired value with the new API.

  • Getting object alive count greater than 0 when calling vips to generate a black image

    Getting object alive count greater than 0 when calling vips to generate a black image

    We are using this benchmarking code through govips for basic operation of creating black images (https://pkg.go.dev/github.com/davidbyttow/govips/v2/vips#Black).

    func BenchmarkVipsBlack(b *testing.B) {
    	for n := 0; n < b.N; n++ {
    		_, _ = vips.Black(100, 100)
    	}
    	vips.PrintCache()
    	vips.PrintObjectReport("BenchmarkVipsBlack")
    	vipsMemStats := &vips.MemoryStats{}
    	vipsRuntimeStats := &vips.RuntimeStats{}
    	vips.ReadVipsMemStats(vipsMemStats)
    	vips.ReadRuntimeStats(vipsRuntimeStats)
    	golog.Logger.Info(fmt.Sprintf("VIPS Runtime Stats: %+v", vipsRuntimeStats))
    	golog.Logger.Info(fmt.Sprintf("VIPS Memory Stats: %+v", vipsMemStats))
    }
    

    The response for this as mentioned below -

    vips live objects: BenchmarkVipsBlack...
    2 objects alive:
    0) VipsBlack (0x12d840e10), count=1
    VipsBlack (black), make a black image, black out=((VipsImage*) 0x13900b000) width=100 height=100 -
    1) VipsImage (0x13900b000), count=1
    VipsImage (image), image class, 100x100 uchar, 1 band, multiband
    2022/11/23 18:44:22 [govips.info] 
    2022-11-23T18:44:22.566+0530    INFO    VIPS Runtime Stats: &{OperationCounts:map[]}
    2022-11-23T18:44:22.566+0530    INFO    VIPS Memory Stats: &{Mem:0 MemHigh:0 Files:0 Allocs:0}
    goos: darwin
    goarch: amd64
    pkg: irs/imagerendering
    cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    BenchmarkVipsBlack-12           Operation cache:
    2022/11/23 18:44:22 [govips.info] 
    =======================================
    vips live objects: BenchmarkVipsBlack...
    22 objects alive:
    0) VipsBlack (0x139009540), count=1
    VipsBlack (black), make a black image, black out=((VipsImage*) 0x13900b7d0) width=100 height=100 -
    1) VipsBlack (0x10500e100), count=1
    VipsBlack (black), make a black image, black out=((VipsImage*) 0x13900e340) width=100 height=100 -
    2) VipsBlack (0x10500e000), count=1
    VipsBlack (black), make a black image, black out=((VipsImage*) 0x13900e020) width=100 height=100 -
    3) VipsBlack (0x1390096c0), count=1
    VipsBlack (black), make a black image, black out=((VipsImage*) 0x13900bc80) width=100 height=100 -
    4) VipsImage (0x13900be10), count=1
    VipsImage (image), image class, 100x100 uchar, 1 band, multiband
    5) VipsImage (0x13900e4d0), count=1
    VipsImage (image), image class, 100x100 uchar, 1 band, multiband
    6) VipsBlack (0x1390095c0), count=1
    VipsBlack (black), make a black image, black out=((VipsImage*) 0x13900b960) width=100 height=100 -
    7) VipsBlack (0x12d840e10), count=1
    VipsBlack (black), make a black image, black out=((VipsImage*) 0x13900b000) width=100 height=100 -
    8) VipsImage (0x13900baf0), count=1
    VipsImage (image), image class, 100x100 uchar, 1 band, multiband
    9) VipsImage (0x13900bc80), count=1
    VipsImage (image), image class, 100x100 uchar, 1 band, multiband
    10) VipsImage (0x13900e020), count=1
    VipsImage (image), image class, 100x100 uchar, 1 band, multiband
    11) VipsBlack (0x1390094c0), count=1
    VipsBlack (black), make a black image, black out=((VipsImage*) 0x13900b640) width=100 height=100 -
    12) VipsImage (0x13900b7d0), count=1
    VipsImage (image), image class, 100x100 uchar, 1 band, multiband
    13) VipsImage (0x13900b960), count=1
    VipsImage (image), image class, 100x100 uchar, 1 band, multiband
    14) VipsImage (0x13900b640), count=1
    VipsImage (image), image class, 100x100 uchar, 1 band, multiband
    15) VipsBlack (0x139009740), count=1
    VipsBlack (black), make a black image, black out=((VipsImage*) 0x13900be10) width=100 height=100 -
    16) VipsBlack (0x10500e080), count=1
    VipsBlack (black), make a black image, black out=((VipsImage*) 0x13900e1b0) width=100 height=100 -
    17) VipsImage (0x13900e1b0), count=1
    VipsImage (image), image class, 100x100 uchar, 1 band, multiband
    18) VipsBlack (0x139009640), count=1
    VipsBlack (black), make a black image, black out=((VipsImage*) 0x13900baf0) width=100 height=100 -
    19) VipsImage (0x13900e340), count=1
    VipsImage (image), image class, 100x100 uchar, 1 band, multiband
    20) VipsImage (0x13900b000), count=1
    VipsImage (image), image class, 100x100 uchar, 1 band, multiband
    21) VipsBlack (0x10500e180), count=1
    VipsBlack (black), make a black image, black out=((VipsImage*) 0x13900e4d0) width=100 height=100 -
    2022/11/23 18:44:22 [govips.info] =======================================
    
    2022-11-23T18:44:22.568+0530    INFO    VIPS Runtime Stats: &{OperationCounts:map[]}
    2022-11-23T18:44:22.568+0530    INFO    VIPS Memory Stats: &{Mem:0 MemHigh:0 Files:0 Allocs:0}
          10        111271 ns/op         891 B/op      5 allocs/op
    PASS
    2022-11-23T18:44:22.571+0530    INFO    vips has been shutdown
    ok      irs/imagerendering      0.933s
    

    As mentioned in the response above, 22 objects are alive. @davidbyttow is this response expected or is this an indication of some memory leak.

    The above code ran for 10 iterations as mentioned in the results above.

  • Add support for Magick loader and most loading parameters.

    Add support for Magick loader and most loading parameters.

    I was trying to process some animated GIFs - which are supported by libvips - but realized that doing so requires some changes in this library: 1) passing parameters to loaders, 2) extracting some additional metadata from images (e.g. the number of pages), and 3) supporting the magick writer.

    I started taking a stab at (1), the only parameter that's missing is the "background" for PDF (I may add it - didn't want to figure out how it works just yet). While I was at it I also added the ability to use magick as loader.

    I'll add tests of course, but I wanted to see if this PR may be accepted and agree on design first.

  • Resized image file size 20% to 40% larger than

    Resized image file size 20% to 40% larger than "sharp" of Node.js

    govips produces 20% - 40% larger image file sizes than sharp (node equivalent) does for the same image dimensions and the same Lanczos3 kernel.

    Please check if govips is producing the optimal file size since both are using the same libvips backend.

    Thanks.

  • Adds support for loading parameters

    Adds support for loading parameters

    Inspired by: https://github.com/davidbyttow/govips/pull/155

    However, this doesn't use libvips options yet. My intent is to likely switch to using VImage options (rather than C vararg functions) for import and export parameters, but I wanted to get this exposed and working first.

  • ImportParams proof of concept

    ImportParams proof of concept

    Related to https://github.com/davidbyttow/govips/issues/147

    I created ImportParams struct with fields:

    • Fail
    • AutoRotate
    • Shrink

    All of them is optional and by default don't set on ...load_buffer call. By the same way can be added any other optional field.

  • Memory Leak

    Memory Leak

    I am having a memory leak with govips. Any suggestions how to solve this?

    after several images

    Allocated Memory = 104 MiB	Total Allocated Memory = 144 MiB	System Memory = 134 MiB	Number of GC = 7
    VIPS Allocated Memory = 114 MiB	VIPS Total Allocated Memory = 121 MiB	VIPS Memory Allocations = 2 
    
    Allocated Memory = 104 MiB	Total Allocated Memory = 288 MiB	System Memory = 134 MiB	Number of GC = 15
    VIPS Allocated Memory = 171 MiB	VIPS Total Allocated Memory = 178 MiB	VIPS Memory Allocations = 3 
    

    Originally posted by @evanoberholster in https://github.com/davidbyttow/govips/issues/44#issuecomment-435683155

  • Add mozjpeg equivalent parameters to save

    Add mozjpeg equivalent parameters to save

    jcupitt explains the mozjpeg parameters in this comment: https://github.com/libvips/libvips/issues/1422#issuecomment-530032329

    Additionally, look for references to mozjpeg in the documentation for vips_jpegsave(): https://libvips.github.io/libvips/API/current/VipsForeignSave.html#VipsForeignJpegSubsample

    These changes improved jpeg compression for my test image, especially with the addition of overshoot_deringing when compressing a screenshot that includes text.

  • NewImageFromBuffer Not Understand Image Format

    NewImageFromBuffer Not Understand Image Format

    Hi there,

    import "bytes"
    import "image"
    import "image/color"
    import "image/png"
    import "image/draw"
    
    im := image.NewRGBA(image.Rect(0, 0, 100, 100))
    draw.Draw(im, im.Bounds(), image.NewUniform(color.NRGBA{255, 0, 0, 255}), image.ZP, draw.Src)
    var buff bytes.Buffer
    err := png.Encode(&buff, im)
    
    vipsImage, err := vips.NewImageFromBuffer(buff.Bytes())
    

    [govips.info] failed to understand image format size=26149

    Any suggestions how to solve this?

  • Add support for higher bit depth AVIF and HEIF images

    Add support for higher bit depth AVIF and HEIF images

    Back in February, John helped me add support for loading and saving 8/10/12 bit HEIC and AVIF files to libvips here: https://github.com/libvips/libvips/pull/2596

    Now with the release of iOS 16 / MacOS Ventura which support AVIF images natively, I want to add support for them to my app.

    I asked about this a while ago here: https://github.com/davidbyttow/govips/issues/313 and finally had some time to implement it myself.

    The changes in this PR are as follows:

    • I cleaned up the HEIF / AVIF export parameters so they both now take a Bitdepth parameter like PNGs. Also libvips has renamed "speed" to "effort" so I migrated us to use that parameter name with backwards support for the speed parameter for code that used it.
    • I added golden image tests for 8bit AVIF and encoding a 16bit TIF to a 12bit AVIF.
    • The files I touched got auto formatted by gofmt so we should probably just commit those changes to avoid annoying future PR authors.
  • add vips_hist_find()

    add vips_hist_find()

    I tried to add support for vips_hist_find() which seems to have worked. I wanted to add vips_max (or something like maxpos) as well but I don't really understand the C API in the first place.

    This is more a feature request then I guess ;-)

  • Building with -extldflags=-static

    Building with -extldflags=-static

    Hi, Is there an option to build it with a static flag?

    That's my Dockerfile and it core-dumps on me or throws linker error `FROM golang:alpine as builder

    RUN apk add musl-dev vips-dev gcc

    WORKDIR /src COPY . .

    RUN go build -o /bin/app --ldflags '-linkmode external -extldflags=-static' . `

  • Add TempDir config option

    Add TempDir config option

    This config option allows the caller to specify a preexisting temporary directory instead of relying on the ability to create one at runtime. This can be important in setups where a shell or mkdir are unavailable at runtime.

  • Cannot create image from raw RGB buffer

    Cannot create image from raw RGB buffer

    We have a use-case where we would like to create a new image based off raw RGB data. Vips does have support for this via the new_from_memory function (or better yet new_from_memory_copy), e.g.:

    vips::VImage out = vips::VImage::new_from_memory (data, length, width, height, 3, VIPS_FORMAT_UCHAR);

  • TransformICCProfile() - expose input ICC profile parameter?

    TransformICCProfile() - expose input ICC profile parameter?

    Hello all, Do you think exposing the fallback input ICC profile would make sense?

    Currently, the TransformICCProfile() function takes only one parameter - the output profile. The input profile is a hardcoded sRGB one.

    image

    While this is a clean solution and would cover 98% of all use cases, it does not permit to deal with some "broken" images like CMYK images without ICC profiles. And there is no control over color transformations on any images without embedded profiles.

    I would expect that such an addition would also provide a solution to this issue (https://github.com/davidbyttow/govips/issues/275).

    Alternatively, someting can be done for OptimizeICCProfile()? Again, nothing can do any good for CMYK images without ICC profiles.

    image

    I would appreciate your input.

  • How to create a transparent canvas?

    How to create a transparent canvas?

    Im trying to create a empty transparent canvas that i can add images on.

    right now i am resorting to

    	c := image.NewNRGBA(rectangle)
    	buf := &bytes.Buffer{}
    	if err := png.Encode(buf, c); err != nil {
    		panic(err)
    	}
    	canvas, err := vips.NewImageFromBuffer(buf.Bytes())
    	if err != nil {
    		panic(err)
    	}
    

    which feels toaly backwards.

    I have tried using vips.Black() but it only gives me a black image and when i try to draw using img.Insert(), the whole image is still just black

    if i do canvas := &vips.ImageRef{} i cannot propagate all fields needed for it to work

    Any smart things i've missed in the lib?

    Cheers and thanks!

Pure golang image resizing
Pure golang image resizing

This package is no longer being updated! Please look for alternatives if that bothers you. Resize Image resizing for the Go programming language with

Jan 9, 2023
An image resizing server written in Go
An image resizing server written in Go

picfit picfit is a reusable Go server to manipulate images (resize, thumbnail, etc.). It will act as a proxy on your storage engine and will be served

Dec 24, 2022
Image resizing for the Go programming language with common interpolation methods

This package is no longer being updated! Please look for alternatives if that bothers you. Resize Image resizing for the Go programming language with

Dec 14, 2021
darkroom - An image proxy with changeable storage backends and image processing engines with focus on speed and resiliency.
darkroom - An image proxy with changeable storage backends and image processing engines with focus on speed and resiliency.

Darkroom - Yet Another Image Proxy Introduction Darkroom combines the storage backend and the image processor and acts as an Image Proxy on your image

Dec 6, 2022
Fast and secure standalone server for resizing and converting remote images

imgproxy imgproxy is a fast and secure standalone server for resizing and converting remote images. The main principles of imgproxy are simplicity, sp

Jan 1, 2023
Go package for fast high-level image processing powered by libvips C library

bimg Small Go package for fast high-level image processing using libvips via C bindings, providing a simple programmatic API. bimg was designed to be

Jan 2, 2023
Image - This repository holds supplementary Go image librariesThis repository holds supplementary Go image libraries

Go Images This repository holds supplementary Go image libraries. Download/Insta

Jan 5, 2022
Fast, simple, scalable, Docker-ready HTTP microservice for high-level image processing

imaginary Fast HTTP microservice written in Go for high-level image processing backed by bimg and libvips. imaginary can be used as private or public

Jan 3, 2023
Cloud function + website for resizing, cropping and bordering images for pragalicious.com

Cloud function + website for resizing, cropping and bordering images for pragalicious.com

Jan 23, 2022
Image processing library and rendering toolkit for Go.

blend Image processing library and rendering toolkit for Go. (WIP) Installation: This library is compatible with Go1. go get github.com/phrozen/blend

Nov 11, 2022
A library for basic image processing in Go.
A library for basic image processing in Go.

Imaging Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.). All the image process

Nov 26, 2021
A library for basic image processing in Go.
A library for basic image processing in Go.

Imaging Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.). All the image process

Nov 26, 2021
Storage and image processing server written in Go
Storage and image processing server written in Go

Mort An S3-compatible image processing server written in Go. Still in active development. Features HTTP server Resize, Rotate, SmartCrop Convert (JPEG

Jan 7, 2023
Image processing algorithms in pure Go
Image processing algorithms in pure Go

bild A collection of parallel image processing algorithms in pure Go. The aim of this project is simplicity in use and development over absolute high

Jan 6, 2023
Imaging is a simple image processing package for Go
Imaging is a simple image processing package for Go

Imaging Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.). All the image process

Dec 30, 2022
An API which allows you to upload an image and responds with the same image, stripped of EXIF data

strip-metadata This is an API which allows you to upload an image and responds with the same image, stripped of EXIF data. How to run You need to have

Nov 25, 2021
Easily customizable Social image (or Open graph image) generator

fancycard Easily customizable Social image (or Open graph image) generator Built with Go, Gin, GoQuery and Chromedp Build & Run Simply, Clone this rep

Jan 14, 2022
Imgpreview - Tiny image previews for HTML while the original image is loading
Imgpreview - Tiny image previews for HTML while the original image is loading

imgpreview This is a Go program that generates tiny blurry previews for images t

May 22, 2022
A fast, correct image dithering library in Go.

dither is a library for dithering images in Go. It has many dithering algorithms built-in, and allows you to specify your own. Correctness is a

Dec 27, 2022