I want to wrap an image around a cylindrical object like mugs in a web app, like so
This will likely be a base image (e.g. a jpeg image of a mug) containing a transformed image of a user uploaded image.
There seems to be a lot of resources on this in PhotoShop. However, this is of course not appropriate for web, mobile or server environments.
I also know this is possible, as a number of sites already do this extremely well. For example, Vista Print (see image), Asda Photos (and loads more on the internet by just searching personalised mugs on Google), using what seems to be just HTML5.
However, bizarley I cannot seem to find any answers for a Web App. There's a lot of questions on this in StackOverflow that are all unanswered like: Wrap an image around a cylinder, wrap image around a cylindrical cup using html 5 canvas and javascript, How overlay image over a cup using html5 canvas and many many more!
Therefore can someone please finally provide an answer to this question.
Simple cylinder wrap with Canvas 2D
Very simple example using sin and cos to create the curved map. The images is cut into strips approx 1 pixel wide then rendered as half a squashed circle. As perspective is a linear effect related to distance I also add a small amount of perspective by scaling up in the y direction depending on sin(angle) (where angle = 0 on the left Math.PI / 2 at the forward center).
These two demos are animated just to show that it is not a slow process, but compared to webGL it is a snail. If you use such a method, don't make it realtime or you will chew up the batteries of mobile devices. Realtime 3D should be done with webGL
Basic wrap
Add lighting.
To extend it a little further you can add overlays to do lighting. I could not find a public domain image of a white cup so I used the same function to render the lighting (A few simple gradients) onto and image. Then for the final output I render the overlay as a backing image, then the text, then two passes again with the shading image, first darken with "multiply", then a soft highlight with "lighten"