automating fake watermarks

To give one of our clients a moderate amount of security, I was asked to add a watermark facility to an ajax shoppingcart. For full security, it makes sense to edit the actual image, but for less pressing security, I had to come up with something clientside.

The trick I built is based on a small hack which gives basic security for images – overlay the image with a transparent image:

<img src="blank.gif" style="background:url(actual_image.jpg)" width="120" height="100" />

When a person right-clicks and saves the image, they actually get a blank image instead.

To extend on this, I was asked to use a watermark image instead of a blank image

Here is an example of the watermark (on a blue background to make it more clear):

Unfortunately, you cannot simply apply the same trick as before:

As you can see, the watermark stretches to fill the image with and height. What we actually want is for the watermark to be centered.

In Firefox, this is dead simple:

<img src="/wp-content/uploads/2006/06/watermark.gif" style="background:url(/wp-content/uploads/2006/06/beatles.jpg);padding:112px 138px" width="124" height="124" />

Unfortunately, that does not always work in IE (read: very rarely), as it ignores padding on images unless the browser is in “standards mode”.

A half-solution then for IE is this:

<span style="position:relative;padding:112px 138px;height:349px;background:url(original_image.jpg);">
  <img src="watermark.gif" width="124" height="124" />
</span>

That places the watermark in the right position, but you can get the background image by right-clicking and saving when the mouse is not directly above the watermark.

So, we need to use yet another level of hackery, and draft in the original blank image in yet another level of elements:

<span style="background:url(original_image.jpg);">
  <span style="position:relative;padding:112px 138px;height:349px;background:url(blank.gif);">
    <img src="watermark.gif" width="124" height="124" />
  </span>
</span>

FSCKing ugly!

Anyway, to automate this, I wrote this thing here:

if(vals.watermark&&!browser.isSafari){
	widget='<img src="'+vals.watermark+'" id="sc_counter_'+sc_counter+'" />';
	var img=new Image();
	img.id='sc_imageloader_'+sc_counter;
	img.callback='callback'+sc_counter;
	window['callback'+sc_counter]=new Function(
		"var el=$('sc_counter_"+sc_counter+"'),el2=$('sc_imageloader_"+sc_counter+"');"
		+"if(browser.isIE){"
			+"var el4=newEl('span');"
			+"el4.style.background='url(/i/blank.gif)';"
			+"el4.style.position='relative';"
			+"el4.style.height=el2.height;"
			+"el4.style.padding=((el2.height-el.height)/2)+'px '+((el2.width-el.width)/2)+'px';"
			+"var el3=newEl('span',0,0,el4);"
			+"el3.style.background='url("+vals.src+")';"
			+"el.parentNode.insertBefore(el3,el);"
			+"el4.appendChild(el)"
		+"}else{"
			+"el.style.background='url("+vals.src+")';"
			+"el.style.padding=((el2.height-el.height)/2)+'px '+((el2.width-el.width)/2)+'px';"
		+"}"
		+"delEl(el2);"
	);
	img.onload=function(){setTimeout("window."+this.callback+"();window."+this.callback+"=null;",1);}
	img.style.display='none';
	img.src=vals.src+'?'+sc_counter;
	document.body.appendChild(img);
}
else widget='<img src="'+vals.src+'" />';

The above is part of a HTML generation thing, which is then passed through a html2dom parser before being added to the document.

The code is basically told “draw an image img1, using image img2 as a watermark”. It must then work out all the widths and sizes itself.

You cannot simply leave out the width and height, as the image will end up being the size of the watermark, with only the top left of the actual image displaying. Therefore, we must work out what width and height to resize the image to.

To do that, we tell the browser to load the actual image, and set an “onload” on it to retroactively resize the watermarked version to the correct dimensions. You’ll note that I’ve told it to forget about the watermark in Safari’s case. That’s because Safari does not have an onload event for images.

A much simpler example of the above code (if I was allowed to tell IE to go screw itself šŸ˜‰ ) would have been this:

if(vals.watermark&&!browser.isSafari&&!browser.isIE){
	widget='<img src="'+vals.watermark+'" id="sc_counter_'+sc_counter+'" />';
	var img=new Image();
	img.onload=new Function(
		"var el=$('sc_counter_"+sc_counter+"');"
		+"el.style.background='url("+vals.src+")';"
		+"el.style.padding=((this.height-el.height)/2)+'px '+((this.width-el.width)/2)+'px';"
		+"delEl(this);"
	);
	img.style.display='none';
	img.src=vals.src;
}
else widget='<img src="'+vals.src+'" />';

2 Replies to “automating fake watermarks”

Comments are closed.