You can draw additional images on top of a resized image, with transparency and blending effects. This enables adding of watermarks, logos, signatures, vignettes, and other effects to resized images.
This feature is available only in Workers. To draw overlay images, add an array of drawing commands to options of fetch() requests. The drawing options are nested in options.cf.image.draw, like in the following example:
fetch(imageURL, {
cf: {
image: {
width: 800,
height: 600,
draw: [
{
url: "https://example.com/branding/logo.png", // draw this image
bottom: 5, // 5 pixels from the bottom edge
right: 5, // 5 pixels from the right edge
fit: "contain", // make it fit within 100x50 area
width: 100,
height: 50,
opacity: 0.8, // 20% transparent
},
],
},
},
});The draw property is an array. Overlays are drawn in the order they appear in the array (the last array entry is the topmost layer). Each item in the draw array is an object, which can have the following properties:
-
url- Absolute URL of the image file to use for the drawing. It can be any of the supported file formats. For drawing watermarks or non-rectangular overlays, Cloudflare recommends that you use PNG or WebP images.
-
widthandheight- Maximum size of the overlay image. Accepts an integer (pixels) or a decimal between
0and1representing a fraction of the original image's dimension. For example,height: 0.25sets the overlay height to 25% of the parent image's height.
- Maximum size of the overlay image. Accepts an integer (pixels) or a decimal between
-
fitandgravity- Affects interpretation of
widthandheight. Same as for the main image.
- Affects interpretation of
-
opacity- Floating-point number between
0(transparent) and1(opaque). For example,opacity: 0.5makes overlay semitransparent.
- Floating-point number between
-
repeat- If set to
true, the overlay image will be tiled to cover the entire area. This is useful for stock-photo-like watermarks. - If set to
"x", the overlay image will be tiled horizontally only (form a line). - If set to
"y", the overlay image will be tiled vertically only (form a line).
- If set to
-
top,left,bottom,right-
Position of the overlay image relative to a given edge. Each property is an offset in pixels.
0aligns exactly to the edge. For example,left: 10positions left side of the overlay 10 pixels from the left edge of the image it is drawn over.bottom: 0aligns bottom of the overlay with bottom of the background image.Setting both
leftandright, or bothtopandbottomis an error.If no position is specified, the image will be centered.
-
-
background- Background color to add underneath the overlay image. Same as for the main image.
-
rotate- Number of degrees to rotate the overlay image by. Same as for the main image.
When interacting with Images through a binding, the Images API supports a .draw() method.
The accepted options for the overlaid image are opacity, repeat, top, left, bottom, and right.
// Fetch image and watermark
const img = await fetch("https://example.com/image.png");
const watermark = await fetch("https://example.com/watermark.png");
const response = (
await env.IMAGES.input(img.body)
.transform({ width: 1024 })
.draw(watermark.body, { opacity: 0.25, repeat: true })
.output({ format: "image/avif" })
).response();
return response;To apply parameters to the overlaid image, you can pass a child .transform() function inside the .draw() request.
In the example below, the watermark is manipulated with rotate and width before being drawn over the base image with the opacity and rotate options.
// Fetch image and watermark
const response = (
await env.IMAGES.input(img.body)
.transform({ width: 1024 })
.draw(watermark.body, { opacity: 0.25, repeat: true })
.output({ format: "image/avif" })
).response();image: {
draw: [
{
url: 'https://example.com/watermark.png',
repeat: true, // Tiled over entire image
opacity: 0.2, // and subtly blended
},
],
}image: {
draw: [
{
url: 'https://example.com/by-me.png', // Predefined logo/signature
bottom: 5, // Positioned near bottom right corner
right: 5,
},
],
}image: {
draw: [
{
url: 'https://example.com/play-button.png',
// Center position is the default
},
],
}Multiple operations can be combined in one image:
image: {
draw: [
{ url: 'https://example.com/watermark.png', repeat: true, opacity: 0.2 },
{ url: 'https://example.com/play-button.png' },
{ url: 'https://example.com/by-me.png', bottom: 5, right: 5 },
],
}