Image resizing, cropping and compression on the fly with the impressive MozJPEG compression algorithm. One Docker container to build your own Cloudinary-like service.
Fetch an image from anywhere; resize, compress, cache and serve... and serve, and serve, and serve...
You pass the image URL and a set of keys with options, like size or compression. Flyimg will fetch the image, convert it, store it, cache it and serve it. The next time the request comes, it will serve the cached version.
<!-- https://www.mozilla.org/media/img/firefox/firefox-256.e2c1fc556816.jpg -->
<img src="https://my.img.service.io/upload/w_333,h_333,q_90/https://www.mozilla.org/media/img/firefox/firefox-256.e2c1fc556816.jpg">
http://oi.flyimg.io/upload/w_300,h_250,c_1/https://m0.cl/t/resize-test_1920.jpg
- Requirements
- Installation [Deployment mode]
- Installation [Development Mode]
- Testing Flyimg service
- How to transform images
- Option details
- output string
- mozjpeg bool
- quality int (0-100)
- width int
- height int
- Using width AND height
- crop bool
- gravity string
- background color (multiple formats)
- strip int
- resize int
- unsharp radiusxsigma{ gain}{ threshold}
- filter string
- scale int
- rotate string
- refresh int
- Face Crop int
- Face Crop Position int
- Face Blur int
- Enable Restricted Domains
- Run test
- How to Provision the application on
- Technology stack
- Benchmark
- Demo Application running
- Roadmap
- Contributors
- Backers
- Sponsors
You will need to have Docker on your machine. Optionally you can use Docker machine to create a virtual environment. We have tested on Mac, Windows and Ubuntu.
Pull the image
docker pull flyimg/flyimg-build
Start the container
docker run -itd -p 8080:80 flyimg/flyimg-build
Check how to provision the application
You can spin up your own working server in 10 minutes using the provision scripts for AWS Elastic Beanstalk or the DigitalOcean Ubuntu Droplets (more environments to come). For other environments or if you want to tweak and play in your machine before rolling out, read along...
You can use git
or composer
for the first step.
git clone https://github.com/flyimg/flyimg.git
Create the project with composer create
.
composer create-project flyimg/flyimg
CD into the folder and to build the docker image by running:
docker build -t flyimg .
This will download and build the main image, It will take a few minutes. If you get some sort of error related to files not found by apt-get or similar, try this same command again.
Then run the container:
docker run -itd -p 8080:80 -v $(pwd):/var/www/html --name flyimg flyimg
For Fish shell users:
docker run -itd -p 8080:80 -v $PWD:/var/www/html --name flyimg flyimg
The above command will make the Dockerfile run supervisord command which launches 2 processes: nginx and php-fpm and starts listening on port 8080.
IMPORTANT! If you cloned the project, only for the first time, you need to run composer install
inside the container:
docker exec -it flyimg composer install
Again, it will take a few minutes to download the dependencies. Same as before, if you get some errors you should try running composer install
again.
You can navigate to your machine's IP in port 8080 (ex: http://127.0.0.1:8080/ ) ; you should get a message saying: Hello from Flyimg! and a small homepage of flyimg already working. If you get any errors at this stage it's most likely that composer has not finished installing or skipped something.
You can test your image resizing service by navigating to: http://127.0.0.1:8080/upload/w_130,h_113,q_90/https://www.mozilla.org/media/img/firefox/firefox-256.e2c1fc556816.jpg
It's working!
This is fetching an image from Mozilla, resizing it, saving it and serving it.
You go to your server URLhttp://imgs.kitty.com
and append /upload/
; after that you can pass these options below, followed by an underscore and a value w_250,q_50
Options are separated by coma (configurable to other separator) .
After the options put the source of your image, it can be relative to your server or absolute: /https://my.storage.io/imgs/pretty-kitten.jpg
So to get a pretty kitten at 250 pixels wide, with 50% compression, you would write.
<img src="http://imgs.kitty.com/upload/w_250,q_50/https://my.storage.io/imgs/pretty-kitten.jpg">
options_keys:
moz: mozjpeg
q: quality
o: output
unsh: unsharp
fc: face-crop
fcp: face-crop-position
fb: face-blur
w: width
h: height
c: crop
bg: background
st: strip
rz: resize
g: gravity
f: filter
r: rotate
sc: scale
sf: sampling-factor
rf: refresh
ett: extent
par: preserve-aspect-ratio
pns: preserve-natural-size
webpl: webp-lossless
default_options:
mozjpeg: 1
quality: 90
output: auto
unsharp: null
face-crop: 0
face-crop-position: 0
face-blur: 0
width: null
height: null
crop: null
background: null
strip: 1
resize: null
gravity: Center
filter: Lanczos
rotate: null
scale: null
sampling-factor: 1x1
refresh: false
extent: null
preserve-aspect-ratio: 1
preserve-natural-size: 1
webp-lossless: 0
Most of these options are ImageMagick flags, many can get pretty advanced, use the ImageMagick docs. We put a lot of defaults in place to prevent distortion, bad quality
default: auto : Output format requested, for example you can force the output as jpeg file in case of source file is png.
example:o_auto
,o_png
,o_webp
,o_jpeg
,o_jpg
default: 1 : Use moz-jpeg compression library, if false
it fallback to the default ImageMagick compression algorithm.
example:moz_0
default: 90 : Sets the compression level for the output image. Your best results will be between 70 and 95.
example:q_100
,q_75
,...
q_30
: http://oi.flyimg.io/upload/q_30/https://raw.githubusercontent.com/flyimg/flyimg/master/web/Rovinj-Croatia.jpg
q_100
: http://oi.flyimg.io/upload/q_100/https://raw.githubusercontent.com/flyimg/flyimg/master/web/Rovinj-Croatia.jpg
default: null : Sets the target width of the image. If not set, width will be calculated in order to keep aspect ratio.
example:w_100
w_100
: http://oi.flyimg.io/upload/w_100/https://raw.githubusercontent.com/flyimg/flyimg/master/web/Rovinj-Croatia.jpg
default: null : Sets the target height of the image. If not set, height will be calculated in order to keep aspect ratio.
example:h_100
h_100
: http://oi.flyimg.io/upload/h_100/https://raw.githubusercontent.com/flyimg/flyimg/master/web/Rovinj-Croatia.jpg
example:h_300,w_300
By default setting width and height together, works like defining a rectangle that will define a max-width and max-height and the image will scale propotionally to fit that area without cropping.
By default; width, height, or both will not scale up an image that is smaller than the defined dimensions.
h_300,w_300
: http://oi.flyimg.io/upload/h_300,w_300/https://raw.githubusercontent.com/flyimg/flyimg/master/web/Rovinj-Croatia.jpg
default: false : When both width and height are set, this allows the image to be cropped so it fills the width x height area.
example:c_1
c_1,h_400,w_400
: http://oi.flyimg.io/upload/c_1,h_400,w_400/https://raw.githubusercontent.com/flyimg/flyimg/master/web/Rovinj-Croatia.jpg
default: Center : When crop is applied, changing the gravity will define which part of the image is kept inside the crop area.
The basic options are: NorthWest
, North
, NorthEast
, West
, Center
, East
, SouthWest
, South
, SouthEast
.
example:g_West
[...] -gravity NorthWest ...
default: white : Sets the background of the canvas for the cases where padding is added to the images. It supports hex, css color names, rgb.
Only css color names are supported without quotation marks.
For the hex code, the hash #
character should be replaced by %23
example:bg_red
,bg_%23ff4455
,bg_rgb(255,120,100)
,...
[...] -background red ...
[...] -background "#ff4455" -> "%23ff4455"
[...] -background "rgb(255,120,100)" ...
http://oi.flyimg.io/upload/r_45,w_400,h_400,bg_red/https://raw.githubusercontent.com/flyimg/flyimg/master/web/Rovinj-Croatia.jpg
default: 1 : removes exif data and additional color profile.
example:st_1
default: null : The alternative resizing method to -thumbnail.
example:rz_1
default: null : Sharpens an image with a convolved Gausian operator. A good example 0.25x0.25+8+0.065
.
example:unsh_0.25x0.25+8+0.065
[...] -unsharp 0.25x0.25+8+0.065 ...
default: Lanczos : Resizing algorithm, Triangle is a smoother lighter option
example:f_Triangle
[...] -filter Triangle
default: null : The "-scale" resize operator is a simplified, faster form of the resize command. Useful for fast exact scaling of pixels.
example:sc_1
default: null : Apply image rotation (using shear operations) to the image.
example: r_90
, r_-180
,...
r_45
: http://oi.flyimg.io/upload/r_-45,w_400,h_400/https://raw.githubusercontent.com/flyimg/flyimg/master/web/Rovinj-Croatia.jpg
default: false : Refresh will delete the local cached copy of the file requested and will generate the image again. Also it will send headers with the command done on the image + info returned by the command identity from IM.
example:rf_1
default: false : Using facedetect repository to detect faces and passe the coordinates to ImageMagick to crop.
example:fc_1
fc_1
: http://oi.flyimg.io/upload/fc_1/http://facedetection.jaysalvat.com/img/faces.jpg
default: false : When using the Face crop option and when the image contain more than one face, you can specify which one you want get cropped
example:fcp_1
,fcp_0
,...
fcp_2
: http://oi.flyimg.io/upload/fc_1,fcp_2/http://facedetection.jaysalvat.com/img/faces.jpg
default: false : Apply blur effect on faces in a given image
example:fb_1
fb_1
: http://oi.flyimg.io/upload/fb_1/http://facedetection.jaysalvat.com/img/faces.jpg
Restricted domains disabled by default. This means that you can fetch a resource from any URL. To enable the domain restriction, change in config/parameters.yml
restricted_domains: true
After enabling, you need to put the white listed domains
whitelist_domains:
- www.domain-1.org
- www.domain-2.org
docker exec -it flyimg vendor/bin/phpunit tests/
- Server: nginx
- Application: Silex , a PHP microframework.
- Image manipulation: ImageMagik
- JPEG encoder: MozJpeg
- Storage: Flysystem
- Containerisation: Docker
Storage files based on Flysystem which is a filesystem abstraction allows you to easily swap out a local filesystem for a remote one. Technical debt is reduced as is the chance of vendor lock-in.
Default storage is Local, but you can use other Adapters like AWS S3, Azure, FTP, Dropbox, ...
Currently, only the local and S3 are implemented as Storage Provider in Flyimg application, but you can add your specific one easily in src/Core/Provider/StorageProvider.php
in parameters.yml change the storage_system
option from local to s3, and fill in the aws_s3 options :
storage_system: s3
aws_s3:
access_id: "s3-access-id"
secret_key: "s3-secret-id"
region: "s3-region"
bucket_name: "s3-bucket-name"
See benchmark.sh for more details Requires: Vegeta http://github.com/tsenart/vegeta
Crop http://localhost:8080/upload/w_200,h_200,c_1,/Rovinj-Croatia.jpg
Requests [total, rate] 500, 50.10
Duration [total, attack, wait] 9.986739873s, 9.97999984s, 6.740033ms
Latencies [mean, 50, 95, 99, max] 25.076911ms, 6.640774ms, 188.643721ms, 331.643374ms, 636.521662ms
Bytes In [total, mean] 213904, 427.81
Bytes Out [total, mean] 0, 0.00
Success [ratio] 100.00%
Status Codes [code:count] 200:500
Resize http://localhost:8080/upload/w_200,h_200,rz_1/Rovinj-Croatia.jpg
Requests [total, rate] 500, 50.10
Duration [total, attack, wait] 9.987057007s, 9.979999967s, 7.05704ms
Latencies [mean, 50, 95, 99, max] 12.830654ms, 7.643809ms, 40.270126ms, 108.39337ms, 195.252615ms
Bytes In [total, mean] 77994, 155.99
Bytes Out [total, mean] 0, 0.00
Success [ratio] 100.00%
Status Codes [code:count] 200:500
Rotate http://localhost:8080/upload/r_-45,w_400,h_400/Rovinj-Croatia.jpg
Requests [total, rate] 500, 50.10
Duration [total, attack, wait] 9.986181761s, 9.979999903s, 6.181858ms
Latencies [mean, 50, 95, 99, max] 984.630622ms, 585.392512ms, 2.660701812s, 2.763049369s, 6.202687668s
Bytes In [total, mean] 1304682, 2609.36
Bytes Out [total, mean] 0, 0.00
Success [ratio] 100.00%
Status Codes [code:count] 200:500
[http://oi.flyimg.io/upload/w_300,h_250,c_1/https://m0.cl/t/resize-test_1920.jpg]
- Benchmark the application.
- Decouple the core logic from Silex in order to make it portable.
- Test it with couple of frameworks, Phalcon Php is a good candidate.
- Add overlays functionality (Text on top of the image)
- Storage auto-mapping
This project exists thanks to all the people who contribute.
Thank you to all our backers! [Become a backer]
Thank you to all our sponsors! (please ask your company to also support this open source project by becoming a sponsor)
Licence: MIT
Enjoy your Flyimaging!