The text was rotated using CSS3 Transforms, with alternate CSS for older IE using the IE Transform Translator. Original photo by Emilian Robert Vicol clipped with polyClip.js

There have been many times I have come across the need to take an image and cut an irregular shape out of it. Normally, when a developer comes across this requirement, the only thing to do is to open the image up with your favorite graphics editor, use the select tool to cut out the shape you want, and then save the result as a PNG, since it is the only image format used by all web browsers that support alpha channels. The problem is that PNG images, while compressed, are not as small as JPEGs if the source image is a photograph, and the download time of a page can balloon to unacceptable levels if there are many of these types of image on a page. When I first came across this problem, I didn’t think there was an obvious solution, but after a lot of thought, I created a library that uses HTML5 canvas to clip a JPEG (or any other image for that matter). The library also supports older versions of IE (7-8) using the Excanvas JavaScript library which polyfills canvas using VML.
Okay, How Can I Do The Same Thing?
- Download my script from github (It includes jQuery 1.6.4 and excanvas release 3. It should work with later versions — if it doesn’t, please let me know and I’ll fix it ;-) ) .
- Include them into the head of your document.
<script src="/path/to/js/jquery-1.6.2.min.js"></script> <!--[if lt IE 9 ]> <script src="/path/to/js/excanvas/excanvas.compiled.js"></script> <![endif]--> <script src="/path/to/js/polyClip-p.js"></script>
- Layout your page as normal, placing
imgtags where you want the clipped images to go:
<div class="clipParent"> <img src="images/image.jpg" /> </div>
Note the
divtag with the class ofclipParent. You must surround all the image tags withdata-polyclipattributes set one. This is so you can style the image correctly, since the library will remove the image tag and replace it with acanvaselement. - For every image on your page that you want to clip, calculate the points of the shape you want to cut out of the image and place them in the
data-polyclipattribute. For example, let’s say you have the following shape you want to cut out of a photograph:
(487, 4)(500, 239)(19, 239)(43, 195)You would then just set the
data-polyclipattribute to those points:<img src="image.jpg" data-polyclip="487, 4, 500, 239, 19, 239, 43, 195" />Note that the point co-ordinates are comma delimited. If you don’t want to calculate these numbers by hand, you can use your favorite imagemap generation tool to do generate the list of coordinates. Just remember to take the coordinates out of the imagemap code and stick it in the
data-polyclipattribute (for the examples on this page, I used the on-line tool available at image-maps.com).
Why Should I Do This Instead of Using a PNG?
Compare the image above with a PNG clipped with the GIMP. Even when I compressed the PNG with my PNG optimization script, the 191K PNG file is huge compared to it’s tiny 18K polyclipped JPEG analogue (Note: file sizes refer to the size of the full image as displayed at the top of this article):
| JPG using polyClip.js (18K) | PNG (191K) |
|---|---|
![]() |
|
You may ask whether the amount of JavaScript used in this solution is greater than the bandwidth saved by using JPEG compression. Not including jQuery, the amount of JavaScript clocks in at 2K or 13K, depending on the browser used (2K for the compressed polyClip script and 11K for excanvas, which will only be loaded by IE7-8). Although jQuery adds 91K to this equation, it doesn’t matter that much to me personally since I am probably using it for other parts of my page anyways. Even with jQuery, the amount of JavaScript downloaded outweighs using a PNG, especially if your are clipping a larger image or a huge amount of smaller images.
Download the latest version of polyClip.js from github.
A Few Caveats
- In IE7 and 8, the image may appear briefly as a black outline before the image appears. Other than that, it looks about the same as the other browsers.
- The image does not show up correctly in Opera Mini. Then again, a lot of things (e.g. CSS3 text-shadows, CSS3 Transforms, etc.) don’t show up correctly in Opera Mini. :-)


8 responses so far
1
Tonttu
// Nov 1, 2011 at 9:05 am
Very nice! Is there a plugin for GIMP/Photoshop to get the coordinates of selection edges automatically?
2
zoltan
// Nov 1, 2011 at 10:27 am
@Tonttu: The syntax for the coordinates are the same as the format used for HTML imagemaps. The GIMP has an Image Map tool built in and its user manual has an excellent tutorial on how to use it. Photoshop apparently has a built-in image-map tool as well, but I have never used it. If anyone tries it, please let me know if it works or not. :-)
3
Tonttu
// Nov 2, 2011 at 6:18 am
Your technique is so novel that an automated/semi-automated tool does not yet exist. Before your script there has not been a need for generating image map coordinates based on selection edges. This non-existing tool should generate the coordinates with a definable density and also allow for manual adding of coordinate nodes. Hmm.. nodes.. this gives me an idea: maybe vector graphics nodes could be converted to coordinates?
4
zoltan
// Nov 3, 2011 at 5:11 pm
@Tonttu: I am not sure, but I don’t think you understood what I meant by getting coordinates with the gimp. In the GIMP’s Image Map tool, you can select points using a polygon tool. I will add instructions on how to get these coordinates to this post in the next few days.
5
Nicholas
// Nov 15, 2011 at 5:57 am
Thank You for sharing – and for pushing the boundaries! I have just made a site for which i need to somehow compress 700kb pngs. This solution comes in very handy.
6
zoltan
// Nov 17, 2011 at 11:21 pm
@Nicholas: Cool! Any chance on seeing it in action?
7
fernando
// Jan 4, 2012 at 7:12 am
There’s a way to calculate the image co-ordinates if you have Illustrator installed. You can create an image map (via attributes palette), then export the code and take the co-ordinates from there. Haven’t tried it with polyclip.js though, but I will do it on my next project.
Thanks for sharing – fantastic tool!
Give Feedback
Don't be shy! Give feedback and join the discussion.