Creating watermarked images in PhoneGap

This post is more than 2 years old.

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.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by J Haag posted on 5/22/2012 at 7:08 PM

haha..canvas does have a use case! Nice work! Looking forward to testing this out. Thanks for sharing.

Comment 2 by WilFlo13 posted on 5/22/2012 at 7:16 PM

Nice work!
Thanks again for your help !

Looking forward to see this example in your next book on PhoneGap/Cordova... ;-)

Comment 3 by John Walker posted on 5/22/2012 at 9:59 PM

We may incorporate taking pictures and watermarking them in the trucking co app.....

Comment 4 by Raymond Camden posted on 5/22/2012 at 10:16 PM

"Trucking Co App".... I bet that app is being built by an awesome, and handsome, developer!

Comment 5 by einKorken posted on 12/29/2013 at 4:01 AM

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

Comment 6 by einKorken posted on 12/29/2013 at 5:07 AM

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?

Comment 7 by Raymond Camden posted on 12/29/2013 at 7:35 PM

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.

Comment 8 by andrew posted on 5/10/2014 at 3:46 AM

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.

Comment 9 by Raymond Camden posted on 5/11/2014 at 4:10 PM

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.

Comment 10 by andrew posted on 5/12/2014 at 2:57 AM

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.

Comment 11 by andrew posted on 5/12/2014 at 4:03 AM

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);
}

Comment 12 by Raymond Camden posted on 5/12/2014 at 5:13 AM

Oh nice - thanks for sharing!

Comment 13 by dev posted on 7/8/2014 at 9:56 AM

hi,
This code is not working.Also,not capturing image....

Comment 14 by Raymond Camden posted on 7/8/2014 at 3:39 PM

When you checked the console, what did you see?

Comment 15 by dev posted on 7/8/2014 at 5:27 PM

Hi,
Its showing like below..
Watermark test
button- not working---you have disabled in your code...

Comment 16 by dev posted on 7/8/2014 at 5:31 PM

Hi,
I have changed rk.png to Capture.png image...Still not working...
Thanks,

Comment 17 by dev posted on 7/8/2014 at 5:34 PM

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>

Comment 18 by Raymond Camden posted on 7/9/2014 at 5:24 AM

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?

Comment 19 by dev posted on 7/9/2014 at 9:09 AM

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,

Comment 20 by Raymond Camden posted on 7/9/2014 at 3:35 PM

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.

Comment 21 by dev posted on 7/9/2014 at 5:01 PM

No sir,its not loading.........

Comment 22 by Raymond Camden posted on 7/9/2014 at 6:14 PM

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.

Comment 23 (In reply to #11) by Hax posted on 9/15/2015 at 3:02 AM

Hi all

How can you then make the picture preview fit the mobile screen size of any suitable mobile phone?

Many THX

Comment 24 (In reply to #23) by Raymond Camden posted on 9/15/2015 at 1:06 PM

You could use CSS: width: 100%;

Comment 25 (In reply to #24) by Hax posted on 9/17/2015 at 3:21 AM

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.

Comment 26 (In reply to #25) by Raymond Camden posted on 9/17/2015 at 1:25 PM

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.

Comment 27 by Luis Zapata posted on 6/1/2016 at 8:17 PM

Thanks, it works, but now, Do you know how to store the picture with the watermark in the cellphone?

Comment 28 (In reply to #27) by Raymond Camden posted on 6/1/2016 at 8:20 PM

Check out the File plugin. It gives file system access.

Comment 29 (In reply to #28) by Luis Zapata posted on 6/1/2016 at 8:27 PM

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...

Comment 30 (In reply to #29) by Raymond Camden posted on 6/1/2016 at 8:28 PM

You need to get the binary data from the <canvas> element. I found a plugin to make it even easier: https://github.com/devgeeks...

Comment 31 (In reply to #30) by Luis Zapata posted on 6/1/2016 at 8:33 PM

Thank you very much, I will check it!