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

Overview

imaginary Build Status Docker Docker Registry Go Report Card Fly.io

Fast HTTP microservice written in Go for high-level image processing backed by bimg and libvips. imaginary can be used as private or public HTTP service for massive image processing with first-class support for Docker & Fly.io. It's almost dependency-free and only uses net/http native package without additional abstractions for better performance.

Supports multiple image operations exposed as a simple HTTP API, with additional optional features such as API token authorization, URL signature protection, HTTP traffic throttle strategy and CORS support for web clients.

imaginary can read images from HTTP POST payloads, server local path or remote HTTP servers, supporting JPEG, PNG, WEBP, HEIF, and optionally TIFF, PDF, GIF and SVG formats if [email protected]+ is compiled with proper library bindings.

imaginary is able to output images as JPEG, PNG and WEBP formats, including transparent conversion across them.

imaginary also optionally supports image placeholder fallback mechanism in case of image processing error or server error of any nature, therefore an image will be always returned by the server in terms of HTTP response body and content MIME type, even in case of error, matching the expected image size and format transparently.

imaginary uses internally libvips, a powerful and efficient library written in C for fast 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.

To get started, take a look the installation steps, usage cases and API docs.

Contents

Supported image operations

  • Resize
  • Enlarge
  • Crop
  • SmartCrop (based on libvips built-in algorithm)
  • Rotate (with auto-rotate based on EXIF orientation)
  • AutoRotate with further image transformations (based on EXIF metadata orientation)
  • Flip (with auto-flip based on EXIF metadata)
  • Flop
  • Zoom
  • Thumbnail
  • Fit
  • Pipeline of multiple independent image transformations in a single HTTP request.
  • Configurable image area extraction
  • Embed/Extend image, supporting multiple modes (white, black, mirror, copy or custom background color)
  • Watermark (customizable by text)
  • Watermark image
  • Custom output color space (RGB, black/white...)
  • Format conversion (with additional quality/compression settings)
  • Info (image size, format, orientation, alpha...)
  • Reply with default or custom placeholder image in case of error.
  • Blur

Prerequisites

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

Installation

go get -u github.com/h2non/imaginary

Also, be sure you have the latest version of bimg:

go get -u github.com/h2non/bimg

libvips

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 -

The install script requires curl and pkg-config

Docker

See Dockerfile for image details.

Fetch the image (comes with latest stable Go and libvips versions)

docker pull h2non/imaginary

Start the container with optional flags (default listening on port 9000)

docker run -p 9000:9000 h2non/imaginary -cors -gzip

Start the container enabling remote URL source image processing via GET requests and url query param.

docker run -p 9000:9000 h2non/imaginary -p 9000 -enable-url-source

Start the container enabling local directory image process via GET requests and file query param.

docker run -p 9000:9000 h2non/imaginary -p 900 -mount /volume/images

Start the container in debug mode:

docker run -p 9000:9000 -e "DEBUG=*" h2non/imaginary

Enter to the interactive shell in a running container

sudo docker exec -it <containerIdOrName> bash

Stop the container

docker stop h2non/imaginary

For more usage examples, see the command line usage.

All Docker images tags are available here.

Docker Compose

You can add imaginary to your docker-compose.yml file:

version: "3"
services:
  imaginary:
    image: h2non/imaginary:latest
    # optionally mount a volume as local image source
    volumes:
      - images:/mnt/data
    environment:
       PORT: 9000
    command: -enable-url-source -mount /mnt/data
    ports:
      - "9000:9000"

Fly.io

Deploy imaginary in seconds close to your users in Fly.io cloud by clicking on the button below:

About Fly.io

Fly is a platform for applications that need to run globally. It runs your code close to users and scales compute in cities where your app is busiest. Write your code, package it into a Docker image, deploy it to Fly's platform and let that do all the work to keep your app snappy.

You can learn more about how Fly.io can reduce latency and provide a better experience by serving traffic close to your users location.

Global image service tutorial

Learn more about how to run a custom deployment of imaginary on the Fly.io cloud.

CloudFoundry

Assuming you have cloudfoundry account, bluemix or pivotal and command line utility installed.

Clone this repository:

git clone https://github.com/h2non/imaginary.git

Push the application

cf push -b https://github.com/yacloud-io/go-buildpack-imaginary.git imaginary-inst01 --no-start

Define the library path

cf set-env imaginary-inst01 LD_LIBRARY_PATH /home/vcap/app/vendor/vips/lib

Start the application

cf start imaginary-inst01

Recommended resources

Given the multithreaded native nature of Go, in terms of CPUs, most cores means more concurrency and therefore, a better performance can be achieved. From the other hand, in terms of memory, 512MB of RAM is usually enough for small services with low concurrency (<5 requests/second). Up to 2GB for high-load HTTP service processing potentially large images or exposed to an eventual high concurrency.

If you need to expose imaginary as public HTTP server, it's highly recommended to protect the service against DDoS-like attacks. imaginary has built-in support for HTTP concurrency throttle strategy to deal with this in a more convenient way and mitigate possible issues limiting the number of concurrent requests per second and caching the awaiting requests, if necessary.

Production notes

In production focused environments it's highly recommended to enable the HTTP concurrency throttle strategy in your imaginary servers.

The recommended concurrency limit per server to guarantee a good performance is up to 20 requests per second.

You can enable it simply passing a flag to the binary:

$ imaginary -concurrency 20

Memory issues

In case you are experiencing any persistent unreleased memory issues in your deployment, you can try passing this environemnt variables to imaginary:

MALLOC_ARENA_MAX=2 imaginary -p 9000 -enable-url-source

Graceful shutdown

When you use a cluster, it is necessary to control how the deployment is executed, and it is very useful to finish the containers in a controlled.

You can use the next command:

$ ps auxw | grep 'bin/imaginary' | awk 'NR>1{print buf}{buf = $2}' | xargs kill -TERM > /dev/null 2>&1

Scalability

If you're looking for a large scale solution for massive image processing, you should scale imaginary horizontally, distributing the HTTP load across a pool of imaginary servers.

Assuming that you want to provide a high availability to deal efficiently with, let's say, 100 concurrent req/sec, a good approach would be using a front end balancer (e.g: HAProxy) to delegate the traffic control flow, ensure the quality of service and distribution the HTTP across a pool of servers:

        |==============|
        |  Dark World  |
        |==============|
              ||||
        |==============|
        |   Balancer   |
        |==============|
           |       |
          /         \
         /           \
        /             \
 /-----------\   /-----------\
 | imaginary |   | imaginary | (*n)
 \-----------/   \-----------/

Clients

Feel free to send a PR if you created a client for other language.

Performance

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

Benchmark

See benchmark.sh for more details

Environment: Go 1.4.2. libvips-7.42.3. OSX i7 2.7Ghz

Requests  [total]       200
Duration  [total, attack, wait]   10.030639787s, 9.949499515s, 81.140272ms
Latencies [mean, 50, 95, 99, max]   83.124471ms, 82.899435ms, 88.948008ms, 95.547765ms, 104.384977ms
Bytes In  [total, mean]     23443800, 117219.00
Bytes Out [total, mean]     175517000, 877585.00
Success   [ratio]       100.00%
Status Codes  [code:count]      200:200

Conclusions

imaginary can deal efficiently with up to 20 request per second running in a multicore machine, where it crops a JPEG image of 5MB and spending per each request less than 100 ms

The most expensive image operation under high concurrency scenarios (> 20 req/sec) is the image enlargement, which requires a considerable amount of math operations to scale the original image. In this kind of operation the required processing time usually grows over the time if you're stressing the server continuously. The advice here is as simple as taking care about the number of concurrent enlarge operations to avoid server performance bottlenecks.

Command-line usage

Usage:
  imaginary -p 80
  imaginary -cors
  imaginary -concurrency 10
  imaginary -path-prefix /api/v1
  imaginary -enable-url-source
  imaginary -disable-endpoints form,health,crop,rotate
  imaginary -enable-url-source -allowed-origins http://localhost,http://server.com,http://*.example.org
  imaginary -enable-url-source -enable-auth-forwarding
  imaginary -enable-url-source -authorization "Basic AwDJdL2DbwrD=="
  imaginary -enable-placeholder
  imaginary -enable-url-source -placeholder ./placeholder.jpg
  imaginary -enable-url-signature -url-signature-key 4f46feebafc4b5e988f131c4ff8b5997
  imaginary -enable-url-source -forward-headers X-Custom,X-Token
  imaginary -h | -help
  imaginary -v | -version

Options:
  -a <addr>                 Bind address [default: *]
  -p <port>                 Bind port [default: 8088]
  -h, -help                 Show help
  -v, -version              Show version
  -path-prefix <value>      Url path prefix to listen to [default: "/"]
  -cors                     Enable CORS support [default: false]
  -gzip                     Enable gzip compression (deprecated) [default: false]
  -disable-endpoints        Comma separated endpoints to disable. E.g: form,crop,rotate,health [default: ""]
  -key <key>                Define API key for authorization
  -mount <path>             Mount server local directory
  -http-cache-ttl <num>     The TTL in seconds. Adds caching headers to locally served files.
  -http-read-timeout <num>  HTTP read timeout in seconds [default: 60]
  -http-write-timeout <num> HTTP write timeout in seconds [default: 60]
  -enable-url-source        Enable remote HTTP URL image source processing (?url=http://..)
  -enable-placeholder       Enable image response placeholder to be used in case of error [default: false]
  -enable-auth-forwarding   Forwards X-Forward-Authorization or Authorization header to the image source server. -enable-url-source flag must be defined. Tip: secure your server from public access to prevent attack vectors
  -forward-headers          Forwards custom headers to the image source server. -enable-url-source flag must be defined.
  -enable-url-signature     Enable URL signature (URL-safe Base64-encoded HMAC digest) [default: false]
  -url-signature-key        The URL signature key (32 characters minimum)
  -allowed-origins <urls>   Restrict remote image source processing to certain origins (separated by commas). Note: Origins are validated against host *AND* path.
  -max-allowed-size <bytes> Restrict maximum size of http image source (in bytes)
  -certfile <path>          TLS certificate file path
  -keyfile <path>           TLS private key file path
  -authorization <value>    Defines a constant Authorization header value passed to all the image source servers. -enable-url-source flag must be defined. This overwrites authorization headers forwarding behavior via X-Forward-Authorization
  -placeholder <path>       Image path to image custom placeholder to be used in case of error. Recommended minimum image size is: 1200x1200
  -concurrency <num>        Throttle concurrency limit per second [default: disabled]
  -burst <num>              Throttle burst max cache size [default: 100]
  -mrelease <num>           OS memory release interval in seconds [default: 30]
  -cpus <num>               Number of used cpu cores.
                            (default for current machine is 8 cores)
  -log-level                Set log level for http-server. E.g: info,warning,error [default: info].
                            Or can use the environment variable GOLANG_LOG=info.

Start the server in a custom port:

imaginary -p 8080

Also, you can pass the port as environment variable:

PORT=8080 imaginary

Enable HTTP server throttle strategy (max 10 requests/second):

imaginary -p 8080 -concurrency 10

Enable remote URL image fetching (then you can do GET request passing the url=http://server.com/image.jpg query param):

imaginary -p 8080 -enable-url-source

Mount local directory (then you can do GET request passing the file=image.jpg query param):

imaginary -p 8080 -mount ~/images

Enable authorization header forwarding to image origin server. X-Forward-Authorization or Authorization (by priority) header value will be forwarded as Authorization header to the target origin server, if one of those headers are present in the incoming HTTP request. Security tip: secure your server from public access to prevent attack vectors when enabling this option:

imaginary -p 8080 -enable-url-source -enable-auth-forwarding

Or alternatively you can manually define an constant Authorization header value that will be always sent when fetching images from remote image origins. If defined, X-Forward-Authorization or Authorization headers won't be forwarded, and therefore ignored, if present. Note:

imaginary -p 8080 -enable-url-source -authorization "Bearer s3cr3t"

Send fixed caching headers in the response. The headers can be set in either "cache nothing" or "cache for N seconds". By specifying 0 imaginary will send the "don't cache" headers, otherwise it sends headers with a TTL. The following example informs the client to cache the result for 1 year:

imaginary -p 8080 -enable-url-source -http-cache-ttl 31556926

Enable placeholder image HTTP responses in case of server error/bad request. The placeholder image will be dynamically and transparently resized matching the expected image widthxheight define in the HTTP request params. Also, the placeholder image will be also transparently converted to the desired image type defined in the HTTP request params, so the API contract should be maintained as much better as possible.

This feature is particularly useful when using imaginary as public HTTP service consumed by Web clients. In case of error, the appropriate HTTP status code will be used to reflect the error, and the error details will be exposed serialized as JSON in the Error response HTTP header, for further inspection and convenience for API clients.

imaginary -p 8080 -enable-placeholder -enable-url-source

You can optionally use a custom placeholder image. Since the placeholder image should fit a variety of different sizes, it's recommended to use a large image, such as 1200x1200. Supported custom placeholder image types are: JPEG, PNG and WEBP.

imaginary -p 8080 -placeholder=placeholder.jpg -enable-url-source

Enable URL signature (URL-safe Base64-encoded HMAC digest).

This feature is particularly useful to protect against multiple image operations attacks and to verify the requester identity.

imaginary -p 8080 -enable-url-signature -url-signature-key 4f46feebafc4b5e988f131c4ff8b5997

It is recommanded to pass key as environment variables:

URL_SIGNATURE_KEY=4f46feebafc4b5e988f131c4ff8b5997 imaginary -p 8080 -enable-url-signature

Increase libvips threads concurrency (experimental):

VIPS_CONCURRENCY=10 imaginary -p 8080 -concurrency 10

Enable debug mode:

DEBUG=* imaginary -p 8080

Or filter debug output by package:

DEBUG=imaginary imaginary -p 8080

Disable info logs:

GOLANG_LOG=error imaginary -p 8080

Examples

Reading a local image (you must pass the -mount=<directory> flag):

curl -O "http://localhost:8088/crop?width=500&height=400&file=foo/bar/image.jpg"

Fetching the image from a remote server (you must pass the -enable-url-source flag):

curl -O "http://localhost:8088/crop?width=500&height=400&url=https://raw.githubusercontent.com/h2non/imaginary/master/testdata/large.jpg"

Crop behaviour can be influenced with the gravity parameter. You can specify a preference for a certain region (north, south, etc.). To enable Smart Crop you can specify the value "smart" to autodetect the most interesting section to consider as center point for the crop operation:

curl -O "http://localhost:8088/crop?width=500&height=200&gravity=smart&url=https://raw.githubusercontent.com/h2non/imaginary/master/testdata/smart-crop.jpg"

Playground

imaginary exposes an ugly HTML form for playground purposes in: http://localhost:8088/form

HTTP API

Allowed Origins

imaginary can be configured to block all requests for images with a src URL this is not specified in the allowed-origins list. Imaginary will validate that the remote url matches the hostname and path of at least one origin in allowed list. Perhaps the easiest way to show how this works is to show some examples.

allowed-origins setting image url is valid
--allowed-origins s3.amazonaws.com/some-bucket/ s3.amazonaws.com/some-bucket/images/image.png VALID
--allowed-origins s3.amazonaws.com/some-bucket/ s3.amazonaws.com/images/image.png NOT VALID (no matching basepath)
--allowed-origins s3.amazonaws.com/some-* s3.amazonaws.com/some-bucket/images/image.png VALID
--allowed-origins *.amazonaws.com/some-bucket/ anysubdomain.amazonaws.com/some-bucket/images/image.png VALID
--allowed-origins *.amazonaws.com anysubdomain.amazonaws.comimages/image.png VALID
--allowed-origins *.amazonaws.com www.notaws.comimages/image.png NOT VALID (no matching host)
--allowed-origins *.amazonaws.com, foo.amazonaws.com/some-bucket/ bar.amazonaws.com/some-other-bucket/image.png VALID (matches first condition but not second)

Authorization

imaginary supports a simple token-based API authorization. To enable it, you should pass the -key flag to the binary.

API token can be defined as HTTP header (API-Key) or query param (key).

Example request with API key:

POST /crop HTTP/1.1
Host: localhost:8088
API-Key: secret

URL signature

The URL signature is provided by the sign request parameter.

The HMAC-SHA256 hash is created by taking the URL path (including the leading /), the request parameters (alphabetically-sorted and concatenated with & into a string). The hash is then base64url-encoded.

Here an example in Go:

signKey  := "4f46feebafc4b5e988f131c4ff8b5997"
urlPath  := "/resize"
urlQuery := "file=image.jpg&height=200&type=jpeg&width=300"

h := hmac.New(sha256.New, []byte(signKey))
h.Write([]byte(urlPath))
h.Write([]byte(urlQuery))
buf := h.Sum(nil)

fmt.Println("sign=" + base64.RawURLEncoding.EncodeToString(buf))

Errors

imaginary will always reply with the proper HTTP status code and JSON body with error details.

Here an example response error when the payload is empty:

{
  "message": "Cannot read payload: no such file",
  "code": 1
}

See all the predefined supported errors here.

Placeholder

If -enable-placeholder or -placeholder <image path> flags are passed to imaginary, a placeholder image will be used in case of error or invalid request input.

If -enable-placeholder is passed, the default imaginary placeholder image will be used, however you can customized it via -placeholder flag, loading a custom compatible image from the file system.

Since imaginary has been partially designed to be used as public HTTP service, including web pages, in certain scenarios the response MIME type must be respected, so the server will always reply with a placeholder image in case of error, such as image processing error, read error, payload error, request invalid request or any other.

You can customize the placeholder image passing the -placeholder <image path> flag when starting imaginary.

In this scenarios, the error message details will be exposed in the Error response header field as JSON for further inspection from API clients.

In some edge cases the placeholder image resizing might fail, so a 400 Bad Request will be used as response status and the Content-Type will be application/json with the proper message info. Note that this scenario won't be common.

Form data

If you're pushing images to imaginary as multipart/form-data (you can do it as well as image/*), you must define at least one input field called file with the raw image data in order to be processed properly by imaginary.

Params

Complete list of available params. Take a look to each specific endpoint to see which params are supported. Image measures are always in pixels, unless otherwise indicated.

  • width int - Width of image area to extract/resize
  • height int - Height of image area to extract/resize
  • top int - Top edge of area to extract. Example: 100
  • left int - Left edge of area to extract. Example: 100
  • areawidth int - Height area to extract. Example: 300
  • areaheight int - Width area to extract. Example: 300
  • quality int - JPEG image quality between 1-100. Defaults to 80
  • compression int - PNG compression level. Default: 6
  • rotate int - Image rotation angle. Must be multiple of 90. Example: 180
  • factor int - Zoom factor level. Example: 2
  • margin int - Text area margin for watermark. Example: 50
  • dpi int - DPI value for watermark. Example: 150
  • textwidth int - Text area width for watermark. Example: 200
  • opacity float - Opacity level for watermark text or watermark image. Default: 0.2
  • flip bool - Transform the resultant image with flip operation. Default: false
  • flop bool - Transform the resultant image with flop operation. Default: false
  • force bool - Force image transformation size. Default: false
  • nocrop bool - Disable crop transformation. Defaults depend on the operation
  • noreplicate bool - Disable text replication in watermark. Defaults to false
  • norotation bool - Disable auto rotation based on EXIF orientation. Defaults to false
  • noprofile bool - Disable adding ICC profile metadata. Defaults to false
  • stripmeta bool - Remove original image metadata, such as EXIF metadata. Defaults to false
  • text string - Watermark text content. Example: copyright (c) 2189
  • font string - Watermark text font type and format. Example: sans bold 12
  • color string - Watermark text RGB decimal base color. Example: 255,200,150
  • image string - Watermark image URL pointing to the remote HTTP server.
  • type string - Specify the image format to output. Possible values are: jpeg, png, webp and auto. auto will use the preferred format requested by the client in the HTTP Accept header. A client can provide multiple comma-separated choices in Accept with the best being the one picked.
  • gravity string - Define the crop operation gravity. Supported values are: north, south, centre, west, east and smart. Defaults to centre.
  • file string - Use image from server local file path. In order to use this you must pass the -mount=<dir> flag.
  • url string - Fetch the image from a remote HTTP server. In order to use this you must pass the -enable-url-source flag.
  • colorspace string - Use a custom color space for the output image. Allowed values are: srgb or bw (black&white)
  • field string - Custom image form field name if using multipart/form. Defaults to: file
  • extend string - Extend represents the image extend mode used when the edges of an image are extended. Defaults to mirror. Allowed values are: black, copy, mirror, white, lastpixel and background. If background value is specified, you can define the desired extend RGB color via background param, such as ?extend=background&background=250,20,10. For more info, see libvips docs.
  • background string - Background RGB decimal base color to use when flattening transparent PNGs. Example: 255,200,150
  • sigma float - Size of the gaussian mask to use when blurring an image. Example: 15.0
  • minampl float - Minimum amplitude of the gaussian filter to use when blurring an image. Default: Example: 0.5
  • operations json - Pipeline of image operation transformations defined as URL safe encoded JSON array. See pipeline endpoints for more details.
  • sign string - URL signature (URL-safe Base64-encoded HMAC digest)
  • interlace bool - Use progressive / interlaced format of the image output. Defaults to false
  • aspectratio string - Apply aspect ratio by giving either image's height or width. Exampe: 16:9

GET /

Content-Type: application/json

Serves as JSON the current imaginary, bimg and libvips versions.

Example response:

{
  "imaginary": "0.1.28",
  "bimg": "1.0.5",
  "libvips": "8.4.1"
}

GET /health

Content-Type: application/json

Provides some useful statistics about the server stats with the following structure:

  • uptime number - Server process uptime in seconds.
  • allocatedMemory number - Currently allocated memory in megabytes.
  • totalAllocatedMemory number - Total allocated memory over the time in megabytes.
  • goroutines number - Number of running goroutines.
  • cpus number - Number of used CPU cores.

Example response:

{
  "uptime": 1293,
  "allocatedMemory": 5.31,
  "totalAllocatedMemory": 34.3,
  "goroutines": 19,
  "cpus": 8
}

GET /form

Content Type: text/html

Serves an ugly HTML form, just for testing/playground purposes

GET | POST /info

Accepts: image/*, multipart/form-data. Content-Type: application/json

Returns the image metadata as JSON:

{
  "width": 550,
  "height": 740,
  "type": "jpeg",
  "space": "srgb",
  "hasAlpha": false,
  "hasProfile": true,
  "channels": 3,
  "orientation": 1
}

GET | POST /crop

Accepts: image/*, multipart/form-data. Content-Type: image/*

Crop the image by a given width or height. Image ratio is maintained

Allowed params
  • width int
  • height int
  • quality int (JPEG-only)
  • compression int (PNG-only)
  • type string
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
  • force bool
  • rotate int
  • embed bool
  • norotation bool
  • noprofile bool
  • flip bool
  • flop bool
  • stripmeta bool
  • extend string
  • background string - Example: ?background=250,20,10
  • colorspace string
  • sigma float
  • minampl float
  • gravity string
  • field string - Only POST and multipart/form payloads
  • interlace bool
  • aspectratio string

GET | POST /smartcrop

Accepts: image/*, multipart/form-data. Content-Type: image/*

Crop the image by a given width or height using the libvips built-in smart crop algorithm.

Allowed params
  • width int
  • height int
  • quality int (JPEG-only)
  • compression int (PNG-only)
  • type string
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
  • force bool
  • rotate int
  • embed bool
  • norotation bool
  • noprofile bool
  • flip bool
  • flop bool
  • stripmeta bool
  • extend string
  • background string - Example: ?background=250,20,10
  • colorspace string
  • sigma float
  • minampl float
  • gravity string
  • field string - Only POST and multipart/form payloads
  • interlace bool
  • aspectratio string

GET | POST /resize

Accepts: image/*, multipart/form-data. Content-Type: image/*

Resize an image by width or height. Image aspect ratio is maintained

Allowed params
  • width int required
  • height int
  • quality int (JPEG-only)
  • compression int (PNG-only)
  • type string
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
  • embed bool
  • force bool
  • rotate int
  • nocrop bool - Defaults to true
  • norotation bool
  • noprofile bool
  • stripmeta bool
  • flip bool
  • flop bool
  • extend string
  • background string - Example: ?background=250,20,10
  • colorspace string
  • sigma float
  • minampl float
  • field string - Only POST and multipart/form payloads
  • interlace bool
  • aspectratio string

GET | POST /enlarge

Accepts: image/*, multipart/form-data. Content-Type: image/*

Allowed params
  • width int required
  • height int required
  • quality int (JPEG-only)
  • compression int (PNG-only)
  • type string
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
  • embed bool
  • force bool
  • rotate int
  • nocrop bool - Defaults to false
  • norotation bool
  • noprofile bool
  • stripmeta bool
  • flip bool
  • flop bool
  • extend string
  • background string - Example: ?background=250,20,10
  • colorspace string
  • sigma float
  • minampl float
  • field string - Only POST and multipart/form payloads
  • interlace bool

GET | POST /extract

Accepts: image/*, multipart/form-data. Content-Type: image/*

Allowed params
  • top int required
  • left int
  • areawidth int required
  • areaheight int
  • width int
  • height int
  • quality int (JPEG-only)
  • compression int (PNG-only)
  • type string
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
  • embed bool
  • force bool
  • rotate int
  • norotation bool
  • noprofile bool
  • stripmeta bool
  • flip bool
  • flop bool
  • extend string
  • background string - Example: ?background=250,20,10
  • colorspace string
  • sigma float
  • minampl float
  • field string - Only POST and multipart/form payloads
  • interlace bool
  • aspectratio string

GET | POST /zoom

Accepts: image/*, multipart/form-data. Content-Type: image/*

Allowed params
  • factor number required
  • width int
  • height int
  • quality int (JPEG-only)
  • compression int (PNG-only)
  • type string
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
  • embed bool
  • force bool
  • rotate int
  • nocrop bool - Defaults to true
  • norotation bool
  • noprofile bool
  • stripmeta bool
  • flip bool
  • flop bool
  • extend string
  • background string - Example: ?background=250,20,10
  • colorspace string
  • sigma float
  • minampl float
  • field string - Only POST and multipart/form payloads
  • interlace bool
  • aspectratio string

GET | POST /thumbnail

Accepts: image/*, multipart/form-data. Content-Type: image/*

Allowed params
  • width int required
  • height int required
  • quality int (JPEG-only)
  • compression int (PNG-only)
  • type string
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
  • embed bool
  • force bool
  • rotate int
  • norotation bool
  • noprofile bool
  • stripmeta bool
  • flip bool
  • flop bool
  • extend string
  • background string - Example: ?background=250,20,10
  • colorspace string
  • sigma float
  • minampl float
  • field string - Only POST and multipart/form payloads
  • interlace bool
  • aspectratio string

GET | POST /fit

Accepts: image/*, multipart/form-data. Content-Type: image/*

Resize an image to fit within width and height, without cropping. Image aspect ratio is maintained The width and height specify a maximum bounding box for the image.

Allowed params
  • width int required
  • height int required
  • quality int (JPEG-only)
  • compression int (PNG-only)
  • type string
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
  • embed bool
  • force bool
  • rotate int
  • norotation bool
  • noprofile bool
  • stripmeta bool
  • flip bool
  • flop bool
  • extend string
  • background string - Example: ?background=250,20,10
  • colorspace string
  • sigma float
  • minampl float
  • field string - Only POST and multipart/form payloads
  • interlace bool
  • aspectratio string

GET | POST /rotate

Accepts: image/*, multipart/form-data. Content-Type: image/*

GET | POST /autorotate

Accepts: image/*, multipart/form-data. Content-Type: image/*

Automatically rotate the image with no further image transformations based on EXIF orientation metadata.

Returns a new image with the same size and format as the input image.

Allowed params
  • rotate int required
  • width int
  • height int
  • quality int (JPEG-only)
  • compression int (PNG-only)
  • type string
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
  • embed bool
  • force bool
  • norotation bool
  • noprofile bool
  • stripmeta bool
  • flip bool
  • flop bool
  • extend string
  • background string - Example: ?background=250,20,10
  • colorspace string
  • sigma float
  • minampl float
  • field string - Only POST and multipart/form payloads
  • interlace bool
  • aspectratio string

GET | POST /flip

Accepts: image/*, multipart/form-data. Content-Type: image/*

Allowed params
  • width int
  • height int
  • quality int (JPEG-only)
  • compression int (PNG-only)
  • type string
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
  • embed bool
  • force bool
  • norotation bool
  • noprofile bool
  • stripmeta bool
  • flip bool
  • flop bool
  • extend string
  • background string - Example: ?background=250,20,10
  • colorspace string
  • sigma float
  • minampl float
  • field string - Only POST and multipart/form payloads
  • interlace bool
  • aspectratio string

GET | POST /flop

Accepts: image/*, multipart/form-data. Content-Type: image/*

Allowed params
  • width int
  • height int
  • quality int (JPEG-only)
  • compression int (PNG-only)
  • type string
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
  • embed bool
  • force bool
  • norotation bool
  • noprofile bool
  • stripmeta bool
  • flip bool
  • flop bool
  • extend string
  • background string - Example: ?background=250,20,10
  • colorspace string
  • sigma float
  • minampl float
  • field string - Only POST and multipart/form payloads
  • interlace bool
  • aspectratio string

GET | POST /convert

Accepts: image/*, multipart/form-data. Content-Type: image/*

Allowed params
  • type string required
  • quality int (JPEG-only)
  • compression int (PNG-only)
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
  • embed bool
  • force bool
  • rotate int
  • norotation bool
  • noprofile bool
  • stripmeta bool
  • flip bool
  • flop bool
  • extend string
  • background string - Example: ?background=250,20,10
  • colorspace string
  • sigma float
  • minampl float
  • field string - Only POST and multipart/form payloads
  • interlace bool
  • aspectratio string

GET | POST /pipeline

Accepts: image/*, multipart/form-data. Content-Type: image/*

This endpoint allow the user to declare a pipeline of multiple independent image transformation operations all in a single HTTP request.

Note: a maximum of 10 independent operations are current allowed within the same HTTP request.

Internally, it operates pretty much as a sequential reducer pattern chain, where given an input image and a set of operations, for each independent image operation iteration, the output result image will be passed to the next one, as the accumulated result, until finishing all the operations.

In imperative programming, this would be pretty much analog to the following code:

var image
for operation in operations {
  image = operation.Run(image, operation.Options)
}
Allowed params
  • operations json required - URL safe encoded JSON with a list of operations. See below for interface details.
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
Operations JSON specification

Self-documented JSON operation schema:

[
  {
    "operation": string, // Operation name identifier. Required.
    "ignore_failure": boolean, // Ignore error in case of failure and continue with the next operation. Optional.
    "params": map[string]mixed, // Object defining operation specific image transformation params, same as supported URL query params per each endpoint.
  }
]
Supported operations names
Example
[
  {
    "operation": "crop",
    "params": {
      "width": 500,
      "height": 300
    }
  },
  {
    "operation": "watermark",
    "params": {
      "text": "I need some covfete",
      "font": "Verdana",
      "textwidth": 100,
      "opacity": 0.8
    }
  },
  {
    "operation": "rotate",
    "params": {
      "rotate": 180
    }
  },
  {
    "operation": "convert",
    "params": {
      "type": "webp"
    }
  }
]

GET | POST /watermark

Accepts: image/*, multipart/form-data. Content-Type: image/*

Allowed params
  • text string required
  • margin int
  • dpi int
  • textwidth int
  • opacity float
  • noreplicate bool
  • font string
  • color string
  • quality int (JPEG-only)
  • compression int (PNG-only)
  • type string
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
  • embed bool
  • force bool
  • rotate int
  • norotation bool
  • noprofile bool
  • stripmeta bool
  • flip bool
  • flop bool
  • extend string
  • background string - Example: ?background=250,20,10
  • colorspace string
  • sigma float
  • minampl float
  • field string - Only POST and multipart/form payloads
  • interlace bool

GET | POST /watermarkimage

Accepts: image/*, multipart/form-data. Content-Type: image/*

Allowed params
  • image string required - URL to watermark image, example: ?image=https://logo-server.com/logo.jpg
  • top int - Top position of the watermark image
  • left int - Left position of the watermark image
  • opacity float - Opacity value of the watermark image
  • quality int (JPEG-only)
  • compression int (PNG-only)
  • type string
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
  • embed bool
  • force bool
  • rotate int
  • norotation bool
  • noprofile bool
  • stripmeta bool
  • flip bool
  • flop bool
  • extend string
  • background string - Example: ?background=250,20,10
  • colorspace string
  • sigma float
  • minampl float
  • field string - Only POST and multipart/form payloads
  • interlace bool

GET | POST /blur

Accepts: image/*, multipart/form-data. Content-Type: image/*

Allowed params
  • sigma float required
  • minampl float
  • width int
  • height int
  • quality int (JPEG-only)
  • compression int (PNG-only)
  • type string
  • file string - Only GET method and if the -mount flag is present
  • url string - Only GET method and if the -enable-url-source flag is present
  • embed bool
  • force bool
  • norotation bool
  • noprofile bool
  • stripmeta bool
  • flip bool
  • flop bool
  • extend string
  • background string - Example: ?background=250,20,10
  • colorspace string
  • field string - Only POST and multipart/form payloads
  • interlace bool
  • aspectratio string

Logging

Imaginary uses an apache compatible log format.

Fluentd log ingestion

You can ingest Imaginary logs with fluentd using the following fluentd config :

# use your own tag name (*.imaginary for this example)
<filter *.imaginary>
    @type parser
    key_name log
    reserve_data true

    <parse>
        @type multi_format
        # access logs parser
        <pattern>
            format regexp
            expression /^[^ ]* [^ ]* [^ ]* \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*) (?<response_time>[^ ]*)$/
            types code:integer,size:integer,response_time:float
            time_key time
            time_format %d/%b/%Y %H:%M:%S
        </pattern>
        # warnings / error logs parser
        <pattern>
            format none
            message_key message
        </pattern>
    </parse>
</filter>

<match *.imaginary>
    @type rewrite_tag_filter

    # Logs with code field are access logs, and logs without are error logs
    <rule>
        key code
        pattern ^.+$
        tag ${tag}.access
    </rule>
    <rule>
        key code
        pattern ^.+$
        invert true
        tag ${tag}.error
    </rule>
</match>

In the end, access records are tagged with *.imaginary.access, and warning / error records are tagged with *.imaginary.error.

Support

Backers

Support us with a monthly donation and help us continue our activities. [Become a backer]

Support this project

OpenCollective

Sponsors

Become a sponsor and get your logo on our README on Github with a link to your site. [Become a sponsor]

Authors

License

MIT - Tomas Aparicio

views

Issues
  • Add URL signature feature

    Add URL signature feature

    URL signature pull request as discussed in this issue #183.

    The HMAC-SHA256 hash is created by taking the URL path (including the leading /), the request parameters (alphabetically-sorted, excluding the sign one and concatenated with & into a string) and the signature salt. The hash is then base64url-encoded.

    Example: curl -O "http://localhost:8088/crop?width=500&height=400&url=https%3A%2F%2Fraw.githubusercontent.com%2Fh2non%2Fimaginary%2Fmaster%2Ftestdata%2Flarge.jpg&sign=4d89IjMIL_-lD2GM9MYehsWqcAbv8-j275l-M9xnQQw"

    The source URL should be URL encoded !

    opened by bleleve 22
  • Docker image: Watermark operation - Error while processing the image: VipsOperation: class

    Docker image: Watermark operation - Error while processing the image: VipsOperation: class "text" not found

    When running the docker image on OS X (Yosemite), and using the watermark operation, I get this error: { message: "Error while processing the image: VipsOperation: class "text" not found", code: 1 }

    help wanted 
    opened by sonu27 18
  • Heroku deployment issue

    Heroku deployment issue

    Trying to deploy on Heroku from the Heroku button in the readme file

    -----> Go app detected
    -----> Installing libvips
           Downloading libvips and unpacking
           libvips installed
     !     A .godir is required. For instructions:
     !     http://mmcgrana.github.io/2012/09/getting-started-with-go-on-heroku
     !     Push rejected, failed to compile Go app.
     !     Push failed
    
    bug 
    opened by olimart 14
  • Resizing width is set based on rotated image dimensions

    Resizing width is set based on rotated image dimensions

    I have this raw image: https://printio-widget-live.s3.amazonaws.com/1B08580D-ABB9-4848-BB96-5D2DCFCD5BFC.jpeg, which is 4000x6000.

    I pass it to our resizer with a width of 1000 set: http://pio-image-resizer.elasticbeanstalk.com/resize?width=1000&url=https://printio-widget-live.s3.amazonaws.com/1B08580D-ABB9-4848-BB96-5D2DCFCD5BFC.jpeg

    It returns an image that is 667x666, instead of one that is 1000x1500.

    Adding norotation=true, I see that it's calculating the width based on the unrotated image, resizing it, and then rotating it. Which is resulting in a cropped, square image.

    Is this a bug? Are there other options I can use to get around this? Thanks.

    bug enhancement 
    opened by kylechadha 14
  • Support custom fill color for nocrop=true on JPEG resize

    Support custom fill color for nocrop=true on JPEG resize

    Hi there,

    Is there any way I can specify a custom color for fill color when nocrop is set to true on jpeg resize? Currently it defaults to black, I would like to change to white (or configurable). I can create a PR to support that, but could you please guide me where to look at? (I'm a java guy, but will try my hand at Go).

    Thanks!

    question 
    opened by tipsytopsy 13
  • blurred image when webp image gets shrinked

    blurred image when webp image gets shrinked

    suspect a bug in shrinkonload function with webp: https://github.com/h2non/bimg/issues/220

    original file original

    after /fit?file=original.webp&height=250&width=250&type=jpeg fit

    also same problem when using type=webp

    I converted here my images to jpg because webp not supported in github, but webp files are available zipped: webp.zip

    bimg issue 
    opened by yuecelm 12
  • 0.1.28 has cpu and memory usage issues

    0.1.28 has cpu and memory usage issues

    Another rather hazy report from me:

    After upgrading imaginary to 0.1.28, our kubernetes cluster works nicely for about 2h.

    After that, the CPU and memory usage of imaginary goes through the roof. There are no messages logged. In the attached screenshot you can see the load times and how they recover after restarting all pods running imaginary.

    The average response time isn't affected to badly but it appears there are stuck/bogged threads that completely kill the percentiles....

    I reverted back to 0.1.27 and the problems are all good.

    So it appears that the new libvips library is leaking resources (just an inspired guess, i have no idea)

    bildschirmfoto 2016-11-03 um 18 07 24

    bug enhancement 
    opened by wirtsi 10
  • Added -http-cache-ttl flag

    Added -http-cache-ttl flag

    This PR adds the flag -http-cache-ttl (in seconds). It will then add the following headers for all GET requests (thus it requires a -mount to be specified also)

    • Cache-Control: public, s-max-age: 123456, max-age: 123456, no-transform
    • Expires: time.Now().Add(..duration)

    Example command: ./imaginary -mount fixtures/ -http-cache-ttl=31556926

    Example headers for a request:

    HTTP/1.1 200 OK
    Cache-Control: public, s-maxage: 31556926, max-age: 31556926, no-transform
    Content-Type: image/jpeg
    Expires: Mon, 31 Oct 2016 01:55:28 UTC
    Server: imaginary 0.1.16 (bimg 0.1.21)
    Date: Sat, 31 Oct 2015 20:06:42 GMT
    Transfer-Encoding: chunked
    

    The flag -http-cache-ttl supports a value of 0-31556926. The value 0 sends caching headers that inform the clients that no caching should be performed. The maximum supported value is 31556926, as this is the maximum recommended value (according to RFC2616).

    feature request 
    opened by Dynom 10
  • Auto rotation without any other modification

    Auto rotation without any other modification

    I would be great if there is an option/endpoint to fix the orientation of an image based on the EXIF data without modifying the image in any other way. The rotate endpoint works only if a rotate parameter is given and a 0-value does not work.

    Not sure, if I am missing something and this works already, but I didn't find it. I did not explore workarounds such as doing a resize that keeps the current size of the image (with auto-rotation), but this does not feel right anyway.

    question feature request 
    opened by digilist 9
  • Black line added when use fit method

    Black line added when use fit method

    Seems like i found a bug when jpeg dimensions is changed with fit method sometimes 1px black line appears (can be in the right or bottom sides).

    Original: ighus8sikg5390whtrrp6hwek6dz3zzlzc9zhf7b-1

    Resized jpeg

    bug 
    opened by lastonoga 9
  • Supporting smart crop

    Supporting smart crop

    Status: Ready for merge

    For this PoC I've abused bimg.Gravity*'s gravity constants to determine wether or not we should apply the SmartCrop algorithm. It works, feel free to test it. However I don't like this approach for two reasons:

    • It would introduce a Gravity type in bimg that isn't a valid Gravity type for libvips
    • It indirectly creates a change in bimg that is only needed for Imaginary (Which would be an incorrect responsibility relation)

    I think there are a couple of options to solve the design issue:

    • Generalising parseGravity() so that it'll return an int. This makes it more generic and it's easy to implement. However we'll lose some type coherence. It also means we'll need to introduce another magic value. It's possible and easy to implement, but I'm not too fond of it.
    • Introduce boilerplate on several places, to work around it. I don't like this approach as it clutters the code. It is easy to implement however.
    • Introduce a completely independent parameter (?smartcrop=true). I don't like this approach, since the instructions seem mutually-exclusive (?gravity=north&smartcrop=true makes no sense).
    • Introducing specific types in Imaginary to solve the responsibility problem. This means duplication of the Gravity* constants, but it's better for the (de-)coupling between bimg and Imaginary. Most significantly the relation bimg->Imaginary. It's possible and doesn't change the bimg implementation. I like this approach.
    • Introducing the GravitySmart constant in bimg and let bimg know how to deal with it. Overall this might be the best option, but also requires the most work. I like this approach best.

    Other Changes:

    • libvips is now downloaded directly from Github. This gives us access to the more recent versions.
    • I've changed some if conditions to a map lookup. This is mostly taste, but I (personally) prefer the readability. If we agree on that I would like to change this on a few other places as well. I also prefer to make these changes in a different PR all together.
    feature request 
    opened by Dynom 9
  • stripmeta=true results in wrong colors for non-sRGB JPEGs

    stripmeta=true results in wrong colors for non-sRGB JPEGs

    When I pass a jpeg to imaginary with a non srgb color profile and also pass stripmeta=true the resulting image doesn't have a color profile and also isn't converted to sRGB, so the image colors are wrong. I would expect it to either copy over the color profile information or convert the image to sRGB.

    opened by lazka 0
  • embed error when using pipeline with resize + watermark on small image

    embed error when using pipeline with resize + watermark on small image

    I'm trying to migrate some old image resizing code I have that has a set of fixed sizes that are blindly cut from the originals. Some of the images are really old and probably should never be cut but the system isn't smart.

    My pipeline operations looks like this:

    [{"operation": "resize", "params": {"width": 950}}, {"operation": "watermark", "params": {"text": "www.123.example.com", "noreplicate": true}}]
    
    curl 'http://localhost:8090/pipeline?file=images%2Foriginal%2F64%2F64316f9775cc421f8383033a301177c7&operations=%5B%7B%22operation%22%3A+%22resize%22%2C+%22params%22%3A+%7B%22width%22%3A+950%7D%7D%2C+%7B%22operation%22%3A+%22watermark%22%2C+%22params%22%3A+%7B%22text%22%3A+%22www.123.example.com%22%2C+%22noreplicate%22%3A+true%7D%7D%5D' -o ana.jpg
    

    I get the following error:

    {"message":"Error while processing the image: embed: bad dimensions","code":1}
    

    It seems to be a problem with the size of the image and the size of the watermark but I don't see how I can scale the watermark text down with the image size. It seems that images less than 300/400 px seem to be a problem.

    opened by ianjosephwilson 1
  • How to generate a fixed size thumbnail without cropping or distorting?

    How to generate a fixed size thumbnail without cropping or distorting?

    I would like to create fixed size thumbnails of images. The /thumbnail endpoint seems to resize which distorts the image. The /fit endpoint will "fit" the image within the specified target size, but the image may be smaller. The image operations are not really explained in detail.

    I would like to call /operation?width=200&height=200&url=https://via.placeholder.com/400x200.png?text=400x200 to get a 200x200 image with "fitted" original content that has the empty space filled with transparency (or a defined background color). Is that possible?

    Imaginary-Thumbnails
    opened by bluepuma77 1
  • Docker tag `latest` was last updated 2 years ago

    Docker tag `latest` was last updated 2 years ago

    Is Docker no longer a recommended way to use imaginary? As per the Docker Hub tags, the tag latest was pushed 2 years ago.

    While I can see that the library is being actively maintained, there aren't any M1-compatible arm based images on Docker Hub either. If not via the official Docker image, what's the recommended approach to use this library?

    opened by dhruvkb 12
  • Build image from Dockerfile error after commit 00f696fe3a3211fb7d01450b9f81308e17c56ca3

    Build image from Dockerfile error after commit 00f696fe3a3211fb7d01450b9f81308e17c56ca3

    Hi, after last commit (00f696fe3a3211fb7d01450b9f81308e17c56ca3 - allow speed from get), can not build image from Dockerfile:

     github.com/h2non/imaginary` [github.com/h2non/imaginary.test]
    ./options.go:148: unknown field 'Speed' in struct literal of type bimg.Options
    FAIL    github.com/h2non/imaginary [build failed]
    FAIL
    Error response from daemon: The command '/bin/sh -c go test ./... -test.v -race -test.coverprofile=atomic .' returned a non-zero code: 2
    Failed to deploy '<unknown> Dockerfile: imaginary-master/Dockerfile': Can't retrieve image ID from build stream
    
    opened by quartoq 1
Releases(v1.2.4)
  • v1.2.4(Aug 12, 2020)

  • v1.2.3(Aug 4, 2020)

  • v1.2.2(Jun 11, 2020)

  • v1.2.1(Jun 8, 2020)

  • v1.2.0(Jun 7, 2020)

    v1.2.0 / 2020-06-07

    • New release, minor features, bimg upgrade and several fixes (#311)
    • watermarkImage must be in lowerCamelCase (#255)
    • Pre-release HEIF / HEIC support (#297)
    • [improvement/log-levels] Add support set log levels (#301)
    • chore(license): update year
    • chore(docs): delete not valid contributor
    • Added PlaceholderStatus option (#304)
    • Create FUNDING.yml
    • Delete README.md~
    • Add fly.io (#300)
    Source code(tar.gz)
    Source code(zip)
  • v1.1.1(Jul 7, 2019)

    v1.1.0

    Docker releases

    Note that by introducing a new minor release we now have:

    • h2non/imaginary:latest (following master, useful for any test environment)
    • h2non/imaginary:1 (equal to latest as long as we don't bump a major)
    • h2non/imaginary:1.1 (following master)
    • h2non/imaginary:1.0 (following release/1.0.x)

    Branches

    • master -- latest and "pretty stable", continues work for 1.1.x development
    • release/1.0.x -- Old stable. Unsure how long it'll be maintained

    Changelog

    • add validation to allowed-origins to include path (#265)
    • Width and height are required in thumbnail request (#262)
    • Merge pull request #258 from r-antonio/master
    • Cleaned code to check for existence of headers
    • Modified check for empty or undefined headers
    • Merge pull request #259 from h2non/release/next
    • Code Style changes
    • Removing gometalinter in favor of golangci-lint
    • Bumping libvips versions for building
    • Merge branch 'master' into release/next
    • Changed custom headers naming to forward headers
    • Fixed spacing typo and headers checking
    • Changed forwarded headers order, added tests and some fixes
    • Added custom headers forwarding support
    • Merge pull request #254 from nicolasmure/fix/readme
    • apply @Dynom patch to fix cli help
    • Update README.md
    • fix enable-url-source param description in README
    • Merge branch 'NextWithCIBase' into release/next
    • Reverting and reordering
    • ups
    • Moving back to a single file, worst case we need to maintain two again.
    • fixing a var
    • Updating travis config, adding docker build and preparing for automated image building
    • Megacheck has been removed in favor of staticcheck
    • timing the pull separately, by putting it in a before_install
    • Trying with a dev base image
    • Adding .dockerignore and consistently guarding the variables
    • Merging in changes by jbergstroem with some extra changes
    • Merge pull request #229 from Dynom/uniformBuildRefactoring
    • Improving gometalinter config
    • First travis-ci config attempt
    • Making sure vendor is not stale and that our deps are correctly configured
    • gometalinter config
    • Fixing Gopkg.toml
    • Adding a newish Dockerfile
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Feb 21, 2019)

    Tagging release 1.1.0

    This release changes the way parameters are handled, by tracking the differences between their default value and whether they were passed along with their default value. This can result in slightly different behaviour, especially with the nocrop parameter.

    Docker releases

    Note that by introducing a new minor release we now have:

    • h2non/imaginary:latest (following master, useful for any test environment)
    • h2non/imaginary:1 (equal to latest as long as we don't bump a major)
    • h2non/imaginary:1.1 (following master)
    • h2non/imaginary:1.0 (following release/1.0.x)

    Branches

    • master -- latest and "pretty stable", continues work for 1.1.x development
    • release/1.0.x -- Old stable. Unsure how long it'll be maintained
    • release/next -- new Docker refactoring work is being done here, expected to be merged in 1.1.x

    Changelog

    d83da84 Testing if an ImageOption false value, was in fact requested 246f796 Updating the documentation 52d156d bumping to 1.1.0

    Source code(tar.gz)
    Source code(zip)
  • v1.0.18(Jan 28, 2019)

  • v1.0.17(Jan 20, 2019)

    Tagging release 1.0.17

    This release contains mostly non-functional improvements, however:

    • The parameter handling is more liberal in parsing certain arguments and is also more clear in it's error messages about what went wrong. See https://github.com/h2non/imaginary/pull/239 for more details.
    • The /health endpoint returns some extra information

    Docker image changes

    The Docker image for this release is built using a new approach for Imaginary and bimg. Of you experience any problems please let us know.

    Changelog

    a9dbf56 refactor(README): remove header image a1bb2fd docs(watermarkimage): Add docs for the /watermarkimage endpoint (#226) d20af55 Including a test case with multiple subdomains 15c4252 Exposing several extra details fbff718 Style fixes f783899 Removing unused function c38cf80 Unavailable is not actually used, replaced it with _ to better convey intent. b24da45 Removing literals in favor of http constants 83750ba Comment fix b1a8027 Correcting the use of abbreviations bab8a72 Removed unused variable and explicitly ignoring errors a299f70 Correcting comments, casing and constant use d71d48b More literal to constant replacements c20f833 Changing the if's to a single map lookup. 45e311f ErrorReply's return value was never used. b55d8a2 explicitly ignoring errors 4220bfc Correct casing for multiple words 0fbc67f Simplifying some if statements, removing unnecessary parenthesis and added an explicit error ignore 45eb61c minor styling a6234c1 Refactoring, making things simpler 54a099c Allow Go 1.9 to fail c1122d2 Bumping Go's version requirement e113d6d cleanup c75d2ba Bumping version to 1.0.17

    Source code(tar.gz)
    Source code(zip)
  • v1.0.16(Dec 11, 2018)

  • v1.0.15(Dec 11, 2018)

    URL signature and wildcard domain support

    This release updates libvips, Go and bimg to the latest versions and it contains several bugfixes. The two most notable features is wildcard domain support for origin URL sources.

    Origin URL sources

    Imaginary allows to process externally hosted images when enabled with the enable-url-source flag. It supported white-listing origins, using the -allowed-origins flag, that were allowed to be passed along. With this release it allows a more liberal configuration, by supporting wildcard domains (E.g.: https://*.example.org)

    URL signature

    With this release Imaginary supports signing the request, hardening Imaginary against request tampering. Enabled by passing the flags -enable-url-signature and -url-signature-key

    Changelog

    6887bcc Changing build steps (#189) d11fb05 feat(version): bump to v1.0.15 3a3bd3a fix(docker): remove race detector (#197) 2a37482 Add URL signature feature (#194) d48f428 Drop salt as suggested in #194 (#200) e558c55 Fix typo in documentation (#202) 2a17cdf Update README.md (#207) e2ad658 Bump Go versions and use '.x' to always get latest patch versions (#220) 132ee8e Adding remote url wildcard support (#219) 71ada16 Watermark image api (#221) ad94782 fix: correct fit operation with autorotated images by switching width/height in certain cases (#208) 40f7ee0 Updated dockerfile vips repo (#222) 6d02570 Updating bimg, libvips and Go

    Source code(tar.gz)
    Source code(zip)
  • v1.0.13(Mar 2, 2018)

    Changes

    v1.0.13 / 2018-03-01

    • feat(version): bump to v1.0.13
    • feat(Docker): upgrade libvips to v8.6.2 (#184)
    • feat(vendor): upgrade bimg to v1.0.18
    • fix(debug): implement custom debug function
    • feat: add docker-compose.yml
    • Merge branch 'master' of https://github.com/h2non/imaginary
    • refactor(vendor): remove go-debug package from vendor
    • refactor(docs): remove codesponsor :(
    • fix testdata image links (#173)
    • Log hours in 24 hour clock (#165)
    • refactor(docs): update CLI usage and minimum requirements
    Source code(tar.gz)
    Source code(zip)
  • v1.0.10(Oct 30, 2017)

  • v1.0.9(Oct 29, 2017)

    Changes

    v1.0.9 / 2017-10-29

    • fix(#157): disable gzip compression support
    • refactor(Dockerfile): use local source copy
    • refactor(requirements): add Go 1.6+ as minimum requirement
    • feat(vendor): support dependencies vendoring
    • refactor(Gopkg): define version
    • feat(vendor): add vendor dependencies
    • feat(travis): add Go 1.9 support
    • refactor(docs): specify POST payloads in description
    • feat(docs): add imagelayer badge
    • feat(docs): add imagelayer badge
    • feat(docs): add imagelayer badge
    • feat(docs): add imagelayer badge
    Source code(tar.gz)
    Source code(zip)
  • v1.0.8(Oct 6, 2017)

    Changes

    v1.0.8 / 2017-10-06

    • feat(docker): upgrade Go to v1.9.1
    • feat(docker): upgrade bimg to v1.0.15
    • feat(api): add smartcrop endpoint
    • feat(#101): add pipeline endpoint implementation + smart crop
    • fix(api): properly parse and use embed
    • feat(docs): add note about pipeline max operations
    • fix(tests): refactor Options -> Params
    • refactor(docs): update author notes
    • refactor(docs): update internal docs links
    • refactor(docs): move sponsor banner
    • feat(docs): add sponsor ad
    • refactor(license): update copyright
    Source code(tar.gz)
    Source code(zip)
  • v1.0.7(Sep 11, 2017)

  • v1.0.5(Sep 11, 2017)

    Changes

    v1.0.5 / 2017-09-10

    • feat(params): add stripmeta params
    • feat(bimg): use bimg v1.0.12
    • feat(Docker): upgrade Go version to 1.9 in Docker image
    Source code(tar.gz)
    Source code(zip)
  • v1.0.2(Jul 28, 2017)

    Changes

    v1.0.2 / 2017-07-28

    • fix(#146): handle proper response code range for max allowed size
    • Typos and minor language in help text (#144)
    • Update README.md (#143)
    • feat(History): add missing Docker changes
    • fix(server_test): assert content type header is present
    • fix(Docker): use proper SHA256 hash
    • feat(Docker): upgrade Go to v1.8.3 and libvips to v8.5.6
    • feat(changelog): update v1.0.1 changes
    • feat(version): bump to v1.0.1
    • feat(#140): expose Content-Length header
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(May 31, 2017)

    Changes

    • feat(version): bump to v1.0.1
    • feat(#140): expose Content-Length header
    • feat(bimg): upgrade to bimg v1.0.10
    • feat(Docker): use Go v1.8.3.
    • feat(Docker): use libvips v8.5.6.
    Source code(tar.gz)
    Source code(zip)
  • v0.1.31(May 18, 2017)

    v0.1.31 / 2017-05-18

    • feat(version): bump to 0.1.31
    • feat(Dockerfile): use libvips v8.5.5, Go v1.8.1 and bimg v1.0.8
    • Correcting the documentation, caching headers are always sent, regardless of being fetched from mount or by URL. (#133)
    • fix(docs): move toc top level sections
    • feat(docs): add new maintainer notice (thanks to @kirillDanshin)
    • feat(travis): use Go 1.8
    • refactor(docs): update support badges
    • feat(docs): add maintainers section
    • fix(.godir): add project name
    • fix(#124): fast workaround to unblock Heroku deployment until the buildpack can be updated
    • Deploy on Cloud Foundry PaaS (#122)
    • Add backers & sponsors from open collective (#119)
      1. remove the .godir as Heroku and Cloud Foundry remove the support. (#117)
    Source code(tar.gz)
    Source code(zip)
  • v0.1.30(Jan 27, 2017)

  • v0.1.29(Dec 18, 2016)

    • feat(max-allowed-size): add new option max-allowed-size in bytes
    • fix(max-allowed-size): HEAD response handling
    • fix(usage): correct help message of 'allowed-origins'
    Source code(tar.gz)
    Source code(zip)
  • v0.1.28(Oct 2, 2016)

    • feat(#95): use [email protected].
    • fix(#75): use [email protected], which provides extract area fix.
    • feat(api): supports extend and embed query params. See HTTP API params docs for more details.
    • feat(#94): add placeholder image support in case of error.
    • refactor(heroku): remove defaults flags in Procfile (user most specify them via Heroku app init settings).
    Source code(tar.gz)
    Source code(zip)
  • v0.1.26(Sep 7, 2016)

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 194 Aug 3, 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
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 731 Aug 8, 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 7, 2022
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 Jul 29, 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 59 Dec 24, 2021
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 460 Jul 19, 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
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
⚡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
magicimage is a simple image validation & save with rich feature package for net/http

Installation go get github.com/IndominusByte/magicimage Usage examples A few usage examples can be found below. See the documentation for the full lis

Nyoman Pradipta Dewantara 2 Feb 5, 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
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