admin管理员组

文章数量:1400668

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 puter?**

Now that's the basic idea.. Users don't have the original file name so can't access 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 bination 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 the clipboard on an interval or some action, but this is annoying 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...

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 puter?**

Now that's the basic idea.. Users don't have the original file name so can't access 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 bination 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 the clipboard on an interval or some action, but this is annoying 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...

Share Improve this question edited May 31, 2023 at 2:20 Daniel Bellmas 6577 silver badges19 bronze badges asked Sep 18, 2013 at 11:23 Vincent DuprezVincent Duprez 3,8829 gold badges38 silver badges81 bronze badges 8
  • 10 Add a watermark, you can't stop a user from getting the picture off the site. – Patsy Issa Commented Sep 18, 2013 at 11:25
  • 2 There's no reliable way to protect images. If the image is displayed in a browser you can copy it. You can make it a bit more difficult, but it's always going to be possible. – Oiva Eskola Commented Sep 18, 2013 at 11:26
  • 7 Watermarks and other deliberate artifacts are really the only option. If somebody can see the picture, they can copy the picture. No matter what efforts you put into your code, they can always just take a screenshot. – David Commented Sep 18, 2013 at 11:26
  • 2 Use lower res images with watermarks for the samples. When they purchase the images they get the full resolution image. – Gary Hayes Commented Sep 18, 2013 at 11:28
  • 6 (Related anecdote)... I was once consulting for a pany which handled medical data, and they wanted a system similar to this. Users should be able to see documents and other data, but shouldn't be able to copy it. (Not a website, a smart client app, so different technologies.) They contracted another firm for that part, spent 7 figures on a solution, and were very proud with what they had. While demoing it, I took out my phone and took a picture of the screen. Data... copied. They didn't like that. – David Commented Sep 18, 2013 at 11:29
 |  Show 3 more ments

6 Answers 6

Reset to default 3

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 pletely transparent. When you bine 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 bine 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.

本文标签: javascriptprotect images from being copiedStack Overflow