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

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

Comments
  • 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.

  • 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
    
  • 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).

  • 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
    }
    
  • 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
  • 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.

  • 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?

  • 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 👍
  • 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

  • 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!

  • 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.

  • How to use package with clang compiler?

    How to use package with clang compiler?

    I have clang installed and available in PATH, but when I try to build my project, I get this error:

    # github.com/h2non/bimg
    cgo: C compiler "gcc" not found: exec: "gcc": executable file not found in %PATH%
    

    How to make it work with clang?

  • Is it possible to use bimg on Windows?

    Is it possible to use bimg on Windows?

    Bimg looks like a great package and exactly what I was looking for, but installation looks a littble bit tricky, especially on Windows. I don't understand how to provide necessary dependencies, which are libvips and C compiler :( Is there any manual for it?

  • VIPS-WARNING  and corrupted image

    VIPS-WARNING and corrupted image

    I'm converting some by compressing some images, but sometimes the alert appears:

    (process:21837): VIPS-WARNING **: 10:16:34.520: read gave 149 warnings
    (process:21837): VIPS-WARNING **: 10:16:34.530:
    

    when this alert appears I notice that the compressed image has been corrupted Does anyone know how I would capture this warning of a specific image for treatment using bimg or golang?

    I'm using this code:

    func compress(inputName string, outPutName string) error {
    	options := bimg.Options{
    		Type:    bimg.JPEG,
    		Width:   480,
    		Quality: 80,
    	}
    
    	buffer, err := bimg.Read(inputName)
    	if err != nil {
    		return err
    	}
    
    	newImage, err := bimg.NewImage(buffer).Process(options)
    	if err != nil {
    		return err
    	}
    
    	err = bimg.Write(outPutName, newImage)
    	if err != nil {
    		return err
    	}
    	return nil
    }
    
  • Support concatenation of two images: vips_join()

    Support concatenation of two images: vips_join()

    A vips_join operation in the library allows concatenating two images one by another. It's widely used in document processing backends.

    Docs

    https://www.libvips.org/API/current/libvips-conversion.html#vips-join

    Signature

    As basic example:

    func VipsJoin(image1 *C.VipsImage, image2 *C.VipsImage, d Direction, ...opts JoinOpt) (*C.VipsImage, error);
    

    Example

    gopher copy

  • Issue with Image DPI quality

    Issue with Image DPI quality

    I used the library to watermark my image but the image DPI has gone down to 72. I want to know update it back to its original value but there is no way i could find out to update its metadata or any other relevant functions. Can you please help me update the DPI?

  • Expose resampling kernel param in vips_reduce

    Expose resampling kernel param in vips_reduce

    Adds Kernel in bimg.Option.

    Uses the kernel param in vips_reduce https://www.libvips.org/API/current/libvips-resample.html#vips-reduce

    Tries to solve https://github.com/h2non/bimg/issues/428

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
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

Jan 8, 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
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
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
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
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
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

Sep 4, 2022
Go bindings for libVLC and high-level media player interface
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

Dec 31, 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

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

Nov 25, 2021
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
⚡High Performance DICOM Medical Image Parser in Go.
⚡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

Jan 4, 2023
An extensive, fast, and accurate command-line image dithering tool.
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.

Dec 31, 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

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

Sep 26, 2022