Как проверить, является ли файл действительным файлом изображения?

В настоящее время я использую PIL.

from PIL import Image
try:
    im=Image.open(filename)
    # do stuff
except IOError:
    # filename not an image file

Однако, хотя этого достаточно для большинства случаев, некоторые файлы изображений, такие как xcf, svg и psd, не обнаруживаются. Файлы Psd вызывают исключение OverflowError.

Могу ли я как-нибудь включить их?


person Sujoy    schedule 20.05.2009    source источник
comment
Что ж, я не знаю, как устроен psd, но я, конечно, знаю, что, по сути, svg не является файлом изображения как таковым, он основан на xml, поэтому, по сути, это простой текстовый файл.   -  person shylent    schedule 20.05.2009
comment
Закрывать дубликаты на разных языках не очень распространенная практика. Если вы не можете найти какие-либо другие вопросы Python с этим, оставьте его открытым, поскольку могут быть специфические для Python решения, которые люди хотят публиковать, но не попали в опубликованный вами вопрос.   -  person Paolo Bergantino    schedule 20.05.2009
comment
да, во-первых, я действительно надеялся на библиотеку python, о которой я не знал: P, а затем, как указал Бен, просто магические числа не проверяют все изображение.   -  person Sujoy    schedule 20.05.2009
comment
@Sujoy, проверка всего изображения практически невозможна, если у вас уже нет его копии, потому что компьютер не может определить разницу между правильным цветным пикселем и искаженным набором единиц и нулей, пока все элементы управления (магические числа) верны.   -  person DevinB    schedule 20.05.2009
comment
@devinb, согласен, я просто получу магические числа и покончим с этим, если кто-то другой не придумает что-то получше, чтобы вызвать рефакторинг :)   -  person Sujoy    schedule 20.05.2009
comment
xcf и psd на самом деле не являются изображениями, это файлы проектов, которые содержат (часто много) изображений ... вы, вероятно, могли бы привести аргументы в пользу svg.   -  person mgalgs    schedule 01.01.2014
comment
PIL может обнаруживать дефект / ошибки файла изображения, но вам необходимо выполнить хотя бы одну операцию манипулирования изображением, чтобы выявить несколько типов ошибок, например Я применил преобразование транспонирования PIL. Только загрузка, как вы предлагаете, иногда не позволяет обнаружить ошибки. Подробности в моем ответе ниже.   -  person Fabiano Tarlao    schedule 02.10.2019


Ответы (9)


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

person Brian R. Bondy    schedule 20.05.2009
comment
Этого будет недостаточно, если он действительно проверяет действительные изображения; наличие магического числа, например, не гарантирует, что файл не был усечен. - person Ben Blank; 20.05.2009
comment
отличный совет, теперь мне просто нужно выяснить, что это за числа. Благодарность :) - person Sujoy; 20.05.2009
comment
@ben, ой, я еще не думал об этом. это действительно хороший момент - person Sujoy; 20.05.2009
comment
@ Бен, как вы ожидаете, что библиотека сделает вывод, что файл был усечен? - person DevinB; 20.05.2009
comment
@ Бен Бланк: Верно, но зачастую лучше решить проблему на 99%, чем не решать ее вообще. - person Brian R. Bondy; 21.05.2009

Я только что нашел встроенный модуль imghdr. Из документации Python:

Модуль imghdr определяет тип изображения, содержащегося в файле или потоке байтов.

Вот как это работает:

>>> import imghdr
>>> imghdr.what('/tmp/bass')
'gif'

Использование модуля намного лучше, чем повторная реализация аналогичной функциональности

person Nadia Alramli    schedule 24.05.2009
comment
да, imghdr работает с большинством форматов изображений, но не со всеми. в соответствии с моей исходной проблемой с файлами svg, xcf и psd, ну, они также не обнаруживаются в imghdr - person Sujoy; 26.05.2009
comment
Да, но вместо того, чтобы изобретать велосипед, есть с чего начать. - person Nadia Alramli; 26.05.2009
comment
Например, вы можете отказаться от необнаруженных заголовков изображений. Если изображение не было обнаружено imghdr, вероятно, оно также не поддерживается PIL. Или вы можете начать с просмотра исходного кода imghdr и посмотреть, как он работает. - person Nadia Alramli; 26.05.2009
comment
Ваш ответ на самом деле лучше, спасибо. Как кто-то сказал выше ... но решить проблему на 99% лучше, чем не решать ее вообще .. - person RinkyPinku; 03.06.2015
comment
Стоит отметить: imghdr.what(path) возвращает None, если задано path не распознанный тип файла изображения. Список распознаваемых в настоящее время типов изображений: rgb, gif, pbm, pgm, ppm, tiff, rast < / i>, xbm, jpeg, bmp, png, webp, < я> exr. - person patryk.beza; 06.04.2016
comment
Я обнаружил, что иногда imghdr.what(path) возвращает None, даже если файл является допустимым изображением, особенно для jpeg. - person GuillaumeDufay; 02.01.2017
comment
Будь осторожен! Действительный hdr не означает действительное изображение (например, байты изображения могли быть зашифрованы!) - person Filippo Mazza; 30.11.2017
comment
В комментарии @FilippoMazza я могу подтвердить, что плохое изображение, которое было обрезано во время передачи, может пройти этот тест, но сломается, когда PIL попытается его прочитать. - person kevinmicke; 21.03.2018
comment
Просто попробовал, и это не удается для многих изображений .jpg. Я думаю, что в этой библиотеке есть ошибки (по состоянию на 2019 год). - person Logic1; 14.08.2019
comment
@ Logic1, не могли бы вы предоставить образцы в Интернете? - person Massimo; 13.12.2019
comment
Вот один пример, в котором imghdr не удается проверить тип изображения (JPEG), есть ли еще кто-нибудь, кто получает тот же результат? По умолчанию (начиная с python 3.9) imghdr.what(...) загружает только первые 32 байта файла в буфер, а затем проверяет, соответствует ли шаблон в буфере любому типу файла, я не знаю, как структурированы все типы заголовков изображений, кажется, что некоторые изображения могут иметь более сложную структуру заголовка, которую imghdr не удалось проверить - person Han; 03.07.2021

В дополнение к тому, что предлагает Брайан, вы можете использовать метод PIL verify. чтобы проверить, не поврежден ли файл.

im.verify ()

Пытается определить, поврежден ли файл, без фактического декодирования данных изображения. Если этот метод обнаруживает какие-либо проблемы, он вызывает соответствующие исключения. Этот метод работает только с вновь открытым изображением; если изображение уже было загружено, результат не определен. Кроме того, если вам нужно загрузить изображение после использования этого метода, вы должны повторно открыть файл изображения. Атрибуты

person Nadia Alramli    schedule 20.05.2009
comment
ну основная проблема заключается в том, что файлы svg, xcf и psd не могут быть открыты с помощью Image.open (), следовательно, нет шансов проверить с помощью im.verify () - person Sujoy; 20.05.2009
comment
Боже мой, документация PIL ужасна. Что именно является подходящим исключением? - person Timmmm; 26.07.2012
comment
Вот ссылка на документацию по подушке для изображения. verify (). К сожалению, это не лучше, и похоже, что они просто подняли абзац выше, ничего не добавляя. - person Two-Bit Alchemist; 08.08.2014
comment
Я видел, как проверять повышение SyntaxError для поврежденных файлов png - person Carl; 20.11.2015
comment
есть ли способ проверить, действительно ли декодирует данные изображения? - person Trevor Boyd Smith; 13.09.2017
comment
im.verify() будет работать с некоторыми плохими изображениями, но я нашел изображения, где он их не поймает, но такие функции, как im.crop(), вызовут исключение. Для моего случая использования я счел лучше просто заключить im.crop() в блок try и обрабатывать исключения по мере необходимости. @TrevorBoydSmith Это также позволяет обойтись без необходимости дважды открывать изображение для использования im.verify() - вы просто читаете данные, и в случае сбоя обрабатываете исключение: EAFP. - person kevinmicke; 22.03.2018
comment
ммх исходный код, кажется, подтверждает ... ничего! Pillow.readthedocs.io/en/latest/_modules/ PIL / - person Massimo; 13.12.2019

В дополнение к проверке PIL изображений вы также можете добавить проверку расширения имени файла следующим образом:

filename.lower().endswith(('.png', '.jpg', '.jpeg', '.tiff', '.bmp', '.gif'))

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

person tsveti_iko    schedule 08.08.2019
comment
Что делать, если расширения в файлах неверны? Например, текстовый файл сохраняется с расширением .jpg или наоборот. - person hafiz031; 11.08.2020
comment
@ hafiz031 Чтобы получить фактический формат, вы можете сделать from PIL import Image img = Image.open(filename) print(img.format), а затем проверить его следующим образом: img.format.lower() in ['png', 'jpg', 'jpeg', 'tiff', 'bmp', 'gif'] - person tsveti_iko; 12.08.2020
comment
К сожалению, у меня это не сработало. Он по-прежнему идентифицирует поврежденное изображение как изображение JPEG. Наконец, мне удалось справиться с этим случаем таким образом (я использую OpenCv): stackoverflow.com/a/63421847/6907424 - person hafiz031; 15.08.2020

Обновить

Я также реализовал следующее решение в моем скрипте Python, здесь, на GitHub.

Я также подтвердил, что поврежденные файлы (jpg) часто не являются «битыми» изображениями, то есть поврежденный файл изображения иногда остается законным файлом изображения, исходное изображение потеряно или изменено, но вы все равно можете загрузить его без ошибок. Но усечение файла всегда вызывает ошибки.

Конец обновления

Вы можете использовать модуль Python Pillow (PIL) с большинством форматов изображений, чтобы проверить, является ли файл действительным и неповрежденным файлом изображения.

В случае, если вы стремитесь обнаружить также битые изображения, @Nadia Alramli правильно предлагает метод im.verify(), но этот не обнаруживает всех возможных дефектов изображения, например, im.verify не обнаруживает усеченные изображения (что большинство зрителей часто загружают с серым участком).

Pillow также может обнаруживать дефекты этого типа, но вы должны применить манипуляции с изображением или декодировать / перекодировать изображение или запустить проверку. Напоследок предлагаю использовать этот код:

try:
  im = Image.load(filename)
  im.verify() #I perform also verify, don't know if he sees other types o defects
  im.close() #reload is necessary in my case
  im = Image.load(filename) 
  im.transpose(PIL.Image.FLIP_LEFT_RIGHT)
  im.close()
except: 
  #manage excetions here

В случае дефектов изображения этот код вызовет исключение. Учтите, что im.verify примерно в 100 раз быстрее, чем обработка изображений (и я думаю, что переворот - одно из самых дешевых преобразований). С помощью этого кода вы собираетесь проверить набор изображений со скоростью около 10 МБ / с со стандартной подушкой или 40 МБ / с с модулем Pillow-SIMD (современный процессор x86_64 2,5 ГГц).

Для других форматов psd, xcf, .. вы можете использовать Imagemagick оболочку Wand, код выглядит следующим образом :

im = wand.image.Image(filename=filename)
temp = im.flip;
im.close()

Но, судя по моим экспериментам, Wand не обнаруживает усеченные изображения, я думаю, что он загружает недостающие части в виде серой области без запроса.

Я красный, что Imagemagick имеет внешнюю команду identify, которая может выполнить задание, но я не нашел способа вызвать эту функцию программно, и я не тестировали этот маршрут.

Я предлагаю всегда выполнять предварительную проверку, проверять, чтобы размер файла не был нулевым (или очень маленьким), это очень дешевая идея:

statfile = os.stat(filename)
filesize = statfile.st_size
if filesize == 0:
  #manage here the 'faulty image' case
person Fabiano Tarlao    schedule 25.11.2018

Один из вариантов - использовать пакет filetype.

Установка

python -m pip install filetype

Преимущества

  1. Быстро: работает, загружая только первые несколько байтов вашего изображения (проверьте магическое число)
  2. Поддерживает различные типы пантомимы: изображения, видео, шрифты, аудио, архивы.

Пример

filetype ›= 1.0.7

import filetype

filename = "/path/to/file.jpg"

if filetype.is_image(filename):
    print(f"{filename} is a valid image...")
elif filetype.is_video(filename):
    print(f"{filename} is a valid video...")

filetype ‹= 1.0.6

import filetype

filename = "/path/to/file.jpg"

if filetype.image(filename):
    print(f"{filename} is a valid image...")
elif filetype.video(filename):
    print(f"{filename} is a valid video...")

Дополнительная информация об официальном репо: https://github.com/h2non/filetype.py

person Alex Fortin    schedule 13.04.2020
comment
Программа Filetype также поддерживает формат webp. Отлично! - person Nav; 09.03.2021

В Linux вы можете использовать python-magic, который использует libmagic для определения форматов файлов.

AFAIK, libmagic изучает файл и пытается рассказать вам больше, чем просто формат, например размеры растрового изображения, версию формата и т. Д. Так что вы можете рассматривать это как поверхностный тест на достоверность.

Для других определений допустимости вам, возможно, придется написать свои собственные тесты.

person fmarc    schedule 20.05.2009

Вы можете использовать привязки Python к libmagic, python-magic, а затем проверить типы mime. . Это не скажет вам, повреждены ли файлы или нет, но он сможет определить, какой это тип изображения.

person Kamil Kisiel    schedule 20.05.2009

person    schedule
comment
В вашем коде есть проблемы с отступами, и он не будет работать должным образом. Также рассмотрите возможность добавления некоторых объяснений того, почему и как ваш код решает проблему. Ответы только на код не будут столь полезны для будущих читателей, которые придут сюда. - person Tomerikoo; 28.02.2020
comment
Здесь мы использовали метод Agrparser. - person rObinradOO; 05.03.2020