Skip to content

Manipulating Images in CDN

Our CDN implements on-the-fly image manipulation using improxy. It support resizing, format change, rotation, varying levels of compression  and more. So, it is needed to generate all sizes and formats for each image for each image in advance, but rather on demand, which leads to significant savings in disk space.

Usage

All parameters of the requested image are encoded in the URL and the request is signed with a key unique for each client, so no one can forge or alter a request.

The simplest URL format for resizing an image looks like this:

example.vshcdn.net/zoh4eiLi/IMG/%TTL/%signature/%resizing_type/%width/%height/%gravity/%enlarge/%encoded_source_url.%extension

Explanation of individual URL parts

  • example.vshcdn.net - the name of the domain you are pointed to VshCDN
  • /zoh4eiLi/IMG/ - location passed to imgproxy, becase the standard location /imgproxy could possibly conflict with /imgproxy on the customer domain
  • %TTL - sets how long the image should be cached in the client browser and on intermediate proxies, including CDN
  • %signature - request signature, string hash that can be generated only by person with access to the customer's CDN key
  • %resizing_type/%width/%height/%gravity/%enlarge - request parameters for imgproxy, will be explained in more detail in the section on supported operations
  • %encoded_source_url -  URL from which to download the image to be processed, encoded in base64
  • %extension - what format should the resulting image have

Signature generation

To generate a signature, you need to know the following parameters:

  • key: value form administration - ImgApi Key - (https://cdn.vshosting.cloud/cdndomains => Show details => Current configuration)
  • salt: value from administration - ImgApi Salt - (https://cdn.vshosting.cloud/cdndomains => Show details => Current configuration)
  • ttl: %ttl value from URL
  • path: the following part of the URL: "%resizing_type/%width/%height/%gravity/%enlarge/%encoded_source_url.%extension"

then you calculate it as follows:

$keyBin = pack("H*" , $key);  
$saltBin = pack("H*" , $salt);  
signature = rtrim(strtr(base64_encode(hash_hmac('sha256', $saltBin."/".$ttl."/".$path, $keyBin, true)), '+/', '-_'), '=');

Example of PHP script for URL generation on image resize

<?php  
$key = ''; // value from administration - ImgApi Key - (https://cdn.vshosting.cloud/cdndomains => Show details => Current configuration)  

$salt = ''; // value from administration - ImgApi Salt  
$cdn_domain_or_alias = 'example.vshcdn.net'; // CDN Domain Alias ​​or value from CDN domain administration  
$backend_url = 'https://example.com/obrazek.jpg'; // URL to backend image  
$ttl = 7200; // cache (browser + CDN) for x seconds, minimum value 3600  

// resize parameters configuration  
$resize = 'fill';  
$width = 50;  
$height = 50;  
$gravity = 'no';  
$enlarge = 1;  
$extension = 'jpg';  

$keyBin = pack("H*" , $key);  
if(empty($keyBin)) {  
die('Key expected to be hex-encoded string');  
}  
$saltBin = pack("H*" , $salt);  
if(empty($saltBin)) {  
die('Salt expected to be hex-encoded string');  
}  

$encodedUrl = rtrim(strtr(base64_encode($backend_url), '+/', '-_'), '=');  
$path = "/{$resize}/{$width}/{$height}/{$gravity}/{$enlarge}/{$encodedUrl}.{$extension}";  
$signature = rtrim(strtr(base64_encode(hash_hmac('sha256', $saltBin."/".$ttl."/".$path, $keyBin, true)), '+/', '-_'), '=');  

print(sprintf("%s/zoh4eiLi/IMG/%d/%s%s", $cdn_domain_or_alias, $ttl, $signature, $path));

Custom file name at the end of the url

If we replace IMG with IMGCU in the URL cdn will discard the part of the URL that comes after the last /, the URL can then look like this:

example.vshcdn.net/zoh4eiLi/IMGCU/%TTL/%signature/%resizing_type/%width/%height/%gravity/%enlarge/%encoded_source_url.%extension/mujvlastninazev.jpg

To use the cache delete function, we must provide the URL without the last part, i.e.:

example.vshcdn.net/zoh4eiLi/IMGCU/%TTL/%signature/%resizing_type/%width/%height/%gravity/%enlarge/%encoded_source_url.%extension

Advanced operations

In addition to the simple URL format, where the default operation is resize, imgproxy allows you to perform more advanced operations. This is the URL format is used for them:

example.vshcdn.net/zoh4eiLi/IMG/%TTL/%signature/%processing_options/%encoded_source_url.%extension

The %processing_options parameter consists of individual operations. Each operation has "%option_name:%argument1:%argument2: ...:argumentN" format, where individual operations are separated by a slash.

Types of operations

Rotate

Description: rotates image clockwise by the specified degree.
URL: rotate:%angle
Parameters: angle: how many degrees to rotate the image, supported values are ​​0,90,180,270

Quality

Description: reduces the quality and thus the size of the generated image
URL: quality:%quality
Parameters: quality: percentage value of quality in the range 0-100

Max Bytes

Description: reduces the image quality below the specified value, an alternative to the Quality operation
URL: max_bytes:%bytes
Parameters: max_bytes - maximum size of the generated image
Note: only the following formats are currently supported: jpg, webp, heic, tiff

Blur

Description: blurs the image according to the set intensity
URL: blur:%sigma
Parameters: sigma: the size of the mask, i.e. the sigma value for the Gaussian weight distribution for the colors of the surrounding pixels

Resize

Description: determines to what dimensions to change the image
URL: resize:%resizing_type:% width:% height:%enlarge
Parameters: resizing_type: see below
width: the resulting width
height: the resulting height
enlarge: whether to enlarge the image when the required size is larger than the original

Resizing type

Description: Specifies the behavior of the img proxy when resizing
URL: resizing_type:%resizing_type
Parameters: resizing_type: how to perform resize, possible values ​​are as follows:
fit: resizes while maintaining the aspect ratio so that the resulting image is the same or smaller than the specified size
fill: preserves the aspect ratio and crops parts of the image so that the resulting image exactly fills the specified dimensions
auto: if the new and original sizes have the same orientation, use fill, otherwise use fit

Gravity

Description: determines which part of the image to try to keep if parts of the image need to be deleted during resize
URL: gravity:%type:%x_offset:%y_offset
Parameters:
x_offset: shifts the resulting gravity in the X axis
y_offset: shifts the resulting gravity in the Y axis
type: type of gravity, i.e. what part of the image is preserved. Available values ​​are:
   ce: (center) center
   no: (north) top edge
   so: (south) lower edge
   ea: (east) right edge
   we: (west) left edge
   noea: (north-east) upper right corner
   nowe: (north-west) upper left corner
   soea: (south-east) lower right corner
   sowe: (south-west) lower left corner

Watermark

Description: inserts a watermark on the image according to the set size, position and intensity 
URL: watermark:%opacity:%position:%x_offset:%y_offset:%scale
Parameters:
opacity: watermark transparency: multiplies the current transparency of the image used for the watermark
position: (optional) specify watermark position: available values are
   ce: (center) center
   no: (north) top edge
   so: (south) lower edge
   ea: (east) right edge
   we: (west) left edge
   noea: (north-east) upper right corner
   nowe: (north-west) upper left corner
   soea: (south-east) lower right corner
   sowe: (south-west) lower left corner
x_offset: (optional) shifts the resulting position in the X axis (not applicable with a "re" position)
y_offset: (optional) shifts the resulting position in the Y axis (not applicable with a "re" position)
scale: (optional) a decimal value that determines the relative size of the watermark to the image

Note: there are 2 special options:
"gravity: sm": smart gravity: imgproxy will try to detect which part of the image is most interesting
"gravity:fp:%x:%y": point gravity: the values ​​of x, y are values ​​between 0 and 1, which determine the vicinity of which part of the image the priority should be maintained. The value [0: 0] is the upper right corner and [1: 1] is the lower left corner.

This is not a complete list of all available operations, but only a selection of the most used ones. The complete list can be found at https://docs.imgproxy.net/#/generating_the_url_advanced.

Combining multiple operations

With the following access credentials:
key = '2387c7e85671cf44'
salt = '9b578a46eacd3b76'

We have a CDN domain "my_domain.vshcdn.net" and the image source is "https://my_domain.com/picture.jpg"
We want to cache the image for 2 hours and we want the new image to have 300x400 changes, the quality being 50% of the original, to be rotated to the right, and for imgproxy to detect which part of the image may be cropped.
And the resulting format should be a modern webp.

The encoded backend URL will therefore be aHR0cHM6Ly9tb2plX2RvbWVuYS5jb20vb2JyYXplay5qcGc

The resulting request URL will look like this:
/resize:fill:300:400:0/gravity:sm/quality:50/rotate:90/aHR0cHM6Ly9tb2plX2RvbWVuYS5jb20vb2JyYXplay5qcGc.webp

The signature of the request will be cnxeUxbuns6P-4OwZBBIMzWxOcGQvaHZHjM1GYYIgXM

And the complete URL will be:
https://my_domain.vshcdn.net/zoh4eiLi/IMG/7200/cnxeUxbuns6P-4OwZBBIMzWxOcGQvaHZHjM1GYYIgXM/resize:fill:300:400:0/gravity:sm/quality:50/rotate:90/aHR0cHM6Ly9tb2plX2RvbWVuYS5jb20vb2JyYXplay5qcGc.webp