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.
imaginarycan 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 libvips@8.3+ is compiled with proper library bindings.
imaginary is able to output images as JPEG, PNG and WEBP formats, including transparent conversion across them.
imaginary optionally supports image placeholder fallback mechanism in case of image processing error or server error of any nature, hence an image will be always returned by imaginary even in case of error, trying to match the requested image size and format type transparently. The error details will be provided in the response HTTP header Error field serialized as JSON.
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.
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.
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 environment variables to imaginary:
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:
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:
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:
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:
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.
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.
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:
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.
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.
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.
widthint - Width of image area to extract/resize
heightint - Height of image area to extract/resize
topint - Top edge of area to extract. Example: 100
leftint - Left edge of area to extract. Example: 100
areawidthint - Height area to extract. Example: 300
areaheightint - Width area to extract. Example: 300
qualityint - JPEG image quality between 1-100. Defaults to 80
rotateint - Image rotation angle. Must be multiple of 90. Example: 180
factorint - Zoom factor level. Example: 2
marginint - Text area margin for watermark. Example: 50
dpiint - DPI value for watermark. Example: 150
textwidthint - Text area width for watermark. Example: 200
opacityfloat - Opacity level for watermark text or watermark image. Default: 0.2
flipbool - Transform the resultant image with flip operation. Default: false
flopbool - Transform the resultant image with flop operation. Default: false
forcebool - Force image transformation size. Default: false
nocropbool - Disable crop transformation. Defaults depend on the operation
noreplicatebool - Disable text replication in watermark. Defaults to false
norotationbool - Disable auto rotation based on EXIF orientation. Defaults to false
noprofilebool - Disable adding ICC profile metadata. Defaults to false
stripmetabool - Remove original image metadata, such as EXIF metadata. Defaults to false
textstring - Watermark text content. Example: copyright (c) 2189
fontstring - Watermark text font type and format. Example: sans bold 12
colorstring - Watermark text RGB decimal base color. Example: 255,200,150
imagestring - Watermark image URL pointing to the remote HTTP server.
typestring - 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.
gravitystring - Define the crop operation gravity. Supported values are: north, south, centre, west, east and smart. Defaults to centre.
filestring - Use image from server local file path. In order to use this you must pass the -mount=<dir> flag.
urlstring - Fetch the image from a remote HTTP server. In order to use this you must pass the -enable-url-source flag.
colorspacestring - Use a custom color space for the output image. Allowed values are: srgb or bw (black&white)
fieldstring - Custom image form field name if using multipart/form. Defaults to: file
extendstring - 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.
backgroundstring - Background RGB decimal base color to use when flattening transparent PNGs. Example: 255,200,150
sigmafloat - Size of the gaussian mask to use when blurring an image. Example: 15.0
minamplfloat - Minimum amplitude of the gaussian filter to use when blurring an image. Default: Example: 0.5
operationsjson - Pipeline of image operation transformations defined as URL safe encoded JSON array. See pipeline endpoints for more details.
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 intrequired
height intrequired
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
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 jsonrequired - 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.
}
]
imaginary

Fast HTTP microservice written in Go for high-level image processing backed by bimg and libvips.
imaginary
can be used as private or public HTTP service for massive image processing with first-class support for Docker & Fly.io. It’s almost dependency-free and only usesnet/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 iflibvips@8.3+
is compiled with proper library bindings.imaginary
is able to output images as JPEG, PNG and WEBP formats, including transparent conversion across them.imaginary
optionally supports image placeholder fallback mechanism in case of image processing error or server error of any nature, hence an image will be always returned by imaginary even in case of error, trying to match the requested image size and format type transparently. The error details will be provided in the response HTTP headerError
field serialized as JSON.imaginary
uses internallylibvips
, 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 nativeimage
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
Prerequisites
Installation
Also, be sure you have the latest version of
bimg
:libvips
Run the following script as
sudo
(supports OSX, Debian/Ubuntu, Redhat, Fedora, Amazon Linux):The install script requires
curl
andpkg-config
Docker
See Dockerfile for image details.
Fetch the image (comes with latest stable Go and
libvips
versions)Start the container with optional flags (default listening on port 9000)
Start the container enabling remote URL source image processing via GET requests and
url
query param.Start the container enabling local directory image process via GET requests and
file
query param.Start the container in debug mode:
Enter to the interactive shell in a running container
Stop the container
For more usage examples, see the command line usage.
All Docker images tags are available here.
Docker Compose
You can add
imaginary
to yourdocker-compose.yml
file: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:
Push the application
Define the library path
Start the application
Google Cloud Run
Click to deploy on Google Cloud Run:
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:
Memory issues
In case you are experiencing any persistent unreleased memory issues in your deployment, you can try passing this environment variables to
imaginary
: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:
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:
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
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 msThe 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
Start the server in a custom port:
Also, you can pass the port as environment variable:
Enable HTTP server throttle strategy (max 10 requests/second):
Enable remote URL image fetching (then you can do GET request passing the
url=http://server.com/image.jpg
query param):Mount local directory (then you can do GET request passing the
file=image.jpg
query param):Enable authorization header forwarding to image origin server.
X-Forward-Authorization
orAuthorization
(by priority) header value will be forwarded asAuthorization
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: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
orAuthorization
headers won’t be forwarded, and therefore ignored, if present. Note: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: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
width
xheight
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 theError
response HTTP header, for further inspection and convenience for API clients.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
1200
x1200
. Supported custom placeholder image types are:JPEG
,PNG
andWEBP
.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.
It is recommended to pass key as environment variables:
Increase libvips threads concurrency (experimental):
Enable debug mode:
Or filter debug output by package:
Disable info logs:
Examples
Reading a local image (you must pass the
-mount=<directory>
flag):Fetching the image from a remote server (you must pass the
-enable-url-source
flag):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: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--allowed-origins s3.amazonaws.com/some-bucket/
s3.amazonaws.com/some-bucket/images/image.png
--allowed-origins s3.amazonaws.com/some-bucket/
s3.amazonaws.com/images/image.png
--allowed-origins s3.amazonaws.com/some-*
s3.amazonaws.com/some-bucket/images/image.png
--allowed-origins *.amazonaws.com/some-bucket/
anysubdomain.amazonaws.com/some-bucket/images/image.png
--allowed-origins *.amazonaws.com
anysubdomain.amazonaws.comimages/image.png
--allowed-origins *.amazonaws.com
www.notaws.comimages/image.png
--allowed-origins *.amazonaws.com, foo.amazonaws.com/some-bucket/
bar.amazonaws.com/some-other-bucket/image.png
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:
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:
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:
See all the predefined supported errors here.
Placeholder
If
-enable-placeholder
or-placeholder <image path>
flags are passed toimaginary
, a placeholder image will be used in case of error or invalid request input.If
-enable-placeholder
is passed, the defaultimaginary
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 startingimaginary
.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 beapplication/json
with the proper message info. Note that this scenario won’t be common.Form data
If you’re pushing images to
imaginary
asmultipart/form-data
(you can do it as well asimage/*
), you must define at least one input field calledfile
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.
int
- Width of image area to extract/resizeint
- Height of image area to extract/resizeint
- Top edge of area to extract. Example:100
int
- Left edge of area to extract. Example:100
int
- Height area to extract. Example:300
int
- Width area to extract. Example:300
int
- JPEG image quality between 1-100. Defaults to80
int
- PNG compression level. Default:6
int
- Image rotation angle. Must be multiple of90
. Example:180
int
- Zoom factor level. Example:2
int
- Text area margin for watermark. Example:50
int
- DPI value for watermark. Example:150
int
- Text area width for watermark. Example:200
float
- Opacity level for watermark text or watermark image. Default:0.2
bool
- Transform the resultant image with flip operation. Default:false
bool
- Transform the resultant image with flop operation. Default:false
bool
- Force image transformation size. Default:false
bool
- Disable crop transformation. Defaults depend on the operationbool
- Disable text replication in watermark. Defaults tofalse
bool
- Disable auto rotation based on EXIF orientation. Defaults tofalse
bool
- Disable adding ICC profile metadata. Defaults tofalse
bool
- Remove original image metadata, such as EXIF metadata. Defaults tofalse
string
- Watermark text content. Example:copyright (c) 2189
string
- Watermark text font type and format. Example:sans bold 12
string
- Watermark text RGB decimal base color. Example:255,200,150
string
- Watermark image URL pointing to the remote HTTP server.string
- Specify the image format to output. Possible values are:jpeg
,png
,webp
andauto
.auto
will use the preferred format requested by the client in the HTTP Accept header. A client can provide multiple comma-separated choices inAccept
with the best being the one picked.string
- Define the crop operation gravity. Supported values are:north
,south
,centre
,west
,east
andsmart
. Defaults tocentre
.string
- Use image from server local file path. In order to use this you must pass the-mount=<dir>
flag.string
- Fetch the image from a remote HTTP server. In order to use this you must pass the-enable-url-source
flag.string
- Use a custom color space for the output image. Allowed values are:srgb
orbw
(black&white)string
- Custom image form field name if usingmultipart/form
. Defaults to:file
string
- Extend represents the image extend mode used when the edges of an image are extended. Defaults tomirror
. Allowed values are:black
,copy
,mirror
,white
,lastpixel
andbackground
. Ifbackground
value is specified, you can define the desired extend RGB color viabackground
param, such as?extend=background&background=250,20,10
. For more info, see libvips docs.string
- Background RGB decimal base color to use when flattening transparent PNGs. Example:255,200,150
float
- Size of the gaussian mask to use when blurring an image. Example:15.0
float
- Minimum amplitude of the gaussian filter to use when blurring an image. Default: Example:0.5
json
- Pipeline of image operation transformations defined as URL safe encoded JSON array. See pipeline endpoints for more details.string
- URL signature (URL-safe Base64-encoded HMAC digest)bool
- Use progressive / interlaced format of the image output. Defaults tofalse
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
andlibvips
versions.Example response:
GET /health
Content-Type:
application/json
Provides some useful statistics about the server stats with the following structure:
number
- Server process uptime in seconds.number
- Currently allocated memory in megabytes.number
- Total allocated memory over the time in megabytes.number
- Number of running goroutines.number
- Number of used CPU cores.Example response:
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:
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
int
int
int
(JPEG-only)int
(PNG-only)string
string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentbool
int
bool
bool
bool
bool
bool
bool
string
string
- Example:?background=250,20,10
string
float
float
string
string
- Only POST andmultipart/form
payloadsbool
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
int
int
int
(JPEG-only)int
(PNG-only)string
string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentbool
int
bool
bool
bool
bool
bool
bool
string
string
- Example:?background=250,20,10
string
float
float
string
string
- Only POST andmultipart/form
payloadsbool
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
int
required
int
int
(JPEG-only)int
(PNG-only)string
string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentbool
bool
int
bool
- Defaults totrue
bool
bool
bool
bool
bool
string
string
- Example:?background=250,20,10
string
float
float
string
- Only POST andmultipart/form
payloadsbool
string
GET | POST /enlarge
Accepts:
image/*, multipart/form-data
. Content-Type:image/*
Allowed params
int
required
int
required
int
(JPEG-only)int
(PNG-only)string
string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentbool
bool
int
bool
- Defaults tofalse
bool
bool
bool
bool
bool
string
string
- Example:?background=250,20,10
string
float
float
string
- Only POST andmultipart/form
payloadsbool
GET | POST /extract
Accepts:
image/*, multipart/form-data
. Content-Type:image/*
Allowed params
int
required
int
int
required
int
int
int
int
(JPEG-only)int
(PNG-only)string
string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentbool
bool
int
bool
bool
bool
bool
bool
string
string
- Example:?background=250,20,10
string
float
float
string
- Only POST andmultipart/form
payloadsbool
string
GET | POST /zoom
Accepts:
image/*, multipart/form-data
. Content-Type:image/*
Allowed params
number
required
int
int
int
(JPEG-only)int
(PNG-only)string
string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentbool
bool
int
bool
- Defaults totrue
bool
bool
bool
bool
bool
string
string
- Example:?background=250,20,10
string
float
float
string
- Only POST andmultipart/form
payloadsbool
string
GET | POST /thumbnail
Accepts:
image/*, multipart/form-data
. Content-Type:image/*
Allowed params
int
required
int
required
int
(JPEG-only)int
(PNG-only)string
string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentbool
bool
int
bool
bool
bool
bool
bool
string
string
- Example:?background=250,20,10
string
float
float
string
- Only POST andmultipart/form
payloadsbool
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
int
required
int
required
int
(JPEG-only)int
(PNG-only)string
string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentbool
bool
int
bool
bool
bool
bool
bool
string
string
- Example:?background=250,20,10
string
float
float
string
- Only POST andmultipart/form
payloadsbool
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
int
required
int
int
int
(JPEG-only)int
(PNG-only)string
string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentbool
bool
bool
bool
bool
bool
bool
string
string
- Example:?background=250,20,10
string
float
float
string
- Only POST andmultipart/form
payloadsbool
string
GET | POST /flip
Accepts:
image/*, multipart/form-data
. Content-Type:image/*
Allowed params
int
int
int
(JPEG-only)int
(PNG-only)string
string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentbool
bool
bool
bool
bool
bool
bool
string
string
- Example:?background=250,20,10
string
float
float
string
- Only POST andmultipart/form
payloadsbool
string
GET | POST /flop
Accepts:
image/*, multipart/form-data
. Content-Type:image/*
Allowed params
int
int
int
(JPEG-only)int
(PNG-only)string
string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentbool
bool
bool
bool
bool
bool
bool
string
string
- Example:?background=250,20,10
string
float
float
string
- Only POST andmultipart/form
payloadsbool
string
GET | POST /convert
Accepts:
image/*, multipart/form-data
. Content-Type:image/*
Allowed params
string
required
int
(JPEG-only)int
(PNG-only)string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentbool
bool
int
bool
bool
bool
bool
bool
string
string
- Example:?background=250,20,10
string
float
float
string
- Only POST andmultipart/form
payloadsbool
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:
Allowed params
json
required
- URL safe encoded JSON with a list of operations. See below for interface details.string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentOperations JSON specification
Self-documented JSON operation schema:
Supported operations names
/crop
endpoint./smartcrop
endpoint./resize
endpoint./enlarge
endpoint./extract
endpoint./rotate
endpoint./autorotate
endpoint./flip
endpoint./flop
endpoint./thumbnail
endpoint./zoom
endpoint./convert
endpoint./watermark
endpoint./watermarkimage
endpoint./blur
endpoint.Example
GET | POST /watermark
Accepts:
image/*, multipart/form-data
. Content-Type:image/*
Allowed params
string
required
int
int
int
float
bool
string
string
int
(JPEG-only)int
(PNG-only)string
string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentbool
bool
int
bool
bool
bool
bool
bool
string
string
- Example:?background=250,20,10
string
float
float
string
- Only POST andmultipart/form
payloadsbool
GET | POST /watermarkimage
Accepts:
image/*, multipart/form-data
. Content-Type:image/*
Allowed params
string
required
- URL to watermark image, example:?image=https://logo-server.com/logo.jpg
int
- Top position of the watermark imageint
- Left position of the watermark imagefloat
- Opacity value of the watermark imageint
(JPEG-only)int
(PNG-only)string
string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentbool
bool
int
bool
bool
bool
bool
bool
string
string
- Example:?background=250,20,10
string
float
float
string
- Only POST andmultipart/form
payloadsbool
GET | POST /blur
Accepts:
image/*, multipart/form-data
. Content-Type:image/*
Allowed params
float
required
float
int
int
int
(JPEG-only)int
(PNG-only)string
string
- Only GET method and if the-mount
flag is presentstring
- Only GET method and if the-enable-url-source
flag is presentbool
bool
bool
bool
bool
bool
bool
string
string
- Example:?background=250,20,10
string
string
- Only POST andmultipart/form
payloadsbool
string
Logging
Imaginary uses an apache compatible log format.
Fluentd log ingestion
You can ingest Imaginary logs with fluentd using the following fluentd config :
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
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