Эффективно обнаружить поврежденный файл jpeg?

Есть ли эффективный способ обнаружения, если файл jpeg поврежден?

Справочная информация:
  решения должны работать изнутри PHP скрипт
  файлы jpeg находятся на диске
  ручная проверка не является опцией (загруженные пользователем данные)

Я знаю, что imagecreatefromjpeg(string $filename); может это сделать. Но это довольно медленно при этом.

Кто-нибудь знает более быстрые/более эффективные решения?

Ответ 1

В командной строке вы можете использовать jpeginfo, чтобы узнать, есть ли файл jpeg в порядке или нет.

$jpeginfo -c test.jpeg

test.jpeg 260 x 264 24bit JFIF N 15332 [OK]

Это должно быть тривиально вызывать jpeginfo из php.

Ответ 2

Мое самое простое (и самое быстрое) решение:


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);
}

Примечание. Это обнаруживает поврежденную структуру файла, но НЕ обнаруживает поврежденные данные изображения.

Ответ 3

FYI - я использовал метод выше (jpeg_file_is_complete) для проверки JPEG файлов, которые, как я знаю, повреждены (когда я загружаю их в браузере, для Например, дно серого цвета - т.е. изображение "обрезано" ). Во всяком случае, когда я выполнил вышеуказанный тест на этом изображении, он НЕ обнаружил его как поврежденный.

Пока использование imagecreatefromjpeg() работает, но не очень быстро. Я обнаружил, что использование jpeginfo также работает для обнаружения этих типов поврежденных изображений и является более быстрым, чем imagecreatefromjpeg (я провел тест на моем PHP с помощью microtime()).

Ответ 4

Пожалуйста, попробуйте

<?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';
}
?>

Ответ 5

Просто небольшое примечание - как получить jpeginfo для Windows (64 бит)? Для автора github нет двоичных файлов win32/win64, но вы можете сделать это:

1) возьмите jpeginfo.exe из этого архива: https://github.com/MoserMichael/cstuff/raw/master/img-archive/img-archive.zip

2) возьмите cygwin1.dll из этого архива: ftp://mirror.internode.on.net/pub/cygwin/x86/release/cygwin64/cygwin64-2.6.0-1.tar.xz

Протестируйте его из командной строки, если он работает: jpeginfo --help. Если есть информация, она работает нормально.

Как проверить выход jpeginfo?

jpeginfo возвращает 0, если файл в порядке, но он возвращает 1 не только тогда, когда он не был, но и когда он обнаружил что-то, что он не понимает. Затем он генерирует такое сообщение:

Warning: unknown JFIF revision number 2.01 1280 x 720 24bit JFIF N 122550 [WARNING]

В поврежденных файлах он возвращает 1 и сообщение вроде этого:

1328 x 2048 24bit JFIF N 1310080 Premature end of JPEG file [WARNING]

Поэтому вы можете проверить фактический вывод не только кода возврата.

Ответ 6

Вы также можете попытаться создать хэш файла на основе MD5 и использовать его в качестве контрольной суммы для проверки данных JPEG на разных этапах. Например, после чтения из файла, затем после передачи и т.д.

Ответ 7

Решение:

Я нашел идеальный инструмент для того, что мне нужно:

http://www.thomasbarker.co.uk/2011/05/29/corrupt-jpeg-checkertool-for-finding-corrupt-jpeg-image-files/

Искажает рекурсивно через каталог и находит поврежденные JPEGS. Похоже, вы можете использовать столько процессоров, сколько захотите.

Работал для меня.

Ответ 8

У меня есть другое решение с просто getimagesize()

if(!getimagesize($image_url)) echo 'Image is corrupt or not readable';