Our server is saving EXIF data to every file saved with imagejpeg()
. As far as I know, this is not the default behavior (or even possible, from what I’ve read). But, it is occurring, and due to the FileDateTime
information being included (and using the time
of save), it is breaking functionality in our upload/approval system (md5_file()
returns a different value for the exact same image due to FileDateTime
always being different).
Is there a way to prevent imagejpeg()
from saving EXIF data for images by default?
Server Information
- CentOS 5
- Parallels Plesk Panel 10.4.4
- GD Version: bundled (2.0.34 compatible)
- PHP 5.3
Code
<?php
public function upload_book_cover($book, $cover, $filename = NULL, $approved = NULL){
global $c_consummo, $user;
$approved = bool($approved, true, true);
if(filesize($cover)>5242880){
return false; // Too large;
}
$max_width = 450;
$cover_info = getimagesize($cover);
if(!$this->is_valid_book_cover_type($cover_info['mime'])){
return false; // Invalid image type
}
$width = $cover_info[0];
$height = $cover_info[1];
if($width<200){
return false; // Too small
} elseif($width>1500){
return false; // Too wide
}
$original_cover = false;
switch($cover_info[2]){
case IMAGETYPE_GIF:
$original_cover = imagecreatefromgif($cover);
break;
case IMAGETYPE_JPEG:
$original_cover = imagecreatefromjpeg($cover);
break;
case IMAGETYPE_PNG:
$original_cover = imagecreatefrompng($cover);
break;
case IMAGETYPE_BMP:
$original_cover = imagecreatefrombmp($cover);
break;
}
if(!$original_cover){
return false; // Unsupported type
}
if($width>$max_width){
$new_width = $max_width;
} else {
$new_width = $width;
}
$new_height = round($height*($new_width/$width));
$new_cover = imagecreatetruecolor($new_width, $new_height);
if(!$new_cover){
return false; // Could not create true color image
}
if(!imagecopyresampled($new_cover, $original_cover, 0, 0, 0, 0, $new_width, $new_height, $width, $height)){
return false; // Could not copy image
}
if(!imagejpeg($new_cover, $cover, 100)){
return false; // Image could not be saved to tmp file
// This is adding *new* EXIF data to images by itself
}
$file_hash = md5_file($cover);
$duplicate_book_cover = $this->find_duplicate_book_cover($book, $file_hash);
if($duplicate_book_cover){
return $duplicate_book_cover;
}
$file_id = $c_consummo->upload_file($cover, $filename);
...
}
10
Answers
You could possibly convert the
jpeg
to agif
first, then convert thegif
back to ajpeg
. In doing so, my understanding is that you would destroy the EXIF data. It’s a hack, but it should work.You could try using
imagecreatefromjpeg
on the image created withimagejpeg
and replacing with the newly created one.$res = imagecreatefromjpeg($filename)
to load the image, thenimagejpeg($res, $filename, QUALITY)
to rerender it.You can use imagemagick too:
It looks like you have tried several things here, but lets try one more.
Do you EVER need EXIF information in your application?
If not lets take out support for EXIF and see if that completely removes it.
If it does not remove it, then perhaps the functions are reading it from the existing photos and then just blindly including it in the file that is written.
You can know for sure by printing out the EXIF information at each step of process
No idea why EXIF data is being written – so the following may help you remove it.
One suggestion is to run something as a command on the server – it will need some installation: http://hacktux.com/read/remove/exif – then run throuhg EXEC from PHP.
There’s also solution posted here that uses ImageMagick if you also have that installed (or cen get it installed: Remove EXIF data from JPG using PHP (but note warning about colour)
Otherwise, the other suggestion is as above, try turning off the EXIT extension.
Sorry if they don’t help, but you did ask for any suggestions.
Read this, maybe it will help:
http://www.php.net/manual/en/function.imagecreatefromjpeg.php#65656
and this:
http://www.sentex.net/~mwandel/jhead/usage.html
The only thing that spring to mind is, that you could ignore the EXIF data and just make your hash from something else? My suggestion would be to try either hashing the raw output without saving to a file (here outputting in gif format -which makes a smaller, 8-bit image for performance- to an output buffer and hashing the buffer content)
Or you could build a string containing only the pixel information and hash that (here done by accessing each pixel and appending its value to a string, in reverse for performance)
For performance, you could also choose only to take samples from the image, as this should work just as well or maybe even better (here sampling every 5th pixel of every 5th row)
I hope some of this will work (as I can’t test it right now) or at least will help you find the way that works for you 🙂
This is a bit of a hack, but it will work, just do this after your
switch()
statement:GD will strip any EXIF data out, as it doesn’t support it.
Try to disable globally EXIF functionality by recompiling PHP without this option.
Apparently, GD doesn’t like when the path to the input / output file is the same, but the credit isn’t mine. To fix, use a new (tmp) file to save the newly created image to: