Cloudinary – Adding Solid Shape Overlays (Squares, Circles, Etc.)

  • report
    Click for Disclaimer
    This Post is over a year old (first published about 5 years ago). As such, please keep in mind that some of the information may no longer be accurate, best practice, or a reflection of how I would approach the same thing today.
  • infoFull Post Details
    info_outlineClick for Full Post Details
    Date Posted:
    Jan. 22, 2019
    Last Updated:
    Jan. 23, 2019
  • classTags
    classClick for Tags

Disclaimer: For anyone wondering, this post was not sponsored by Cloudinary or is in any way officially affiliated, endorsed, or supported by them.  I am just a big fan of them, and enjoy seeing how I can use all their features in unusual combinations.

Background Info:

This task, overlaying solid shapes on Cloudinary, is simple (somewhat), yet might be missed by many as even being possible. It uses a concept that I am fascinated by, that what is displayed on our computer screens is not a single image, but the result of many transformations and calculations. For example, it is impossible (in practical methods) to display a true curved line (or anything other than a perfectly horizontal or vertical line) on a pixel based display; pixels are squares, so the best you can do is push more and more pixels together until, when viewed from a distance, squares that are placed in a non-linear (e.g. polynomial) arrangement start to appear curved. This is why curves in really old video games, that are low resolution, look blocky and jagged.

For those interested, the process of transforming non-pixel-based shapes, such as a vector representation of a circle, into a pixel-based form (which is what you are looking at right now), is called “rasterisation“.

Rasterization - Turning Non-Pixel Based Sources or Vectors into Pixels

Wojciech Muła [GFDL (, CC-BY-SA-3.0 ( or CC BY-SA 2.5 (], via Wikimedia Commons

Anyway, I digress. The reason why I brought up transformations is because they are part of the core of Cloudinary, and what allows me to overlay custom shapes on top of images. The fact that Cloudinary lets users “chain” transformations together in an unlimited fashion, means that almost any shape can be dynamically rendered with a Cloudinary URL, given the right combination of pixel transformations.


Throughout this article, ACCOUNT_NAME stands in for the name of your Cloudinary cloud account, which should be a short string of characters and numbers.

Adding Squares:

Here is a practical example: A simple blue square added to the default Cloudinary sample image. Here is the sample image without any transformations, and the URL used to fetch it.


And here is the same image, with a blue square rendered over it:,w_200,h_200/co_rgb:4a90e2,e_colorize,fl_layer_apply,g_north_west,x_270,y_100/sample

Cloudinary - Drawing Blue Square Over Sample Image

The trick here is that “l_pixel” maps to an image I’ve uploaded to my account, with the public ID of “pixel”, and is a 1×1 solid colored pixel saved as an image file. The transformations applied above blow it up to 200 x 200 pixels, position it at x=270 and y=100, and “colorize” it with an RGB / Hex string corresponding to blue. You might think this is very basic, but the fact that you can chain these together means you can do crazy things like this:,w_500,h_500,o_40/h_302,l_pixel,w_17,x_146,y_48/co_rgb:4a90e2,e_colorize,fl_layer_apply,g_north_west,x_146,y_48/h_21,l_pixel,w_100,x_63,y_332/co_rgb:4a90e2,e_colorize,fl_layer_apply,g_north_west,x_63,y_332/h_97,l_pixel,w_20,x_63,y_254/co_rgb:4a90e2,e_colorize,fl_layer_apply,g_north_west,x_63,y_254/h_20,l_pixel,w_153,x_70,y_47/co_rgb:4a90e2,e_colorize,fl_layer_apply,g_north_west,x_70,y_47/h_100,l_pixel,w_100,x_166,y_70/co_rgb:000000,e_colorize,fl_layer_apply,g_north_west,x_166,y_70/h_15,l_pixel,w_85,x_246,y_50/co_rgb:6283aa,e_colorize,fl_layer_apply,g_north_west,x_246,y_50/h_83,l_pixel,w_15,x_246,y_51/co_rgb:6283aa,e_colorize,fl_layer_apply,g_north_west,x_246,y_51/h_20,l_pixel,w_89,x_246,y_117/co_rgb:6283aa,e_colorize,fl_layer_apply,g_north_west,x_246,y_117/h_76,l_pixel,w_17,x_321,y_117/co_rgb:6283aa,e_colorize,fl_layer_apply,g_north_west,x_321,y_117/h_22,l_pixel,w_100,x_240,y_173/co_rgb:6283aa,e_colorize,fl_layer_apply,g_north_west,x_240,y_173/h_138,l_pixel,w_19,x_327,y_173/co_rgb:27a456,e_colorize,fl_layer_apply,g_north_west,x_327,y_173/h_21,l_pixel,w_79,x_331,y_235/co_rgb:27a456,e_colorize,fl_layer_apply,g_north_west,x_331,y_235/h_100,l_pixel,w_23,x_386,y_238/co_rgb:27a456,e_colorize,fl_layer_apply,g_north_west,x_386,y_238/sample

Cloudinary - Multiple Solid Colored Squares Overlay on Image - Josh

Adding Circles:

Again, this is a bit of a “cheat”; there is not built-in way to overlay a solid circle with Cloudinary. However… it is possible to create a circle by first creating a square, and then rounding the corners with a radius. Check it out!,h_500,w_500/g_north_west,l_pixel,r_150,w_300,h_300/b_rgb:4a90e2,co_rgb:4a90e2,e_colorize,fl_layer_apply,g_north_west,x_90,y_90/sample

Cloudinary - Drawing Blue Circle Over Sample Image

Let’s Kick It Up a Notch:

OK, so far this might not seem all that impressive. What is the point? Well, think about how this could be applied to situations where you need to dynamically generate an image overlay based on a set of criteria. For example, if you make an online game and need to generate an achievement badge that can be shared to Facebook as an image, but the colors are based on the user’s profile settings. You can generate that image with Cloudinary, just by passing transformations in the image path, which means the image URL can even be generated completely client-side. Check out this doozy of a URL:,h_500,o_40,w_500/h_224,l_pixel,w_224/co_rgb:070707,e_colorize,fl_layer_apply,g_north_west,x_28,y_75/h_395,l_pixel,w_454/co_rgb:2744a6,e_colorize,fl_layer_apply,g_north_west,x_23,y_35/h_210,l_pixel,w_210/co_rgb:ffffff,e_colorize,fl_layer_apply,g_north_west,x_34,y_82/c_scale,h_188,l_profilepicture,w_215/fl_layer_apply,g_north_west,x_34,y_107/h_209,l_pixel,w_208/co_rgb:ffffff,e_colorize,fl_layer_apply,g_north_west,x_254,y_82/l_text:Roboto_37_normal:Stats:/co_rgb:000000,e_colorize,fl_layer_apply,g_north_west,x_316,y_93/l_text:Roboto_19_normal:Flowers%20Pollinated%20:%2020/co_rgb:000000,e_colorize,fl_layer_apply,g_north_west,x_266,y_141/l_text:Roboto_19_normal:People%20Chased%20:%2025/co_rgb:000000,e_colorize,fl_layer_apply,g_north_west,x_266,y_167/l_text:Roboto_55_normal:Buzzy%20McBuzzer/co_rgb:ffffff,e_colorize,fl_layer_apply,g_north_west,x_52,y_314/l_text:Roboto_31_normal:Rank%20:%2010/co_rgb:ffffff,e_colorize,fl_layer_apply,g_north_west,x_170,y_380/h_119,l_pixel,w_119/co_rgb:c8c61f,e_colorize,fl_layer_apply,g_north_west,r_59,x_295,y_194/l_text:Roboto_42_normal:%3C10%3E/co_rgb:000000,e_colorize,fl_layer_apply,g_north_west,x_308,y_237/sample

Cloudinary - Dynamic Gaming Badge Overlay Generated Example

Crazy, right? However, once you come up with a set of transformations you want to use together, you could either save it as a saved transformation, or dynamically generate the URL with just a little bit of code, for example, like this:

function getGamerBadge(gamerProfile){
	return ',h_500,o_40,w_500/h_224,l_pixel,w_224/co_rgb:000000,e_colorize,fl_layer_apply,g_north_west,x_28,y_75/h_395,l_pixel,w_454/co_rgb:' + gamerProfile.colors.dark + ',e_colorize,fl_layer_apply,g_north_west,x_23,y_35/h_210,l_pixel,w_210/co_rgb:' + gamerProfile.colors.light + ',e_colorize,fl_layer_apply,g_north_west,x_34,y_82/c_scale,h_188,l_' + gamerProfile.profileImageId + ',w_215/fl_layer_apply,g_north_west,x_34,y_107/h_209,l_pixel,w_208/co_rgb:' + gamerProfile.colors.light + ',e_colorize,fl_layer_apply,g_north_west,x_254,y_82/l_text:Roboto_37_normal:Stats:/co_rgb:000000,e_colorize,fl_layer_apply,g_north_west,x_316,y_93/l_text:Roboto_19_normal:Flowers%20Pollinated%20:%20' + gamerProfile.stats.pollinated + '/co_rgb:000000,e_colorize,fl_layer_apply,g_north_west,x_266,y_141/l_text:Roboto_19_normal:People%20Chased%20:%20' + gamerProfile.stats.chased + '/co_rgb:000000,e_colorize,fl_layer_apply,g_north_west,x_266,y_167/l_text:Roboto_55_normal:' + encodeURIComponent( + '/co_rgb:' + gamerProfile.colors.light + ',e_colorize,fl_layer_apply,g_north_west,x_52,y_314/l_text:Roboto_31_normal:Rank%20:%20' + gamerProfile.rank + '/co_rgb:' + gamerProfile.colors.light + ',e_colorize,fl_layer_apply,g_north_west,x_170,y_380/h_119,l_pixel,w_119/co_rgb:' + gamerProfile.colors.badge +  ',e_colorize,fl_layer_apply,g_north_west,r_59,x_295,y_194/l_text:Roboto_42_normal:%3C' + gamerProfile.rank + '%3E/co_rgb:000000,e_colorize,fl_layer_apply,g_north_west,x_308,y_237/sample';
var buzzyGamerProfile = {
	name : 'Buzzy McBuzzer',
	rank : 10,
	stats : {
		pollinated : 20,
		chased : 25
	profileImageId : 'profilepicture',
	colors : {
		dark : '2744A6',
		light : 'ffffff',
		badge : 'c8c61f'
var buzzyGamerBadgeImageSrc = getGamerBadge(buzzyGamerProfile);

More information:

I am currently working on a tool related to all of these features, but in the mean time, here are some additional resources to check out if you are interested in the power-user features of Cloudinary transformations:

Leave a Reply

Your email address will not be published.