Reputation: 23799
Is there an efficient way of detecting if a jpeg file is corrupted?
Background info:
solutions needs to work from within a php script
the jpeg files are on disk
manual checking is no option (user uploaded data)
I know that imagecreatefromjpeg(string $filename);
can do it. But it is quite slow at doing so.
Does anybody know a faster/more efficient solutions?
Upvotes: 21
Views: 17139
Reputation: 3044
Just a small note- how to get jpeginfo for Windows (64 bit)? There are no win32/win64 binaries on author's github but you can do this:
1) grab jpeginfo.exe
from this archive:
https://github.com/MoserMichael/cstuff/raw/master/img-archive/img-archive.zip
2) grab cygwin1.dll
from this archive:
ftp://mirror.internode.on.net/pub/cygwin/x86/release/cygwin64/cygwin64-2.6.0-1.tar.xz
Test it from commandline if it works: jpeginfo --help
. If there is info- it works just fine.
How to test jpeginfo output?
jpeginfo
returns 0 if the file is ok but it returns 1 not only when it's not but also when it found something it doesn't understand. Then it generates a message like this:
Warning: unknown JFIF revision number 2.01 1280 x 720 24bit JFIF N 122550 [WARNING]
On corrupted files it returns 1 and message like this:
1328 x 2048 24bit JFIF N 1310080 Premature end of JPEG file [WARNING]
Therefore you might want to test the actual output not only return code.
Upvotes: 1
Reputation: 1
Please try it
<?php
$img = $_GET['img'];
$str_exec = 'jpeginfo -c /chroot/home/www/html/media/'.$img;
$result = exec($str_exec);
if(strpos($result, 'ERROR'))
{
echo 'ERROR';
}
else
{
echo 'OK';
}
?>
Upvotes: 0
Reputation: 191
I have an other solution with a simply getimagesize()
if(!getimagesize($image_url)) echo 'Image is corrupt or not readable';
Upvotes: -3
Reputation: 497
FYI -- I've used the method above (jpeg_file_is_complete
) to test JPEGs which I know are corrupt (when I load them in a browser, for example, the bottom is gray -- i.e., the image is "cut off"). Anyhow, when I ran the above test on that image it DID NOT detect it as corrupt.
So far, using imagecreatefromjpeg()
works, but is not very fast. I found that using jpeginfo
works as well to detect these types of corrupt images, and is FASTER than imagecreatefromjpeg
(I ran a benchmark in my PHP using microtime()
).
Upvotes: 7
Reputation: 33
Solution:
I found the perfect tool for what I needed:
Searches recursively through a directory and finds any corrupted JPEGS. Looks like you can use as many CPUs as you like to do it also.
Worked for me.
Upvotes: -1
Reputation: 349
My simplest (and fastest) solution:
function jpeg_file_is_complete($path) {
if (!is_resource($file = fopen($path, 'rb'))) {
return FALSE;
}
// check for the existence of the EOI segment header at the end of the file
if (0 !== fseek($file, -2, SEEK_END) || "\xFF\xD9" !== fread($file, 2)) {
fclose($file);
return FALSE;
}
fclose($file);
return TRUE;
}
function jpeg_file_is_corrupted($path) {
return !jpeg_file_is_complete($path);
}
Note: This only detects a corrupted file structure, but does NOT detect corrupted image data.
Upvotes: 9
Reputation: 38940
You may also try to generate file hash based on MD5 and use it as checksum to validate JPEG data on various steps. For example, after read from file, then after transfer, etc.
Upvotes: -1
Reputation: 36702
From the command line you can use jpeginfo to find out if a jpeg file is OK or not.
$ jpeginfo -c test.jpeg
test.jpeg 260 x 264 24bit JFIF N 15332 [OK]
It should be trivial to call jpeginfo from php.
Upvotes: 18