Go package for fast high-level image processing powered by libvips C library

Overview

bimg Build Status GoDoc Go Report Card Coverage Status License

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

bimg was designed to be a small and efficient library supporting common image operations such as crop, resize, rotate, zoom or watermark. It can read JPEG, PNG, WEBP natively, and optionally TIFF, PDF, GIF and SVG formats if [email protected]+ is compiled with proper library bindings. Lastly AVIF is supported as of [email protected]+. For AVIF support libheif needs to be compiled with an applicable AVIF en-/decoder.

bimg is able to output images as JPEG, PNG and WEBP formats, including transparent 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. bimg is used in production environments processing thousands of images per day.

v1 notice: bimg introduces some minor breaking changes in v1 release. If you're using gopkg.in, you can still rely in the v0 without worrying about API breaking changes.

Contents

Supported image operations

  • Resize
  • Enlarge
  • Crop (including smart crop support, libvips 8.5+)
  • Rotate (with auto-rotate based on EXIF orientation)
  • Flip (with auto-flip based on EXIF metadata)
  • Flop
  • Zoom
  • Thumbnail
  • Extract area
  • Watermark (using text or image)
  • Gaussian blur effect
  • Custom output color space (RGB, grayscale...)
  • Format conversion (with additional quality/compression settings)
  • EXIF metadata (size, alpha channel, profile, orientation...)
  • Trim (libvips 8.6+)

Prerequisites

  • libvips 8.3+ (8.8+ recommended)
  • C compatible compiler such as gcc 4.6+ or clang 3.0+
  • Go 1.3+

Note:

  • libvips v8.3+ is required for GIF, PDF and SVG support.
  • libvips v8.9+ is required for AVIF support. libheif compiled with a AVIF en-/decoder also needs to be present.

Installation

go get -u github.com/h2non/bimg

libvips

Follow libvips installation instructions:

https://libvips.github.io/libvips/install.html

Installation script

Note: install script is officially deprecated, it might not work as expected. We recommend following libvips install instructions.

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

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

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

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

The install script requires curl and pkg-config.

Performance

libvips is probably the fastest 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"
  "github.com/h2non/bimg"
)

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 == 800 && size.Height == 600 {
  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.

Authors

Credits

People who recurrently contributed to improve bimg in some way.

Thank you!

License

MIT - Tomas Aparicio

views

Issues
  • Adds AVIF support

    Adds AVIF support

    • This adds a new type AVIF to the supported type list if libvips >= 8.9.0 is installed.
    • Calls libheif through libvips with the AV1 compression set to save AVIF images.

    This should fix #353.

    feature request 
    opened by LarsFronius 15
  • vendor/github.com/h2non/bimg/image.go:15: undefined: Options

    vendor/github.com/h2non/bimg/image.go:15: undefined: Options

    Hi, I have a problème with go build

    go v1.8 macOS 10.12.4

    vendor/github.com/h2non/bimg/image.go:15: undefined: Options
    vendor/github.com/h2non/bimg/image.go:25: undefined: Options
    vendor/github.com/h2non/bimg/image.go:82: undefined: Gravity
    vendor/github.com/h2non/bimg/image.go:122: undefined: Watermark
    vendor/github.com/h2non/bimg/image.go:135: undefined: Angle
    vendor/github.com/h2non/bimg/image.go:159: undefined: Interpretation
    vendor/github.com/h2non/bimg/image.go:167: undefined: Options
    vendor/github.com/h2non/bimg/image.go:177: undefined: ImageMetadata
    vendor/github.com/h2non/bimg/image.go:183: undefined: Interpretation
    vendor/github.com/h2non/bimg/image.go:199: undefined: ImageSize
    vendor/github.com/h2non/bimg/image.go:25: too many errors
    
    opened by euskadi31 15
  • Restructure transformations

    Restructure transformations

    A discussed a while ago, I refactored a lot of bimg to allow for (mostly) lossless transformations and cleanup the interface while at it. I also tackled a few technical debts and possible bugs when I encountered them. This includes my RGBA support from PR #351.

    Sorry for this HUGE PR. I think it's worth it, though.

    The API of bimg is untouched. So everything that worked before, still works. Under the hood this uses a new API though, that is also exposed: ImageTransformation. Let's take the example from the documentation:

    // read the raw data
    buffer, err := bimg.Read("image.jpg")
    if err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
    }
    
    // decode the image and prepare our transformation chain
    it, err := bimg.NewImageTransformation(buffer)
    if err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
    }
    
    // crop the image to a specific width
    err = it.Crop(bimg.CropOptions{Width: 300})
    if err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
    }
    
    // then flip it
    err = it.Rotate(bimg.RotateOptions{Flip: true})
    if err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
    }
    
    // encode the image
    newImage, err := it.Save(bimg.SaveOptions{})
    if err != nil {
      fmt.Fprintln(os.Stderr, err)
      return
    } 
    
    // save the cropped and flipped image
    bimg.Write("new.jpg", newImage)
    

    After NewImageTransformation we now have a VipsImage under the hood, not a buffer. The operations Crop, Rotate, etc. now perform on this VipsImage (replacing it in the process). It will not be re-encoded in between. Only when calling Save will the image be encoded. Especially when dealing with lossy formats like JPEG, this significantly improves image quality, since it only encodes once (while before it would have encoded and then decoded the JPEG between these stages).

    This, in short, is the main new feature of this PR.


    Additionally

    • VipsImage is now ref counted and is registered with the garbage collector for cleanup. So when the Go GC removes the reference, it will also remove its Glib reference. We therefore don't have to cleanup after ourselves all the time (but we can call Close() to help the GC)
    • I added support for saving GIF images (using magicksave).
    • Background color arrays are now created on the Go side, not on the C side. This shortens the C code and keeps the business logic closer to where we expect it.
    • A few VipsVersion checks were wrong and would break in the future. I fixed them.
    • I replaced a few cascaded if-statements with switch-statements.
    • Determining the filetype is now done using strings instead of sequences of bytes, to increase the readability.

    Possible Considerations

    I think the ImageTransformation could as well replace the Image and its fluent interface. This would, however, break the API. If this is desired, we can certainly do that and release it as v2. I am also fine keeping it separate (and/or combine it later).

    opened by aksdb 13
  • Unsupported image format

    Unsupported image format

    I'm using bimg in a function. Whole project is running as a service in a background. My usage is pretty simple.

    After "while" usually anything between 1-2 days, and after processing hips of images (hard to say, but we are talking about 1000-2000 images) .Process(options) function crashes with "Unsupported image format".

    After restart everything is back to normal. I've checked source images - and they are ok, and after restart same image which wasn't recognised correctly is ok. It's super hard to debug because I can't reproduce problem without leaving service for 1-2 days..

    Any clues ? I'm doing something wrong here ?

    
    /**
     * resize image action
     * 
     * @param inBuf []byte image to resize
     * @param w, h int width and height
     * @param c
     */
    func Resize(inBuf []byte, w int, h int, c bool, t, quality int) []byte {
    
        options := bimg.Options{
            Width : w,
            Height : h,
            Crop : c,
            //Embed : true,
            Interpolator : bimg.BICUBIC,
            Gravity: bimg.CENTRE,
            Quality:      quality,
        }
    
        // change image type
        if t > 0 {
            options.Type = bimg.ImageType(t)
        }
    
        image := bimg.NewImage(inBuf)
    
        newImage, err := image.Process(options)
    
    
        if err != nil {
            fmt.Println("failed to process image")
            log.Printf("options: %v", options)
    
            //bimg.VipsDebugInfo()
            fmt.Fprintln(os.Stderr, err)
            LastError = err.Error()
    
        }
    
        return newImage
    }
    
    enhancement help wanted 
    opened by slav123 13
  • Adding GIF, PDF and SVG support (libvips 8.3)

    Adding GIF, PDF and SVG support (libvips 8.3)

    Heya, after a long pause, I'm back at it and it seems that libvips now support reading GIF and PDF.

    What do you think of this?

    Cheers,

    source of the gif: http://media.photobucket.com/user/jacobseric/media/publicdomain.gif.html

    Issue:

    • [x] libvips requires a version of poppler that isn't present into travis to be compiled with pdf support
    feature request 
    opened by greut 10
  • Tests importing bimg are failing.

    Tests importing bimg are failing.

    When running the following (dramatically simplified) test things blow up a bit.

    package darkroom
    
    import (
        "fmt"
        "testing"
    
        "github.com/h2non/bimg"
    )
    
    func TestGravity(t *testing.T) {
        testData := []struct {
            input  string
            output bimg.Gravity
        }{
            {"center", bimg.CENTRE},
            {"north", bimg.NORTH},
            {"south", bimg.SOUTH},
            {"east", bimg.EAST},
            {"west", bimg.WEST},
        }
        fmt.Println(testData)
    }
    
    $ go test
    # testmain
    /usr/local/Cellar/go/1.5.1/libexec/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
    duplicate symbol _interpolator_window_size in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_affine_interpolator in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_colourspace_bridge in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_colourspace_issupported_bridge in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_embed_bridge in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_enable_cache_set_trace in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_enum_nick_bridge in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_exif_orientation in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_extract_area_bridge in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_flip_bridge in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_image_guess_interpretation_bridge in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_init_image in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_jpegload_buffer_shrink in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_jpegsave_bridge in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_pngsave_bridge in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_rotate in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_shrink_bridge in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_watermark in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_watermark_replicate in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_webpsave_bridge in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    duplicate symbol _vips_zoom_bridge in:
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000001.o
        /var/folders/ps/jyf857wx7s10p80vttjspnh80000gv/T/go-link-836730646/000002.o
    ld: 21 duplicate symbols for architecture x86_64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    
    FAIL    bitbucket.org/bfitzsimmons/darkroom [build failed]
    

    This only occurs when running a test. Compiling and running an app which uses the lib. works as intended.

    help wanted 
    opened by bfitzsimmons 10
  • Openslide dependency

    Openslide dependency

    When installing VIPS using the provided gist, a dependency on openslide is introduced, and therefore a requirement to run Homebrew as root is also introduced. This is officially "not supported" by Homebrew, and kills the script if you have installed Homebrew as required.

    The failure:

    $ curl -s https://bitbucket.org/api/2.0/snippets/bfitzsimmons/AaAk/52663c0a731eebeac46bd60bb2d9b1e7916417c2/files/vips_install | sudo bash -
    Could not find libvips using a PKG_CONFIG_PATH of '/usr/lib/pkgconfig:/usr/local/Library/ENV/pkgconfig/10.10::/usr/local/lib/pkgconfig:/usr/lib/pkgconfig'
    Detected Mac OS
    Installing libvips via homebrew
    Error: Cowardly refusing to `sudo brew install`
    You can use brew with sudo, but only if the brew executable is owned by root.
    However, this is both not recommended and completely unsupported so do so at
    your own risk.
    

    The reason for the failure (note the password prompt):

    $ brew install Caskroom/cask/xquartz
    ==> Tapping Caskroom/cask
    Cloning into '/usr/local/Library/Taps/caskroom/homebrew-cask'...
    ...
    ==> Checking out tag v0.54.0
    🍺  /usr/local/Cellar/brew-cask/0.54.0: 2634 files, 10M, built in 4 seconds
    ==> brew cask install Caskroom/cask/xquartz
    ==> We need to make Caskroom for the first time at /opt/homebrew-cask/Caskroom
    ==> We'll set permissions properly so we won't need sudo in the future
    Password:
    ...
    🍺  xquartz staged at '/opt/homebrew-cask/Caskroom/xquartz/2.7.7' (64M)
    

    I know that the gist is coming from the sharp project, but if bimg does not require openslide, should a new gist be created that avoids the dependency? Perhaps a modification of the current one?

    question 
    opened by bfitzsimmons 10
  • Fix for memory issue when watermarking images

    Fix for memory issue when watermarking images

    I rewrote the image watermarking because of the related memory issue I had. See also #138.

    Few remarks:

    • not sure what the specs are for watermarking, I took another approach to watermark an image with another image. Could be that it is not according the specs.

    • ~~when running the test (on OSX) I get an error regarding defering a C-pointer:~~

    • I run some benchmarks already available see the differences below. Benchmarks (ran on OSX, local machine):

    // New implementation
    BenchmarkWatermarkJpeg-4        	      20	  60215874 ns/op
    BenchmarkWatermarPng-4          	     500	   3406345 ns/op
    BenchmarkWatermarWebp-4         	      30	  40243090 ns/op
    BenchmarkWatermarkImageJpeg-4   	      20	  72954939 ns/op
    BenchmarkWatermarImagePng-4     	      30	  38325610 ns/op
    BenchmarkWatermarImageWebp-4    	      20	  70658176 ns/op
    
    // Previous implementation
    BenchmarkWatermarkJpeg-4        	      20	  60050577 ns/op
    BenchmarkWatermarPng-4          	     500	   3385920 ns/op
    BenchmarkWatermarWebp-4         	      30	  39207303 ns/op
    BenchmarkWatermarkImageJpeg-4   	      10	 148488564 ns/op
    BenchmarkWatermarImagePng-4     	      30	  47970915 ns/op
    BenchmarkWatermarImageWebp-4    	      20	  66507471 ns/op
    
    • good news is that the memory issues are solved, and I can use this library to watermark images 👍
    enhancement 
    opened by ajdevries 9
  • Use vips reduce when downscaling

    Use vips reduce when downscaling

    I'm scaling an image down by about half and it seems bimg is using vips_affine to do the downscaling, which results in really aliased images: image

    Instead I've swapped it to use vips_reduce when downscaling: image

    I think this would fix https://github.com/h2non/bimg/issues/94

    opened by vektah 9
  • Gaussian Blur

    Gaussian Blur

    Hi @h2non

    This is a PR to add support for Gaussian Blur. As always, there's a big difference between < 7.41 and >= 7.42. I've tested with 7.40, works great, but I cannot test right now with 7.42 (I'll try in a docker soon).

    Quick information on the PR:

    • Maybe the way I've added the options are not the best, let me know how exactly you want it
    • before 7.42, only one parameter (radius int), after, two parameters (sigma, min_ampl double)
    • I've plugged the call in the transformImage and shouldTransformImage, maybe you want it elsewhere
    • I used the vips_gaussblur method, maybe using a mask is more effective ? that could be something to test
    • No test/bench right now, but I'll add it later, just opening the PR to get a feedback on previous points
    • No documentation yet, same as above, I'll add it later once we are OK on the code itself

    It's not tested on vips >= 7.42, so any feedback on that will be of great help!

    Thanks!

    opened by zllak 9
  • Support RGBA

    Support RGBA

    This PR is a shot at implementing #332.

    • Colors are now RGBA.
    • Embedding now considers adding an alpha channel if necessary.
    • Flattening is now only performed if the background color does not have an alpha channel set (A > 0).
    • Added go.mod (makes it easier to use in "modern" Go projects :-))

    The biggest downside of this change is, that it "breaks" the API by changing the Color struct. I deemed this better than the alternatives, though:

    • Adding a separate struct that supports alpha would mean two Options attributes - one with and one without alpha.

      This means, that it is now harder to communicate which one has precedence and it is also harder to check in code (is the default = empty struct black, or unset?).

      Positive side effect: if now someone actually wants black, s/he has to set the struct to an actual value with an actual alpha channel (otherwise it would stay transparent/unchanged).

      The change itself is only a small piece (not many places use colors) so it is better that the compiler now warns about the changed interface than introducing it silently. Now it can be properly reviewed how the alpha channel should be dealt with.

    • Using an interface (like color.Color in the stdlib) would be a nice way as well, however the perfect name for that interface would be ... Color. So it would also collide with the current struct.

      The naming would then be something like RGB, RGBA (structs) and Color (interface).

      An upside would be, that using an interface in the Options would default to nil. That way we would definitely know if a background color has been set or not. A downside obviously is, that it can be nil.... probably a matter of taste. And of course it also breaks the API compatibility. Just differently.

    • Using interfaces, but keep Color a struct and find a nice name for the other struct (ColorA?) and the interface (RGBA? Colorer? ;-))

      That would most likely keep most of the code compatible (since the bimg.Color would fulfill the interface) but the names are then no really optimal. And there is also still the nil thing which can be either good or bad.

    Feel free to suggest improvements.

    I am happy to hear your stance on the Color change and what you would prefer as well.

    enhancement 
    opened by aksdb 7
  • Performance is low

    Performance is low

    GoCV - 74.686ms Bimg - 3.292993s

    Same task with Imaging (github.com/disintegration/imaging) ~300ms // with python-cv ~150ms // with python PIL ~1.5s

    package main
    
    import (
    	"fmt"
    	"time"
    
    	"github.com/h2non/bimg"
    	"gocv.io/x/gocv"
    )
    
    func do() {
    	st := time.Now().UTC()
    	newMat3 := gocv.NewMat()
    	newMat2 := gocv.NewMat()
    	newMat := gocv.NewMat()
    	mat := gocv.IMRead("/Users/hrachdev/Desktop/hawaii.jpg", gocv.IMReadColor)
    	gocv.Resize(mat, &newMat3, image.Point{0, 0}, 3, 3, gocv.InterpolationArea)
    	gocv.Resize(newMat3, &newMat2, image.Point{0, 0}, 2, 2, gocv.InterpolationArea)
    	gocv.Resize(newMat2, &newMat, image.Point{0, 0}, 0.05, 0.05, gocv.InterpolationArea)
    	gocv.IMWrite("/Users/hrachdev/Desktop/111/haw-cv.jpg", newMat)
    	fmt.Println(time.Since(st))
    
    	st = time.Now().UTC()
    	bf, _ := bimg.Read("/Users/hrachdev/Desktop/hawaii.jpg")
    	imB := bimg.NewImage(bf)
    	szB, _ := imB.Size()
    	opt1 := bimg.Options{
    		Width:        szB.Width * 3,
    		Height:       szB.Height * 3,
    		Quality:      95,
    		Interlace:    true,
    		Interpolator: bimg.Interpolator(gocv.InterpolationArea),
    	}
    	opt2 := bimg.Options{
    		Width:        szB.Width * 6,
    		Height:       szB.Height * 6,
    		Quality:      95,
    		Interlace:    true,
    		Interpolator: bimg.Interpolator(gocv.InterpolationArea),
    	}
    	opt3 := bimg.Options{
    		Width:        int(float32(szB.Width) * 0.3),
    		Height:       int(float32(szB.Height) * 0.3),
    		Quality:      95,
    		Interlace:    true,
    		Interpolator: bimg.Interpolator(gocv.InterpolationArea),
    	}
    	imB.Process(opt1)
    	imB.Process(opt2)
    	imNewB, _ := imB.Process(opt3)
    	bimg.Write("/Users/hrachdev/Desktop/111/haw-bim.jpg", imNewB)
    	fmt.Println(time.Since(st))
    }
    
    func main() {
    	do()
    }
    
    opened by HrachMD 0
  • unable to run with delve on m1 mac

    unable to run with delve on m1 mac

    I am running go version 1.18.2 on an m1 mac. When i try to run go run main.go it runs beautifully without any errors but when I try to run ~/go/bin/dlv debug main.go I get an error saying go build github.com/h2non/bimg: invalid flag in pkg-config --cflags: -Xpreprocessor I have tried running export CGO_CFLAGS_ALLOW=“-Xpreprocessor” && ~/go/bin/dlv debug main.go but to no avail. Any help would be appreciated.

    opened by insaaniManav 0
  • Question: Is true streaming supported?

    Question: Is true streaming supported?

    opened by hamochi 1
  • Dominant RGB color detection

    Dominant RGB color detection

    Hey @h2non,

    Hope you're good. I was looking for a solution to get dominant color from image for padding. I saw you asked this question few years back in VIPS repo and got this solution from @jcu https://gist.github.com/jcupitt/ee3afcbb931b41b4d7f4.

    Looks like it isn't available in bimg, any plans of adding this feature?

    Thanks in advance

    opened by vaibsharma 0
Releases(v1.1.5)
  • v1.1.5(Nov 21, 2020)

  • v1.1.3(Aug 4, 2020)

    v1.1.3 / 2020-08-04

    • fix(ci): disable <8.7 libvips
    • feat: autorotate
    • feat: bump version
    • Merge pull request #347 from vansante/master
    • Merge pull request #345 from fredeastside/more_exif_data
    • add more exif data to metadata
    • Merge pull request #3 from laurentiuilie/add-support-for-heifs-file
    • add brands heis, hevc
    • Merge pull request #2 from laurentiuilie/add-support-for-heifs-file
    • add test image for heifs
    • remove test file and add the check
    • add support for HEIFS file
    • fix(palette): indentation
    • Merge pull request #337 from theplant/master
    • support Palette option for png
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Jun 7, 2020)

    v1.1.0 / 2020-06-07

    • feat(ci): enable libvips versions
    • fix(ci)
    • fix(ci)
    • fix(ci): try exporting env vars
    • fix
    • feat: add Dockerfile / Docker-driven CI job
    • fix(co)
    • feat(version): bump minor to 1
    • fix(ci): try new install
    • fix(ci): try new install
    • fix(ci): add curl package
    • fix(ci): add curl package
    • fix(ci): add curl package
    • fix(ci): try new install
    • fix(ci): indent style
    • fix(ci): indent style
    • fix(ci): indent style
    • Merge pull request #299 from evanoberholster/master
    • refactor(ci): disable verions matrix
    • refactor(docs): use github.com package import path
    • feat: add test image
    • Merge pull request #281 from pohang/skip_smartcrop
    • Merge pull request #317 from larrabee/master
    • Merge pull request #307 from OrderMyGear/eslam/ch15924/some-product-images-have-a-border
    • refactor(travis): adjust matrix versions
    • Merge pull request #333 from simia-tech/master
    • Fix orientation in vipsFlip call (resizer rotateAndFlipImage)
    • chore(docs): delete old contributor
    • enable vipsAffine to use Extend option value and send it to lipvips this will change the default from the one that lipvips use which is background to the ones that bimg use which is C.VIPS_EXTEND_BLACK but because the lip add extra 1 or .5 pix the background is considered black anyway so this will not affect anyone but will fix the bug of having border on the right and bottom of some images
    • Merge pull request #327 from shoreward/master
    • update libvips documentation links
    • fix(vips.h): delete preprocessor HEIF version check
    • Merge pull request #320 from cgroschupp/feat/reduce-png-save-size
    • use VIPS_FOREIGN_PNG_FILTER_ALL in vips_pngsave_bridge
    • fix(resizer): add exported error comment
    • Merge branch 'master' of https://github.com/h2non/bimg
    • chore(ci): temporarily disable go/libvips versions
    • Merge pull request #291 from andrioid/patch-1
    • Merge pull request #293 from team-lab/gammaFilter
    • Merge pull request #315 from vansante/heif
    • feat(version): bump patch
    • Fix bug with images with alpha channel on embeding background
    • Fix typo
    • Dont upgrade version, add missing test file
    • Add support for other HEIF mimetype
    • Supporting auto rotate for HEIF/HEIC images.
    • Adding support for heif (i.e. heic files).
    • Merge branch 'master' into master
    • feat(travis): add libvips 8.6.0 matrix
    • GammaFilter
    • Adds support to Elementary OS Loki
    • Add min dimension logic to smartcrop
    • Merge pull request #271 from Dynom/ImprovingAreaWidthTestCoverage
    • Adding a test case that verifies #250
    • Bumping versions in preinstall script
    • Update Transform ICC Profiles with Input Profile
    Source code(tar.gz)
    Source code(zip)
  • v1.0.19(Mar 26, 2020)

  • v1.0.18(Dec 22, 2017)

    Changes

    v1.0.18 / 2017-12-22

    • Merge pull request #216 from Bynder/master
    • Merge pull request #208 from mikestead/feature/webp-lossless
    • Remove go-debug usage
    • refactor(docs): remove codesponsor :(
    • fix(options): use float64 type in Options.Threshold
    • Merge pull request #206 from tstm/add-trim-options
    • Add lossless option for saving webp
    • Set the test file to write its own file
    • Add the option to use background and threshold options on trim
    Source code(tar.gz)
    Source code(zip)
  • v1.0.17(Dec 22, 2017)

    Changes

    v1.0.17 / 2017-11-14

    • refactor(resizer): remove fmt statement
    • fix(type_test): use string formatting
    • Merge pull request #207 from traum-ferienwohnungen/nearest-neighbour
    • Add nearest-neighbour interpolation
    • Merge pull request #203 from traum-ferienwohnungen/fix_icc_memory_leak
    • Fix memory leak on icc_transform
    Source code(tar.gz)
    Source code(zip)
  • v1.0.15(Oct 5, 2017)

    Changes

    v1.0.15 / 2017-10-05

    • Merge pull request #198 from greut/webpload
    • Add shrink-on-load for webp.
    • Merge pull request #197 from greut/typos
    • Small typo.
    • feat(docs): add codesponsor
    Source code(tar.gz)
    Source code(zip)
  • v1.0.14(Sep 12, 2017)

    Changes

    v1.0.14 / 2017-09-12

    • Merge pull request #192 from greut/trim
    • Adding trim operation.
    • Merge pull request #191 from greut/alpha4
    • Update 8.6 to alpha4.
    Source code(tar.gz)
    Source code(zip)
  • v1.0.10(Jun 26, 2017)

    v1.0.10 / 2017-06-25

    • Merge pull request #164 from greut/length
    • Add Image.Length()
    • Merge pull request #163 from greut/libvips856
    • Run libvips 8.5.6 on Travis.
    • Merge pull request #161 from henry-blip/master
    • Expose vips cache memory management functions.
    • feat(docs): add watermark image note in features
    Source code(tar.gz)
    Source code(zip)
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

Gojek 195 Aug 12, 2022
A lightning fast image processing and resizing library for Go

govips A lightning fast image processing and resizing library for Go This package wraps the core functionality of libvips image processing library by

David Byttow 740 Aug 19, 2022
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

null 0 Jan 5, 2022
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

Grigory Dryapak 4.3k Aug 18, 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

Guillermo Estrada 60 Aug 14, 2022
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

null 0 Nov 26, 2021
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

null 0 Nov 26, 2021
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

Anthony N. Simon 3.6k Aug 9, 2022
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

Marcin Kaciuba 459 Aug 12, 2022
Efficient moving window for high-speed data processing.

Moving Window Data Structure Copyright (c) 2012. Jake Brukhman. ([email protected]). All rights reserved. See the LICENSE file for BSD-style license. I

Jake Brukhman 31 Jun 30, 2021
Go bindings for libVLC and high-level media player interface

Go bindings for libVLC 2.X/3.X/4.X and high-level media player interface. The package can be useful for adding multimedia capabilities to applications

Adrian-George Bostan 310 Jul 28, 2022
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

Youngbin Han 4 Jan 14, 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

Cristina Simionescu 0 Nov 25, 2021
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

Dmitry Chestnykh 8 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

makeworld 251 Jul 25, 2022
⚡High Performance DICOM Medical Image Parser in Go.

dicom High Performance Golang DICOM Medical Image Parser ?? v1.0 just released! This is a library and command-line tool to read, write, and generally

Suyash Kumar 753 Jul 28, 2022
An extensive, fast, and accurate command-line image dithering tool.

didder is an extensive, fast, and accurate command-line image dithering tool. It is designed to work well for both power users as well as pipeline scripting. It is backed by my dithering library, and is unique in its correctness and variety of dithering algorithms.

makeworld 132 Jul 26, 2022
Fast Image Convolutions (Gaussian) Blur

Usage package main import ( "image" "image/jpeg" "os" "github.com/0xc0d/ficblur" ) func main() { imageFile, err := os.Open("img.jpeg") panicN

Ali Josie 0 Feb 5, 2022
Go package for decoding and encoding TARGA image format

tga tga is a Go package for decoding and encoding TARGA image format. It supports RLE and raw TARGA images with 8/15/16/24/32 bits per pixel, monochro

Sigrid Solveig Haflínudóttir 31 Jul 29, 2022