7 апреля 2014 г.

Проверка валидности картинки на Python

Встала задачка проверить валидность скаченной картинки на питоне. Картинок много, способов тоже. Пошёл тестить.

Самый популярный способ по версии StackOverflow работает с PIL:
def test_pil(filename):
    from PIL import Image
    from cStringIO import StringIO
 
    try:
        file_data = StringIO(open(filename, 'rb').read())
        im = Image.open(file_data)
        im.verify()
        return (im.format == 'JPEG')
    except:
        return False

Отдельный код открытия файла - это конкретно мои требования, его можно и сразу PIL-ом открыть конечно.

Второй по популярности способ - через модуль imghdr специально предназначенный для анализа картинок:
def test_imghdr(filename):
    import imghdr
 
    try:
        fd = open(filename, 'rb').read()
        return (imghdr.what(None, fd) == 'jpeg')
    except:
        return False

Создал пару файлов valid.jpg и unvalid.jpg, прописал ассерты на правильную работу обоих функций
    assert test_imghdr('valid.jpg') and test_pil('valid.jpg')
    assert not test_imghdr('unvalid.jpg') and not test_pil('unvalid.jpg')
    assert not test_imghdr('notfound.jpg') and not test_pil('notfound.jpg')

notfound.jpg, как понятно, из названия имя несуществующего файла.

Обе функции работают корректно. Осталось сравнить их по скорости, поскольку картинок мне проверять много много миллионов (:
Для этого есть чудный модуль timeit
    print "test_imghdr %.2f" % timeit.timeit("test_imghdr('valid.jpg')", 
                                             setup="from __main__ import test_imghdr")
    print "test_pil %.2f"timeit.timeit("test_pil('valid.jpg')", 
                                           setup="from __main__ import test_pil")

По итогам теста выбрал не самый популярный способ =)


test_pil 84.40sec

test_imghdr 36.92sec

исходники

Комментариев нет: