A reader asked me if it was possible to watermark images (like those taken with a camera) in PhoneGap. This is rather trivial using Canvas (hey, it does have a use!) so I whipped up the following example to demonstrate it in action.
First - let's look at the code. It's short enough to show all at once:
The UI for the application is just a header and a button. I've got the button initially disabled as I need to ensure some resources load before you start taking pictures.
Looking at the JavaScript code, you can see that I've created a canvas instance from the DOM and have created a watermark image. When it loads, I'm ready to watermark so I enable the button.
The button's touchstart event ties in to the PhoneGap Camera API to trigger the device to create a new picture. I could allow for gallery photos as well or make use of images from the web.
Once you take a picture, it's a trivial matter then to load it into an image object and copy it onto the canvas. Note that I place the watermark in the lower right hand corner of the image. That's where most watermarks seem to go so I did the same.
Here's a quick example. Forgive the horrible quality of the Xoom camera.

You can do anything you want with the image now, including getting the bits and uploading it to a server.
Archived Comments
haha..canvas does have a use case! Nice work! Looking forward to testing this out. Thanks for sharing.
Nice work!
Thanks again for your help !
Looking forward to see this example in your next book on PhoneGap/Cordova... ;-)
We may incorporate taking pictures and watermarking them in the trucking co app.....
"Trucking Co App".... I bet that app is being built by an awesome, and handsome, developer!
Hello Raymond, I've been reading a lot of your entries lately [ google always sends me to you ;) ] and they have been very helpful.
I am using your code snippet above,
but I can't figure out how to get the code to display the full picture taken from the camera (or chosen from photo library) it always just displays a part of the image and often it stretches it. I took out targetWidth and targetHeight and changed #myCanvas size but it still does not display the image correctly, can you help me?
I am using an iPhone4S and Cordova 3
For example I take this photo: http://i.imgur.com/gKlKynL.jpg
and this gets displayed: http://i.imgur.com/h2az6kt.png
Its not even the right direction, any Idea?
Odd. Add a new image to the html, just something like <img id="ray">. Then in the success function above, set ray's src to picuri. Tell me if the image there is ok.
Dear Raymond, I'm not a programmer, just using phonegap for fun, so not familiar with code, can you please describe how to get the full image from camera and set the watermark's size? Thank you.
While you don't necessarily have to be a "programmer", in the formal sense, I do not recommend trying to use my code if you know *nothing* about code. I wouldn't recommend doing anything with PhoneGap really. I'd take the time to learn JavaScript basics at a minimum just so you are at least able to read the code and see what it is doing.
That being said: To get the original full size image, you remove the targetWidth/Height stuff from the call. That tells to code to NOT resize it. As for the watermark, I think you would need to create it the size you want. drawImage doesn't let you resize, it just specifies where on the canvas it goes.
Thanks for the respond, actually I tried all, removing target's dimensions, changing/adding canvas size, changing/adding watermark's size, etc. No effect, just cropped image. Your idea with additional img id=ray is working, script shows full image, but of course without watermark. I created an easy app for iPad using phonegap via adobe creative cloud, nothing interesting, just photo gallery, so I find your idea with "picture in picture" very interesting, it can be used to show photograph from the gallery on the wall in real apartments. Maybe you know the complete script which allow to insert picture in picture? Regards, A.
perhaps I found a solution, it is necessary to specify canvasDom size, it's working now, thank you!
img.onload = function(e) {
canvasDom.width=2048;
canvasDom.height=1536;
canvas.drawImage(img,0,0);
canvas.drawImage(watermark, canvasDom.width-watermark.width, canvasDom.height-watermark.height);
}
Oh nice - thanks for sharing!
hi,
This code is not working.Also,not capturing image....
When you checked the console, what did you see?
Hi,
Its showing like below..
Watermark test
button- not working---you have disabled in your code...
Hi,
I have changed rk.png to Capture.png image...Still not working...
Thanks,
Hi,
this is the code that im using...
<head>
<script src="cordova-1.7.0.js"></script>
<script src="jquery.min.js"></script>
<script>
var watermark;
var canvasDom;
var canvas;
function init() {
document.addEventListener("deviceready", startUp, false);
}
function startUp() {
canvasDom = $("#myCanvas")[0];
canvas = canvasDom.getContext("2d");
//Create a watermark image object
watermark = new Image();
watermark.src = "Capture.png";
watermark.onload = function(e) {
//you can only take pictures once this is loaded...
$("#takePictureButton").removeAttr("disabled");
}
$("#takePictureButton").on("touchstart", function(e) {
navigator.camera.getPicture(camSuccess, camError, {quality: 75, targetWidth: 400, targetHeight: 400, destinationType: Camera.DestinationType.FILE_URI});
});
function camError(e) {
console.log("Camera Error");
console.log(JSON.stringify(e));
}
function camSuccess(picuri) {
console.log("Camera Success");
var img = new Image();
img.src=picuri;
img.onload = function(e) {
canvas.drawImage(img, 0, 0);
canvas.drawImage(watermark, canvasDom.width-watermark.width, canvasDom.height - watermark.height);
}
}
}
</script>
<style>
#myCanvas {
width: 400px;
height: 400px;
}
</style>
</head>
<body onload="init()">
<h1>Watermark Test</h1>
<button id="takePictureButton" disabled>Take a Picture</button>
<p/>
<canvas id="myCanvas"></canvas>
</body>
</html>
Please do not post large code samples here. Instead, use a Pastebin or similar link.
You did not say if you saw an error in the console. Did you try that?
Hello sir,
I don't see any error here.but image is not loading.I have placed image in www directory.My image name is Capture.
Thanks,
I'd start with some basic debugging then. For example, ensure the watermark is loading by adding a console.log message as the first line in watermark.onload.
No sir,its not loading.........
If you didn't use the same file name as me, then obviously you would need to change the src to match. When you test w/ your debug tools, you can also look at the Network panel to see how/if the request fails.
Hi all
How can you then make the picture preview fit the mobile screen size of any suitable mobile phone?
Many THX
You could use CSS: width: 100%;
You see I was having troubles trying to get the captured picture to take up the width and height of the screen AND my watermark aligning exactly in the bottom right. For some reason my watermark goes beyond the bottom of the picture.
What would be ideal is some idea on how to move the watermark using the javascript with corresponding css.
Incidentally I'm using the window.InnerWidth parameter for the CanvasDom size and targetWidth/Height size. The point being that the sample picture should ideally fit within all reasonable mobile screen resolutions. MyCanvas CSS width/height is set to 100%
Its also hard to understand the relationship between the canvasDom size and the targetWidth size.
The only other thing this brilliant tutorial needs is a button to save the picture with watermark to internal storage.
I know I've seen - somewhere - a Canvas to filesystem example for Cordova/PhoneGap. I don't have the URL handy, but I bet you could Google for it.
Thanks, it works, but now, Do you know how to store the picture with the watermark in the cellphone?
Check out the File plugin. It gives file system access.
I store regular camera pictures with this "entry.moveTo(parentEntry, myroute);", but it doesn't work with the canvas or the image, could you please give me a hint of which function should i use?. I'm reading this documentation page: http://docs.phonegap.com/en...
You need to get the binary data from the <canvas> element. I found a plugin to make it even easier: https://github.com/devgeeks...
Thank you very much, I will check it!