简体   繁体   中英

protect images from being copied

Im looking for reliable solutions to protect images from being copied.. My customer (photographer) would like to avoid customers copying her pictures without buying them.

I was thinking about mixing these techniques:


PHP self-made expiration

images are loaded from a php script reading from the image file, in the request I bundle the request timestamp and filename. if the timestamp is very close to the actual timestamp (both timestamps are generated on the same server, so no time config issues) the request is created on page generation. For example: in the generated html, I have some img tag like:

So when the users wants to copy the image source from source code, the image.php script won't answer as there is a delay between page generation and image request...

No caching

If I send a No cache header, I suppose the browser doesn't caches/stores the file on the client computer?


Now that's the basic idea.. Users don't have the original file name so can't acces them directly.. With this solution, I can even watermark them on the fly or resize them

Users could still print screen them, there are 2 types of printscreens, those that put them in the clipboard, and those that save a file.

Would there be a solution, I was thinking about some sort of javascript side onkeydown and detecting the printscreen touch, or shift+alt+cmd+[1-4] on mac cobination and blank out imagesbefore any action is taken.. is this possible, more or less reliable and how?

Another partial idea I had was to clear clipboard on an interval or some action, but this is annoyinng for people, doesn't work for desktop saved screen captures and maybe doesn't works on all browsers.

any other idea?

So where to go from here? This is a practical question, I know people could take a picture of their screen after all or use a hdmi cable to capturing device.. but seriously, this is overkill, no one will do this for such pictures, we're not talking about top secret classified documents...

Anything displayed can be captured. All solutions are from server side: adding a watermark, or using small low-resolution images for display.

The general rule of thumb is: If it can be accessed with a browser, the user already has full access to it and can take it if they wish to do so. Example options:

Option 1:

Prevent right clicking via JavaScript.

Won't work when user:

  • Disables JavaScript and refreshes the page.
  • Uses a screenshot tool.
  • Manually inspects your HTML and finds the img src.

Option 2:

Put image as the background image of a div.

Won't work when user:

  • Uses a screenshot tool.
  • Manually inspects your HTML/CSS and finds the img src.

Option 3:

Use a watermark and/or a low res image.

Probably the best approach here. If your client is a photographer that wants to protect his/her work, displaying a low-res image and providing an option/link to purchase the hi-res version may be the best course of action. Adding a watermark may also dissuade visitors from taking the image free-of-charge as nobody wants to frame a picture that has a photographer's logo across the middle.

  1. photographer mostly doing high quality pictures, so why not show on the web site low quality images and write on them "Demo" or something.
  2. use flash to prevent from the users copy them.
  3. encode your images into base64 and show them with canvas or svg.

There is no 100% protection..

The client always can make for example a Screenshot from the image. Or can get the Link to the image with the browser's code-inspector.

Add a watermark is the best solution.

So this is my implementation:

First when calling an image during a page generation in php:

$reqinfo['id'] = $data[id];
$reqinfo['maxsize'] = 320;
$reqinfo['timestamp'] = time();
$reqinfo['base'] = false;

$encoded = base64_encode(openssl_encrypt(serialize($reqinfo), 'AES-128-CBC', 'martine',0,'fgrgfvcfghtfdrfg'));

echo'<div class="imagecontainer"><img src="photo.php?info='.$encoded.'" /></div>'; 

This already implement some restrictions in css and javascript on the imagecontainer class. I send the image ID (or name) the maximum width or height and the request timestamp, all this encrypted in a request string sent to photo.php base is ment to be true if image may bypass everything and be called like a plain image.

photo.php

<?
//request info
$reqinfo = unserialize(openssl_decrypt(base64_decode($_GET[info]), 'AES-128-CBC', 'martine',0,'fgrgfvcfghtfdrfg'));

//image expired
if(time() - $reqinfo[timestamp] > 10){ exit(); }

//public image
if($reqinfo[base] == true){ readfile('img/'.$reqinfo[id].'.jpg'); exit(); }

//header cache
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header('Content-type: image/jpeg');

//check cache existance and send out
if(file_exists( 'img/'.$reqinfo[id].'_'.$reqinfo[maxsize].'.jpg')) { readfile('img/'.$reqinfo[id].'_'.$reqinfo[maxsize].'.jpg'); exit(); }

//source Image
$image_path = 'img/'.$reqinfo[id].'.jpg';
list($original_width, $original_height)= getimagesize($image_path); 
$srcImage = imagecreatefromjpeg( $image_path );
$ratio = $original_height/$original_width;


//create destination image holder
$destination_width = $reqinfo['maxsize'];
if($destination_width < 1) $destination_width = 1;
if($destination_width > $original_width)$destination_width = $original_width;
$destination_height = round($destination_width*$ratio);
if ($destination_height > $reqinfo['maxsize'])
{
    $destination_height = $reqinfo['maxsize'];
    $destination_width = round($destination_height/$ratio);
}
$targetImage = imagecreatetruecolor( $destination_width, $destination_height );
imagealphablending($targetImage,true);

//resample copy logo
imagecopyresampled( $targetImage, $srcImage, 
0, 0, 
0, 0, 
$destination_width, $destination_height, 
$original_width, $original_height );


// watermark
$watermark = imagecreatefrompng('watermark.png');
imagesettile($targetImage, $watermark);
imagefilledrectangle($targetImage, 0, 0, $destination_width, $destination_height, IMG_COLOR_TILED);




//output
imagejpeg(  $targetImage, 'img/'.$reqinfo[id].'_'.$reqinfo[maxsize].'.jpg' );
imagejpeg(  $targetImage );
imagedestroy( $targetImage );


?>

'martine' is a simple passphrase img is obviously an non public path

Hope this is more or less clear, basically this (in order):

  • Decrypt the $reqinfo array
  • check if imagerequest is fresh, if a user copies the urls and loads in another frame, no image will be loaded.
  • Checks if the image can bypass resize and watermark and be sent to the browser
  • Checks if a cached version exists to speed up process
  • Recreates a resized version
  • Add a watermark
  • Saves a server cached version
  • sends out the 'disposable' image

Hope this can helps someone...

I've experimented with various techniques: 1 is to divide the image into multiple images-- think about dividing an image up into say 16 different PNGs. Each image showing say a 4x4 pixel or 10x10 pixel block of colored pixels, with 15 10x10 blocks being completely transparent. When you combine these images exactly on top of each other, the full image is displayed. Of course you can do it with only 2 images, or as many as you like. This will absolutely prevent someone from downloading the image.

Secondly, I've experimented with a similar technique, however, hiding and showing the images randomly, with most of them showing at any one time.. that way if someone screen captures it, it'll be only a part of the image. Due to "persistence of vision" you should be able to see the image normally IF the framerate was high enough.. but currently, it really doesn't work well.

Lastly, you can combine these techniques with CSS filters and altered colored images-- think, rotate the hue on the source image, and use a filter to rotate it back. You can get crazy with all kinds of filters and mix-blend-modes to craft a perfectly displayed image that cannot be downloaded and look anything like the original without reversing the technique.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM