Top Related Projects
thumbor is an open-source photo thumbnail service by globo.com
Fast, simple, scalable, Docker-ready HTTP microservice for high-level image processing
A caching, resizing image proxy written in Go
An image resizing server written in Go
Dockerized application that resizes and crops images on the fly, delivering optimized images in formats such as AVIF, WebP, MozJPEG, or PNG using ImageMagick, with an efficient caching system.
Fast and secure standalone server for resizing and converting remote images
Quick Overview
Imagor is a fast, Docker-ready image processing server written in Go. It's designed to be a high-performance, on-demand image manipulation and optimization service, capable of handling a wide range of image operations including resizing, cropping, and various filters.
Pros
- High performance and scalability due to its Go implementation
- Extensive image manipulation capabilities (resize, crop, filters, etc.)
- Easy deployment with Docker support
- Compatible with Thumbor's URL structure, making it a drop-in replacement
Cons
- Limited documentation compared to some more established alternatives
- Fewer built-in storage options compared to Thumbor
- May require additional setup for advanced features or custom integrations
- Relatively newer project, which might mean less community support
Code Examples
- Basic image resizing:
import "github.com/cshum/imagor"
loader := imagor.NewHTTPLoader()
processor := imagor.NewProcessor()
result, err := processor.Process(ctx, loader, imagor.Params{
Image: "https://example.com/image.jpg",
Width: 300,
Height: 200,
})
- Applying filters:
result, err := processor.Process(ctx, loader, imagor.Params{
Image: "https://example.com/image.jpg",
Filters: []imagor.Filter{
{Name: "brightness", Args: []interface{}{10}},
{Name: "contrast", Args: []interface{}{15}},
},
})
- Cropping and resizing:
result, err := processor.Process(ctx, loader, imagor.Params{
Image: "https://example.com/image.jpg",
Width: 300,
Height: 200,
CropMode: imagor.CropModeSmartCrop,
Fit: imagor.FitCover,
})
Getting Started
To get started with Imagor, follow these steps:
-
Install Imagor:
go get github.com/cshum/imagor
-
Create a basic server:
package main import ( "github.com/cshum/imagor" "github.com/cshum/imagor/imagorpath" ) func main() { app := imagor.New( imagor.WithLoaders(imagor.NewHTTPLoader()), imagor.WithProcessors(imagor.NewProcessor()), ) server := imagorpath.NewServer(app) server.ListenAndServe(":8000") }
-
Run the server and access images using Thumbor-compatible URLs:
http://localhost:8000/300x200/filters:brightness(10):contrast(15)/https://example.com/image.jpg
Competitor Comparisons
thumbor is an open-source photo thumbnail service by globo.com
Pros of Thumbor
- More mature and widely adopted project with a larger community
- Extensive documentation and broader feature set
- Supports multiple storage backends and caching mechanisms
Cons of Thumbor
- Written in Python, which may have performance limitations compared to Go
- Can be more complex to set up and configure
- Larger resource footprint
Code Comparison
Thumbor (Python):
from thumbor.handlers.imaging import ImagingHandler
class MyHandler(ImagingHandler):
def get(self):
# Custom image processing logic
super(MyHandler, self).get()
Imagor (Go):
package main
import "github.com/cshum/imagor"
func main() {
srv := imagor.New()
srv.Use(imagor.NewProcessor())
srv.ListenAndServe(":8000")
}
Key Differences
- Thumbor offers more built-in features and flexibility, while Imagor focuses on simplicity and performance
- Imagor is written in Go, which can provide better performance and lower resource usage
- Thumbor has a more extensive plugin ecosystem, whereas Imagor has a more streamlined approach
- Imagor's API is designed to be compatible with Thumbor, making migration easier
Both projects aim to provide efficient image processing and serving capabilities, with Thumbor offering more features and Imagor prioritizing performance and simplicity.
Fast, simple, scalable, Docker-ready HTTP microservice for high-level image processing
Pros of Imaginary
- Written in Go, potentially offering better performance and concurrency
- Supports a wider range of image processing operations, including face detection and smart cropping
- Provides a Docker image for easy deployment
Cons of Imaginary
- More complex setup and configuration compared to Imagor
- Larger codebase, which may lead to a steeper learning curve
- Fewer built-in caching options
Code Comparison
Imaginary (main.go):
func main() {
opts := ServerOptions{
Port: 9000,
CORS: false,
EnableURLSource: true,
EnablePlaceholder: true,
EnableURLSignature: true,
}
server := NewServer(opts)
server.Listen()
}
Imagor (main.go):
func main() {
app := imagor.New()
app.Use(imagor.LoaderURL())
app.Use(imagor.ProcessorImage())
app.Use(imagor.ServerImage())
app.Run(":8000")
}
Both projects offer powerful image processing capabilities, but Imaginary provides more advanced features at the cost of increased complexity. Imagor focuses on simplicity and ease of use, making it a good choice for projects with straightforward image processing needs. The code comparison shows that Imaginary requires more configuration options, while Imagor has a more streamlined setup process.
A caching, resizing image proxy written in Go
Pros of imageproxy
- Written in Go, potentially offering better performance and concurrency
- Supports a wider range of image processing operations, including rotation and smart cropping
- More flexible caching options, including support for various backends like Amazon S3 and Google Cloud Storage
Cons of imageproxy
- Less actively maintained, with fewer recent updates compared to imagor
- Lacks some advanced features present in imagor, such as lazy loading and watermarking
- May have a steeper learning curve for configuration and deployment
Code Comparison
imageproxy:
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/favicon.ico" {
http.Error(w, "404 Not Found", http.StatusNotFound)
return
}
// ... (additional code)
}
imagor:
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
start := time.Now()
defer func() {
s.metrics.Latency.Observe(time.Since(start).Seconds())
}()
// ... (additional code)
}
Both projects implement image processing servers, but they differ in their approach and feature sets. imageproxy offers a broader range of image operations and flexible caching, while imagor provides more advanced features and active development. The choice between them depends on specific project requirements and preferences.
An image resizing server written in Go
Pros of picfit
- Written in Go, potentially offering better performance and concurrency
- Supports multiple storage backends (File System, Amazon S3, Google Cloud Storage)
- Includes a built-in HTTP server for serving processed images
Cons of picfit
- Less actively maintained (last commit over 2 years ago)
- Fewer image processing operations compared to imagor
- Limited documentation and examples
Code Comparison
imagor (Python):
from imagor import imagor
app = imagor()
app.run(host='0.0.0.0', port=8000)
picfit (Go):
package main
import "github.com/thoas/picfit"
func main() {
picfit.Run()
}
Both projects aim to provide image processing and serving capabilities, but they differ in implementation language and feature sets. imagor is written in Python and offers a wider range of image processing operations, while picfit is implemented in Go and focuses on performance and multiple storage backend support.
imagor has more recent development activity and better documentation, making it potentially easier to adopt and integrate. However, picfit's Go implementation may provide better performance for high-load scenarios.
The code comparison shows that both projects offer simple ways to start the image processing server, with imagor providing more configuration options directly in the startup code.
Dockerized application that resizes and crops images on the fly, delivering optimized images in formats such as AVIF, WebP, MozJPEG, or PNG using ImageMagick, with an efficient caching system.
Pros of flyimg
- Built with PHP and Symfony, which may be more familiar to some developers
- Supports a wider range of image processing operations out-of-the-box
- Includes a built-in security layer with signing requests
Cons of flyimg
- Less actively maintained compared to imagor
- May have higher resource requirements due to PHP runtime
- Fewer deployment options and less cloud-native focus
Code Comparison
imagor:
func (p *ImageProcessor) Resize(img image.Image, width, height int) image.Image {
return resize.Resize(uint(width), uint(height), img, resize.Lanczos3)
}
flyimg:
public function resize(Image $image, int $width, int $height): Image
{
return $image->resize($width, $height);
}
Both projects offer similar core functionality for image processing, but their implementations differ based on the programming languages used. imagor is written in Go, which may provide better performance and lower resource usage, while flyimg uses PHP, which might be more accessible to web developers familiar with the LAMP stack.
imagor focuses on being a lightweight, cloud-native solution with easy deployment options, while flyimg offers a more comprehensive set of image manipulation features out-of-the-box. The choice between the two may depend on specific project requirements, team expertise, and infrastructure preferences.
Fast and secure standalone server for resizing and converting remote images
Pros of imgproxy
- Written in Go, offering potentially better performance and lower resource usage
- Supports a wider range of image processing operations, including face detection and watermarking
- More actively maintained with frequent updates and releases
Cons of imgproxy
- More complex setup and configuration compared to imagor
- Requires separate installation of libvips and other dependencies
- May have a steeper learning curve for newcomers to image processing
Code Comparison
imagor configuration example:
ALLOWED_SOURCES = ['http://example.com/']
MAX_WIDTH = 1000
MAX_HEIGHT = 1000
imgproxy configuration example:
IMGPROXY_KEY=your_key
IMGPROXY_SALT=your_salt
IMGPROXY_MAX_SRC_RESOLUTION=50
Key Differences
- imagor is Python-based, while imgproxy is Go-based
- imagor follows the Thumbor API, making it easier to migrate from Thumbor
- imgproxy offers more advanced features like automatic format conversion and WebP support
- imagor has a simpler setup process, especially for Python developers
- imgproxy may have better performance for high-volume image processing tasks
Both projects aim to provide efficient image processing and serving capabilities, but they cater to different use cases and developer preferences. The choice between them depends on specific project requirements, existing infrastructure, and team expertise.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
imagor
imagor is a fast, secure image processing server and Go library.
imagor uses one of the most efficient image processing library libvips. It is typically 4-8x faster than using the quickest ImageMagick and GraphicsMagick settings. imagor implements libvips streaming that facilitates parallel processing pipelines, achieving high network throughput.
imagor features a ton of image processing use cases, available as a HTTP server with first-class Docker support. It adopts the thumbor URL syntax representing a high-performance drop-in replacement.
imagor is a Go library built with speed, security and extensibility in mind. Alongside there is imagorvideo bringing video thumbnail capability through ffmpeg C bindings.
Quick Start
docker run -p 8000:8000 shumc/imagor -imagor-unsafe -imagor-auto-webp
Original images:
https://raw.githubusercontent.com/cshum/imagor/master/testdata/gopher.png
https://raw.githubusercontent.com/cshum/imagor/master/testdata/dancing-banana.gif
https://raw.githubusercontent.com/cshum/imagor/master/testdata/gopher-front.png
Try out the following image URLs:
http://localhost:8000/unsafe/fit-in/200x200/filters:fill(white)/https://raw.githubusercontent.com/cshum/imagor/master/testdata/gopher.png
http://localhost:8000/unsafe/200x200/smart/filters:fill(white):format(jpeg):quality(80)/https://raw.githubusercontent.com/cshum/imagor/master/testdata/gopher.png
http://localhost:8000/unsafe/fit-in/-180x180/10x10/filters:hue(290):saturation(100):fill(yellow)/raw.githubusercontent.com/cshum/imagor/master/testdata/gopher.png
http://localhost:8000/unsafe/30x40:100x150/filters:fill(cyan)/raw.githubusercontent.com/cshum/imagor/master/testdata/dancing-banana.gif
http://localhost:8000/unsafe/fit-in/200x150/filters:fill(yellow):watermark(raw.githubusercontent.com/cshum/imagor/master/testdata/gopher-front.png,repeat,bottom,0,40,40)/raw.githubusercontent.com/cshum/imagor/master/testdata/dancing-banana.gif
Image Endpoint
imagor endpoint is a series of URL parts which defines the image operations, followed by the image URI:
/HASH|unsafe/trim/AxB:CxD/fit-in/stretch/-Ex-F/GxH:IxJ/HALIGN/VALIGN/smart/filters:NAME(ARGS):NAME(ARGS):.../IMAGE
HASH
is the URL signature hash, orunsafe
if unsafe mode is usedtrim
removes surrounding space in images using top-left pixel colorAxB:CxD
means manually crop the image at left-top pointAxB
and right-bottom pointCxD
. Coordinates can also be provided as float values between 0 and 1 (percentage of image dimensions)fit-in
means that the generated image should not be auto-cropped and otherwise just fit in an imaginary box specified byExF
stretch
means resize the image toExF
without keeping its aspect ratios-Ex-F
means resize the image to beExF
of width per height size. The minus signs mean flip horizontally and verticallyGxH:IxJ
add left-top paddingGxH
and right-bottom paddingIxJ
HALIGN
is horizontal alignment of crop. Acceptsleft
,right
orcenter
, defaults tocenter
VALIGN
is vertical alignment of crop. Acceptstop
,bottom
ormiddle
, defaults tomiddle
smart
means using smart detection of focal pointsfilters
a pipeline of image filter operations to be applied, see filters sectionIMAGE
is the image path or URI- For image URI that contains
?
character, this will interfere the URL query and should be encoded withencodeURIComponent
or equivalent
- For image URI that contains
Filters
Filters /filters:NAME(ARGS):NAME(ARGS):.../
is a pipeline of image operations that will be sequentially applied to the image. Examples:
/filters:fill(white):format(jpeg)/
/filters:hue(290):saturation(100):fill(yellow):format(jpeg):quality(80)/
/filters:fill(white):watermark(raw.githubusercontent.com/cshum/imagor/master/testdata/gopher-front.png,repeat,bottom,10):format(jpeg)/
imagor supports the following filters:
background_color(color)
sets the background color of a transparent imagecolor
the color name or hexadecimal rgb expression without the â#â character
blur(sigma)
applies gaussian blur to the imagebrightness(amount)
increases or decreases the image brightnessamount
-100 to 100, the amount in % to increase or decrease the image brightness
contrast(amount)
increases or decreases the image contrastamount
-100 to 100, the amount in % to increase or decrease the image contrast
fill(color)
fill the missing area or transparent image with the specified color:color
- color name or hexadecimal rgb expression without the â#â character- If color is "blur" - missing parts are filled with blurred original image
- If color is "auto" - the top left image pixel will be chosen as the filling color
- If color is "none" - the filling would become fully transparent
focal(AxB:CxD)
orfocal(X,Y)
adds a focal region or focal point for custom transformations:- Coordinated by a region of left-top point
AxB
and right-bottom pointCxD
, or a pointX,Y
. - Also accepts float values between 0 and 1 that represents percentage of image dimensions.
- Coordinated by a region of left-top point
format(format)
specifies the output format of the imageformat
accepts jpeg, png, gif, webp, tiff, avif, jp2
grayscale()
changes the image to grayscalehue(angle)
increases or decreases the image hueangle
the angle in degree to increase or decrease the hue rotation
label(text, x, y, size, color[, alpha[, font]])
adds a text label to the image. It can be positioned inside the image with the alignment specified, color and transparency support:text
text label, also support url encoded text.x
horizontal position that the text label will be in:- Positive number indicate position from the left, negative number from the right.
- Number followed by a
p
e.g. 20p means calculating the value from the image width as percentage left
,right
,center
align left, right or centered respectively
y
vertical position that the text label will be in:- Positive number indicate position from the top, negative number from the bottom.
- Number followed by a
p
e.g. 20p means calculating the value from the image height as percentage top
,bottom
,center
vertical align top, bottom or centered respectively
size
- text label font sizecolor
- color name or hexadecimal rgb expression without the â#â characteralpha
- text label transparency, a number between 0 (fully opaque) and 100 (fully transparent).font
- text label font type
max_bytes(amount)
automatically degrades the quality of the image until the image is under the specifiedamount
of bytesmax_frames(n)
limit maximum number of animation framesn
to be loadedorient(angle)
rotates the image before resizing and cropping, according to the angle valueangle
accepts 0, 90, 180, 270
page(num)
specify page number for PDF, or frame number for animated image, starts from 1dpi(num)
specify the dpi to render at for PDF and SVGproportion(percentage)
scales image to the proportion percentage of the image dimensionquality(amount)
changes the overall quality of the image, does nothing for pngamount
0 to 100, the quality level in %
rgb(r,g,b)
amount of color in each of the rgb channels in %. Can range from -100 to 100rotate(angle)
rotates the given image according to the angle valueangle
accepts 0, 90, 180, 270
round_corner(rx [, ry [, color]])
adds rounded corners to the image with the specified color as backgroundrx
,ry
amount of pixel to use as radius. ry = rx if ry is not providedcolor
the color name or hexadecimal rgb expression without the â#â character
saturation(amount)
increases or decreases the image saturationamount
-100 to 100, the amount in % to increase or decrease the image saturation
sharpen(sigma)
sharpens the imagestrip_exif()
removes Exif metadata from the resulting imagestrip_icc()
removes ICC profile information from the resulting imagestrip_metadata()
removes all metadata from the resulting imageupscale()
upscale the image iffit-in
is usedwatermark(image, x, y, alpha [, w_ratio [, h_ratio]])
adds a watermark to the image. It can be positioned inside the image with the alpha channel specified and optionally resized based on the image size by specifying the ratioimage
watermark image URI, using the same image loader configured for imagorx
horizontal position that the watermark will be in:- Positive number indicate position from the left, negative number from the right.
- Number followed by a
p
e.g. 20p means calculating the value from the image width as percentage left
,right
,center
positioned left, right or centered respectivelyrepeat
the watermark will be repeated horizontally
y
vertical position that the watermark will be in:- Positive number indicate position from the top, negative number from the bottom.
- Number followed by a
p
e.g. 20p means calculating the value from the image height as percentage top
,bottom
,center
positioned top, bottom or centered respectivelyrepeat
the watermark will be repeated vertically
alpha
watermark image transparency, a number between 0 (fully opaque) and 100 (fully transparent).w_ratio
percentage of the width of the image the watermark should fit-inh_ratio
percentage of the height of the image the watermark should fit-in
Utility Filters
These filters do not manipulate images but provide useful utilities to the imagor pipeline:
attachment(filename)
returns attachment in theContent-Disposition
header, and the browser will open a "Save as" dialog withfilename
. Whenfilename
not specified, imagor will get the filename from the image sourceexpire(timestamp)
adds expiration time to the content.timestamp
is the unix milliseconds timestamp, e.g. if content is valid for 30s then timestamp would beDate.now() + 30*1000
in JavaScript.preview()
skips the result storage even if result storage is enabled. Useful for conditional cachingraw()
response with a raw unprocessed and unchecked source image. Image still loads from loader and storage but skips the result storage
Loader, Storage and Result Storage
imagor Loader
, Storage
and Result Storage
are the building blocks for loading and saving images from various sources:
Loader
loads image. EnableLoader
where you wish to load images from, but without modifying it e.g. static directory.Storage
loads and saves image. This allows subsequent requests for the same image loads directly from the storage, instead of HTTP source.Result Storage
loads and saves the processed image. This allows subsequent request of the same parameters loads from the result storage, saving processing resources.
imagor provides built-in adaptors that support HTTP(s), Proxy, File System, AWS S3 and Google Cloud Storage. By default, HTTP Loader
is used as fallback. You can choose to enable additional adaptors that fit your use cases.
File System
Docker Compose example with file system, using mounted volume:
version: "3"
services:
imagor:
image: shumc/imagor:latest
volumes:
- ./:/mnt/data
environment:
PORT: 8000
IMAGOR_UNSAFE: 1 # unsafe URL for testing
FILE_LOADER_BASE_DIR: /mnt/data # enable file loader by specifying base dir
FILE_STORAGE_BASE_DIR: /mnt/data # enable file storage by specifying base dir
FILE_STORAGE_MKDIR_PERMISSION: 0755 # optional
FILE_STORAGE_WRITE_PERMISSION: 0666 # optional
FILE_RESULT_STORAGE_BASE_DIR: /mnt/data/result # enable file result storage by specifying base dir
FILE_RESULT_STORAGE_MKDIR_PERMISSION: 0755 # optional
FILE_RESULT_STORAGE_WRITE_PERMISSION: 0666 # optional
ports:
- "8000:8000"
AWS S3
Docker Compose example with AWS S3. Also works with S3 compatible such as MinIO, DigitalOcean Space.
version: "3"
services:
imagor:
image: shumc/imagor:latest
environment:
PORT: 8000
IMAGOR_SECRET: mysecret # secret key for URL signature
AWS_ACCESS_KEY_ID: ...
AWS_SECRET_ACCESS_KEY: ...
AWS_REGION: ...
S3_LOADER_BUCKET: mybucket # enable S3 loader by specifying bucket
S3_LOADER_BASE_DIR: images # optional
S3_STORAGE_BUCKET: mybucket # enable S3 storage by specifying bucket
S3_STORAGE_BASE_DIR: images # optional
S3_STORAGE_ACL: public-read # optional - see https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#canned-acl
S3_RESULT_STORAGE_BUCKET: mybucket # enable S3 result storage by specifying bucket
S3_RESULT_STORAGE_BASE_DIR: images/result # optional
S3_RESULT_STORAGE_ACL: public-read # optional
ports:
- "8000:8000"
Custom S3 Endpoint
Configure custom S3 endpoint for S3 compatible such as MinIO, DigitalOcean Space:
S3_ENDPOINT: http://minio:9000
S3_FORCE_PATH_STYLE: 1
By default, S3 prepends bucket name as subdomain to the request URL:
http://mybucket.minio:9000/image.jpg
this may not be desirable for a self-hosted endpoint. You can also switch to path-style requests using S3_FORCE_PATH_STYLE=1
such that the host remains unchanged:
http://minio:9000/mybucket/image.jpg
Different AWS Credentials for S3 Loader, Storage and Result Storage
Set the following environment variables to override the global AWS Credentials for S3 Loader, Storage and Result Storage:
AWS_LOADER_REGION
AWS_LOADER_ACCESS_KEY_ID
AWS_LOADER_SECRET_ACCESS_KEY
S3_LOADER_ENDPOINT
AWS_STORAGE_REGION
AWS_STORAGE_ACCESS_KEY_ID
AWS_STORAGE_SECRET_ACCESS_KEY
S3_STORAGE_ENDPOINT
AWS_RESULT_STORAGE_REGION
AWS_RESULT_STORAGE_ACCESS_KEY_ID
AWS_RESULT_STORAGE_SECRET_ACCESS_KEY
S3_RESULT_STORAGE_ENDPOINT
Google Cloud Storage
Docker Compose example with Google Cloud Storage:
version: "3"
services:
imagor:
image: shumc/imagor:latest
volumes:
- ./googlesecret:/etc/secrets/google
environment:
PORT: 8000
IMAGOR_SECRET: mysecret # secret key for URL signature
GOOGLE_APPLICATION_CREDENTIALS: /etc/secrets/google/appcredentials.json # google cloud secrets file
GCLOUD_LOADER_BUCKET: mybucket # enable loader by specifying bucket
GCLOUD_LOADER_BASE_DIR: images # optional
GCLOUD_STORAGE_BUCKET: mybucket # enable storage by specifying bucket
GCLOUD_STORAGE_BASE_DIR: images # optional
GCLOUD_STORAGE_ACL: publicRead # optional - see https://cloud.google.com/storage/docs/json_api/v1/objects/insert
GCLOUD_RESULT_STORAGE_BUCKET: mybucket # enable result storage by specifying bucket
GCLOUD_RESULT_STORAGE_BASE_DIR: images/result # optional
GCLOUD_RESULT_STORAGE_ACL: publicRead # optional
ports:
- "8000:8000"
Storage and Result Storage Path Style
Storage
and Result Storage
path style enables additional hashing rules to the storage path when loading and saving images:
IMAGOR_STORAGE_PATH_STYLE=digest
foobar.jpg
becomese6/86/1a810ff186b4f747ef85f7c53946f0e6d8cb
IMAGOR_RESULT_STORAGE_PATH_STYLE=digest
fit-in/16x17/foobar.jpg
becomes61/4c/9ba1725e8cdd8263a4ad437c56b35f33deba
IMAGOR_RESULT_STORAGE_PATH_STYLE=suffix
166x169/top/foobar.jpg
becomesfoobar.45d8ebb31bd4ed80c26e.jpg
17x19/smart/example.com/foobar
becomesexample.com/foobar.ddd349e092cda6d9c729
IMAGOR_RESULT_STORAGE_PATH_STYLE=size
166x169/top/foobar.jpg
becomesfoobar.45d8ebb31bd4ed80c26e_166x169.jpg
17x19/smart/example.com/foobar
becomesexample.com/foobar.ddd349e092cda6d9c729_17x19
Security
URL Signature
In production environment, it is highly recommended turning off IMAGOR_UNSAFE
and setting up URL signature using IMAGOR_SECRET
, to prevent DDoS attacks that abuse multiple image operations.
The URL signature hash is based on SHA digest, created by taking the URL path (excluding /unsafe/
) with secret. The hash is then Base64 URL encoded.
An example in Node.js:
const crypto = require('crypto');
function sign(path, secret) {
const hash = crypto.createHmac('sha1', secret)
.update(path)
.digest('base64')
.replace(/\+/g, '-').replace(/\//g, '_')
return hash + '/' + path
}
console.log(sign('500x500/top/raw.githubusercontent.com/cshum/imagor/master/testdata/gopher.png', 'mysecret'))
// cST4Ko5_FqwT3BDn-Wf4gO3RFSk=/500x500/top/raw.githubusercontent.com/cshum/imagor/master/testdata/gopher.png
Custom HMAC Signer
imagor uses SHA1 HMAC signer by default, the same one used by thumbor. However, SHA1 is not considered cryptographically secure. If that is a concern it is possible to configure different signing method and truncate length. imagor supports sha1
, sha256
, sha512
signer type:
IMAGOR_SIGNER_TYPE=sha256
IMAGOR_SIGNER_TRUNCATE=40
The Node.js example then becomes:
const crypto = require('crypto');
function sign(path, secret) {
const hash = crypto.createHmac('sha256', secret)
.update(path)
.digest('base64')
.slice(0, 40)
.replace(/\+/g, '-').replace(/\//g, '_')
return hash + '/' + path
}
console.log(sign('500x500/top/raw.githubusercontent.com/cshum/imagor/master/testdata/gopher.png', 'mysecret'))
// IGEn3TxngivD0jy4uuiZim2bdUCvhcnVi1Nm0xGy/500x500/top/raw.githubusercontent.com/cshum/imagor/master/testdata/gopher.png
Image Bombs Prevention
imagor checks the image type and its resolution before the actual processing happens. The processing will be rejected if the image dimensions are too big, which protects from so-called "image bombs". You can set the max allowed image resolution and dimensions using VIPS_MAX_RESOLUTION
, VIPS_MAX_WIDTH
, VIPS_MAX_HEIGHT
:
VIPS_MAX_RESOLUTION=16800000
VIPS_MAX_WIDTH=5000
VIPS_MAX_HEIGHT=5000
Allowed Sources and Base URL
Whitelist specific hosts to restrict loading images only from the allowed sources using HTTP_LOADER_ALLOWED_SOURCES
or HTTP_LOADER_ALLOWED_SOURCE_REGEXP
.
-
HTTP_LOADER_ALLOWED_SOURCES
accepts csv wth glob pattern e.g.:HTTP_LOADER_ALLOWED_SOURCES=*.foobar.com,my.foobar.com,mybucket.s3.amazonaws.com
-
HTTP_LOADER_ALLOWED_SOURCE_REGEXP
accepts a regular expression matching on the full URL e.g.:HTTP_LOADER_ALLOWED_SOURCE_REGEXP='^https://raw\.githubusercontent\.com/cshum/imagor/.*'
Alternatively, it is possible to set a base URL for loading images strictly from one HTTP source. This also trims down the base URL from image endpoint:
Example URL:
http://localhost:8000/unsafe/fit-in/200x150/filters:fill(yellow):watermark(raw.githubusercontent.com/cshum/imagor/master/testdata/gopher-front.png,repeat,bottom,0,40,40)/raw.githubusercontent.com/cshum/imagor/master/testdata/dancing-banana.gif
With HTTP Loader Base URL config:
HTTP_LOADER_BASE_URL=https://raw.githubusercontent.com/cshum/imagor/master
The example URL then becomes:
http://localhost:8000/unsafe/fit-in/200x150/filters:fill(yellow):watermark(testdata/gopher-front.png,repeat,bottom,0,40,40)/testdata/dancing-banana.gif
Metadata and Exif
imagor provides metadata endpoint that extracts information such as image format, resolution and Exif metadata. Under the hood, it tries to retrieve data just enough to extract the header, without reading and processing the whole image in memory.
To use the metadata endpoint, add /meta
right after the URL signature hash before the image operations. Example:
http://localhost:8000/unsafe/meta/fit-in/50x50/raw.githubusercontent.com/cshum/imagor/master/testdata/Canon_40D.jpg
{
"format": "jpeg",
"content_type": "image/jpeg",
"width": 50,
"height": 34,
"orientation": 1,
"pages": 1,
"bands": 3,
"exif": {
"ApertureValue": "368640/65536",
"ColorSpace": 1,
"ComponentsConfiguration": "Y Cb Cr -",
"Compression": 6,
"DateTime": "2008:07:31 10:38:11",
"ISOSpeedRatings": 100,
"Make": "Canon",
"MeteringMode": 5,
"Model": "Canon EOS 40D",
//...
}
}
Prepending /params
to the existing endpoint returns the endpoint attributes in JSON form, useful for previewing the endpoint parameters. Example:
curl 'http://localhost:8000/params/g5bMqZvxaQK65qFPaP1qlJOTuLM=/fit-in/500x400/0x20/filters:fill(white)/raw.githubusercontent.com/cshum/imagor/master/testdata/gopher.png'
Go Library
imagor is a Go library built with speed, security and extensibility in mind. It facilitates high-level image processing in a modular architecture made up of a series of Go packages:
- imagor - the imagor core library
- imagorpath - parse and generate imagor endpoint
- vips - libvips C bindings with
imagor.Processor
implementation - httploader - HTTP Loader, an
imagor.Loader
implementation - filestorage - File Storage, an
imagor.Storage
implementation - s3storage - AWS S3 Storage, an
imagor.Storage
implementation - gcloudstorage - Google Cloud Storage, an
imagor.Storage
implementation
Install libvips and enable CGO:
brew install vips
for MacCGO_CFLAGS_ALLOW=-Xpreprocessor
being set to compile Go
See example below and also examples folder for various ways you can use imagor:
package main
import (
"context"
"github.com/cshum/imagor"
"github.com/cshum/imagor/imagorpath"
"github.com/cshum/imagor/loader/httploader"
"github.com/cshum/imagor/vips"
"io"
"os"
)
func main() {
app := imagor.New(
imagor.WithLoaders(httploader.New()),
imagor.WithProcessors(vips.NewProcessor()),
)
ctx := context.Background()
if err := app.Startup(ctx); err != nil {
panic(err)
}
defer app.Shutdown(ctx)
blob, err := app.Serve(ctx, imagorpath.Params{
Image: "https://raw.githubusercontent.com/cshum/imagor/master/testdata/gopher.png",
Width: 500,
Height: 500,
Smart: true,
Filters: []imagorpath.Filter{
{"fill", "white"},
{"format", "jpg"},
},
})
if err != nil {
panic(err)
}
reader, _, err := blob.NewReader()
if err != nil {
panic(err)
}
defer reader.Close()
file, err := os.Create("gopher.jpg")
if err != nil {
panic(err)
}
defer file.Close()
if _, err := io.Copy(file, reader); err != nil {
panic(err)
}
}
Configuration
imagor supports command-line arguments and environment variables for the arguments equivalent in capitalized snake case, see available options imagor -h
.
For instances -imagor-secret
would become IMAGOR_SECRET
:
# both are equivalent
imagor -debug -imagor-secret 1234
DEBUG=1 IMAGOR_SECRET=1234 imagor
Configuration can also be specified in a .env
environment variable file and referenced with the -config
flag:
imagor -config path/to/config.env
config.env:
PORT=8000
IMAGOR_SECRET=mysecret
DEBUG=1
Available options
imagor -h
Usage of imagor:
-debug
Debug mode
-port int
Server port (default 8000)
-version
imagor version
-config string
Retrieve configuration from the given file (default ".env")
-imagor-secret string
Secret key for signing imagor URL
-imagor-unsafe
Unsafe imagor that does not require URL signature. Prone to URL tampering
-imagor-auto-webp
Output WebP format automatically if browser supports
-imagor-auto-avif
Output AVIF format automatically if browser supports (experimental)
-imagor-base-params string
imagor endpoint base params that applies to all resulting images e.g. filters:watermark(example.jpg)
-imagor-signer-type string
imagor URL signature hasher type: sha1, sha256, sha512 (default "sha1")
-imagor-signer-truncate int
imagor URL signature truncate at length
-imagor-result-storage-path-style string
imagor result storage path style: original, digest, suffix (default "original")
-imagor-storage-path-style string
imagor storage path style: original, digest (default "original")
-imagor-cache-header-ttl duration
imagor HTTP cache header ttl for successful image response (default 168h0m0s)
-imagor-cache-header-swr duration
imagor HTTP Cache-Control header stale-while-revalidate for successful image response (default 24h0m0s)
-imagor-cache-header-no-cache
imagor HTTP Cache-Control header no-cache for successful image response
-imagor-request-timeout duration
Timeout for performing imagor request (default 30s)
-imagor-load-timeout duration
Timeout for imagor Loader request, should be smaller than imagor-request-timeout
-imagor-save-timeout duration
Timeout for saving image to imagor Storage
-imagor-process-timeout duration
Timeout for image processing
-imagor-process-concurrency int
Maximum number of image process to be executed simultaneously. Requests that exceed this limit are put in the queue. Set -1 for no limit (default -1)
-imagor-process-queue-size int
Maximum number of image process that can be put in the queue. Requests that exceed this limit are rejected with HTTP status 429
-imagor-base-path-redirect string
URL to redirect for imagor / base path e.g. https://www.google.com
-imagor-modified-time-check
Check modified time of result image against the source image. This eliminates stale result but require more lookups
-imagor-disable-params-endpoint
imagor disable /params endpoint
-imagor-disable-error-body
imagor disable response body on error
-server-address string
Server address
-server-cors
Enable CORS
-server-strip-query-string
Enable strip query string redirection
-server-path-prefix string
Server path prefix
-server-access-log
Enable server access log
-prometheus-bind string
Specify address and port to enable Prometheus metrics, e.g. :5000, prom:7000
-prometheus-path string
Prometheus metrics path (default "/")
-http-loader-allowed-sources string
HTTP Loader allowed hosts whitelist to load images from if set. Accept csv wth glob pattern e.g. *.google.com,*.github.com.
-http-loader-base-url string
HTTP Loader base URL that prepends onto existing image path. This overrides the default scheme option.
-http-loader-forward-headers string
Forward request header to HTTP Loader request by csv e.g. User-Agent,Accept
-http-loader-override-response-headers string
Override HTTP Loader response header to image response by csv e.g. Cache-Control,Expires
-http-loader-forward-client-headers
Forward browser client request headers to HTTP Loader request
-http-loader-insecure-skip-verify-transport
HTTP Loader to use HTTP transport with InsecureSkipVerify true
-http-loader-max-allowed-size int
HTTP Loader maximum allowed size in bytes for loading images if set
-http-loader-proxy-urls string
HTTP Loader Proxy URLs. Enable HTTP Loader proxy only if this value present. Accept csv of proxy urls e.g. http://user:pass@host:port,http://user:pass@host:port
-http-loader-allowed-source-regexp string
HTTP Loader allowed hosts regexp to load images from if set. Combines as OR with allowed host glob pattern sources.
-http-loader-proxy-allowed-sources string
HTTP Loader Proxy allowed hosts that enable proxy transport, if proxy URLs are set. Accept csv wth glob pattern e.g. *.google.com,*.github.com.
-http-loader-default-scheme string
HTTP Loader default scheme if not specified by image path. Set "nil" to disable default scheme. (default "https")
-http-loader-accept string
HTTP Loader set request Accept header and validate response Content-Type header (default "*/*")
-http-loader-block-link-local-networks
HTTP Loader rejects connections to link local network IP addresses.
-http-loader-block-loopback-networks
HTTP Loader rejects connections to loopback network IP addresses.
-http-loader-block-private-networks
HTTP Loader rejects connections to private network IP addresses.
-http-loader-block-networks string
HTTP Loader rejects connections to link local network IP addresses. This options takes a comma separated list of networks in CIDR notation e.g ::1/128,127.0.0.0/8.
-http-loader-disable
Disable HTTP Loader
-file-safe-chars string
File safe characters to be excluded from image key escape. Set -- for no-op
-file-loader-base-dir string
Base directory for File Loader. Enable File Loader only if this value present
-file-loader-path-prefix string
Base path prefix for File Loader
-file-result-storage-base-dir string
Base directory for File Result Storage. Enable File Result Storage only if this value present
-file-result-storage-mkdir-permission string
File Result Storage mkdir permission (default "0755")
-file-result-storage-path-prefix string
Base path prefix for File Result Storage
-file-result-storage-write-permission string
File Storage write permission (default "0666")
-file-result-storage-expiration duration
File Result Storage expiration duration e.g. 24h. Default no expiration
-file-storage-base-dir string
Base directory for File Storage. Enable File Storage only if this value present
-file-storage-path-prefix string
Base path prefix for File Storage
-file-storage-mkdir-permission string
File Storage mkdir permission (default "0755")
-file-storage-write-permission string
File Storage write permission (default "0666")
-file-storage-expiration duration
File Storage expiration duration e.g. 24h. Default no expiration
-aws-access-key-id string
AWS Access Key ID. Required if using S3 Loader or S3 Storage
-aws-region string
AWS Region. Required if using S3 Loader or S3 Storage
-aws-secret-access-key string
AWS Secret Access Key. Required if using S3 Loader or S3 Storage
-aws-session-token string
AWS Session Token. Optional temporary credentials token
-s3-endpoint string
Optional S3 Endpoint to override default
-s3-safe-chars string
S3 safe characters to be excluded from image key escape. Set -- for no-op
-s3-force-path-style
S3 force the request to use path-style addressing s3.amazonaws.com/bucket/key, instead of bucket.s3.amazonaws.com/key
-s3-loader-bucket string
S3 Bucket for S3 Loader. Enable S3 Loader only if this value present
-s3-loader-base-dir string
Base directory for S3 Loader
-s3-loader-path-prefix string
Base path prefix for S3 Loader
-s3-result-storage-bucket string
S3 Bucket for S3 Result Storage. Enable S3 Result Storage only if this value present
-s3-result-storage-base-dir string
Base directory for S3 Result Storage
-s3-result-storage-path-prefix string
Base path prefix for S3 Result Storage
-s3-result-storage-acl string
Upload ACL for S3 Result Storage (default "public-read")
-s3-result-storage-expiration duration
S3 Result Storage expiration duration e.g. 24h. Default no expiration
-s3-storage-bucket string
S3 Bucket for S3 Storage. Enable S3 Storage only if this value present
-s3-storage-base-dir string
Base directory for S3 Storage
-s3-storage-path-prefix string
Base path prefix for S3 Storage
-s3-storage-acl string
Upload ACL for S3 Storage (default "public-read")
-s3-storage-expiration duration
S3 Storage expiration duration e.g. 24h. Default no expiration
-aws-loader-access-key-id string
AWS Access Key ID for S3 Loader to override global config
-aws-loader-region string
AWS Region for S3 Loader to override global config
-aws-loader-secret-access-key string
AWS Secret Access Key for S3 Loader to override global config
-aws-loader-session-token string
AWS Session Token for S3 Loader to override global config
-s3-loader-endpoint string
Optional S3 Loader Endpoint to override default
-aws-storage-access-key-id string
AWS Access Key ID for S3 Storage to override global config
-aws-storage-region string
AWS Region for S3 Storage to override global config
-aws-storage-secret-access-key string
AWS Secret Access Key for S3 Storage to override global config
-aws-storage-session-token string
AWS Session Token for S3 Storage to override global config
-s3-storage-endpoint string
Optional S3 Storage Endpoint to override default
-aws-result-storage-access-key-id string
AWS Access Key ID for S3 Result Storage to override global config
-aws-result-storage-region string
AWS Region for S3 Result Storage to override global config
-aws-result-storage-secret-access-key string
AWS Secret Access Key for S3 Result Storage to override global config
-aws-result-storage-session-token string
AWS Session Token for S3 Result Storage to override global config
-s3-result-storage-endpoint string
Optional S3 Storage Endpoint to override default
-gcloud-safe-chars string
Google Cloud safe characters to be excluded from image key escape. Set -- for no-op
-gcloud-loader-base-dir string
Base directory for Google Cloud Loader
-gcloud-loader-bucket string
Bucket name for Google Cloud Storage Loader. Enable Google Cloud Loader only if this value present
-gcloud-loader-path-prefix string
Base path prefix for Google Cloud Loader
-gcloud-result-storage-acl string
Upload ACL for Google Cloud Result Storage
-gcloud-result-storage-base-dir string
Base directory for Google Cloud Result Storage
-gcloud-result-storage-bucket string
Bucket name for Google Cloud Result Storage. Enable Google Cloud Result Storage only if this value present
-gcloud-result-storage-expiration duration
Google Cloud Result Storage expiration duration e.g. 24h. Default no expiration
-gcloud-result-storage-path-prefix string
Base path prefix for Google Cloud Result Storage
-gcloud-storage-acl string
Upload ACL for Google Cloud Storage
-gcloud-storage-base-dir string
Base directory for Google Cloud
-gcloud-storage-bucket string
Bucket name for Google Cloud Storage. Enable Google Cloud Storage only if this value present
-gcloud-storage-expiration duration
Google Cloud Storage expiration duration e.g. 24h. Default no expiration
-gcloud-storage-path-prefix string
Base path prefix for Google Cloud Storage
-vips-max-animation-frames int
VIPS maximum number of animation frames to be loaded. Set 1 to disable animation, -1 for unlimited
-vips-disable-blur
VIPS disable blur operations for vips processor
-vips-disable-filters string
VIPS disable filters by csv e.g. blur,watermark,rgb
-vips-max-filter-ops int
VIPS maximum number of filter operations allowed. Set -1 for unlimited (default -1)
-vips-max-width int
VIPS max image width
-vips-max-height int
VIPS max image height
-vips-max-resolution int
VIPS max image resolution
-vips-mozjpeg
VIPS enable maximum compression with MozJPEG. Requires mozjpeg to be installed
-vips-avif-speed int
VIPS avif speed, the lowest is at 0 and the fastest is at 9 (Default 5).
-vips-strip-metadata
VIPS strips all metadata from the resulting image
Top Related Projects
thumbor is an open-source photo thumbnail service by globo.com
Fast, simple, scalable, Docker-ready HTTP microservice for high-level image processing
A caching, resizing image proxy written in Go
An image resizing server written in Go
Dockerized application that resizes and crops images on the fly, delivering optimized images in formats such as AVIF, WebP, MozJPEG, or PNG using ImageMagick, with an efficient caching system.
Fast and secure standalone server for resizing and converting remote images
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot