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

изменить:

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

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

Я присваиваю номера страниц и соединяю эти изображения. Некоторые изображения представляют собой одну левую или правую страницу. Некоторые изображения широкие и представляют собой «разворот» левой и правой страниц. Например, pagesAt(3) и pagesAt(4) могут возвращать одну и ту же пару std::pair изображений или std::pair одного и того же широкого изображения.

Иногда существует нечетное количество «тонких» изображений, и первое изображение должно отображаться отдельно, как и широкое изображение. Примером может быть одна титульная страница.

Незнание того, какие файлы в каталоге не являются изображениями, означает, что я не могу с уверенностью присвоить эти номера страниц и объединить файлы для отображения. Кроме того, пользователь может решить перейти на страницу X, и когда я позже обнаружу и удалю файл, не являющийся изображением, и соответствующим образом переназначу номера страниц, страница X может оказаться другим изображением.

исходный:

Если это имеет значение, я использую c++ и QImage из библиотеки Qt.

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

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

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

So,

Будет ли загрузка только заголовков изображения намного быстрее, чем загрузка всего изображения? Или выполнение небольшого количества операций ввода-вывода для чтения заголовка означает, что я мог бы завершить загрузку изображения полностью? Позже я также буду распаковывать изображения из архивов, так что это также относится к распаковке только заголовка по сравнению с распаковкой всего файла.

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


person Kache    schedule 30.12.2009    source источник
comment
Как быстро вам нужно узнать, действительны ли изображения? (Сразу, сразу после звонка или через какое-то неопределенное время?) Что вы делаете с изображением — манипулируете им, показываете или просто перемещаете данные куда-то еще?   -  person Caleb Huitt - cjhuitt    schedule 30.12.2009
comment
Я уточнил свой вопрос выше. Под достоверностью я подразумевал обнаружение файлов, не являющихся изображениями, без простого просмотра расширения файла или загрузки полного файла изображения. Вот почему я спрашивал, есть ли способ проверять заголовки только при переборе каталога.   -  person Kache    schedule 31.12.2009


Ответы (5)


Инструмент Unix file (который существует почти всегда) делает именно это. Это простой инструмент, который использует базу данных известных заголовков файлов и двоичных подписей для определения типа файла (и, возможно, для извлечения некоторой простой информации).

База данных представляет собой простой текстовый файл (который компилируется для повышения эффективности), который описывает множество форматов двоичных файлов, используя простой структурированный формат (задокументированный в man magic). Исходник находится в /usr/share/file/magic (в Ubuntu). Например, запись для формата файла PNG выглядит так:

0       string          \x89PNG\x0d\x0a\x1a\x0a         PNG image
!:mime  image/png
>16     belong          x               \b, %ld x
>20     belong          x               %ld,
>24     byte            x               %d-bit
>25     byte            0               grayscale,
>25     byte            2               \b/color RGB,
>25     byte            3               colormap,
>25     byte            4               gray+alpha,
>25     byte            6               \b/color RGBA,
>28     byte            0               non-interlaced
>28     byte            1               interlaced

Вы можете извлечь подписи только для типов файлов изображений и создать свой собственный «сниффер» или даже использовать синтаксический анализатор из инструмента file (который, похоже, имеет лицензию BSD).

person gavinb    schedule 30.12.2009
comment
Сладкий, спасибо. Но я хотел бы, чтобы это приложение работало кросс-платформенно, поэтому я не могу полагаться на системный вызов unix. Под «созданием собственного сниффера» вы имеете в виду кодирование моего собственного «считывателя заголовков»? Или вы хотите сказать, что у меня есть способ получить исходный код этого инструмента file? - person Kache; 31.12.2009
comment
Неважно, я нашел источник для этого. Теперь мне просто нужно посмотреть, могу ли я использовать его напрямую или мне нужно написать что-то свое с ним. - person Kache; 31.12.2009

Просто добавлю свои 2 цента: вы можете использовать QImageReader для получения информации о файлах изображений без фактической загрузки файлов.

Например, с помощью метода .format вы можете проверить формат изображения файла.

Из официального документа Qt ( http://qt-project.org/doc/qt-4.8/qimagereader.html#format ):

Возвращает формат, который QImageReader использует для чтения изображений. Вы можете вызвать эту функцию после назначения устройства считывателю, чтобы определить формат устройства. Например: Читатель QImageReader("image.png"); // reader.format() == "png" Если ридер не может прочитать какое-либо изображение с устройства (например, там нет изображения или изображение уже было прочитано), или если формат не поддерживается, эта функция возвращает значение пустой QByteArray().

person Viktor Benei    schedule 12.05.2012

Я не знаю ответа на вопрос о загрузке заголовка, и, вероятно, это зависит от типа изображения, которое вы пытаетесь загрузить. Вы можете рассмотреть возможность использования Qt::Concurrent для просмотра изображений, позволяя остальной части программы продолжать работу, если это возможно. В этом случае вы, вероятно, сначала представите все записи как неизвестное состояние, а затем измените состояние на изображение или не изображение, когда проверка будет выполнена.

person Caleb Huitt - cjhuitt    schedule 30.12.2009
comment
Вполне вероятно, что все изображения будут одного формата — может быть всего одно или два разных. Как только я найду два/три изображения одного формата, я могу с уверенностью предположить, что остальные тоже такие же. - person Kache; 31.12.2009

Если вы говорите о файлах изображений в целом, а не только о конкретном формате, я готов поспорить, что есть случаи, когда заголовок изображения действителен, а данные изображения - нет. Вы ничего не сказали о своем приложении, нельзя ли добавить фоновый поток, который мог бы хранить несколько изображений в оперативной памяти и менять их местами в зависимости от того, что пользователь может загрузить дальше? IE: приложение для показа слайдов будет загружать 1 или 2 изображения впереди и позади текущего. Или, может быть, отображать вопросительный знак рядом с именем изображения, пока фоновый поток не сможет проверить достоверность данных.

person Chris H    schedule 30.12.2009
comment
Поврежденные данные — это нормально. Я не был слишком ясен раньше, извините. Что мне действительно нужно, так это обнаруживать не изображения более разумно, чем смотреть на расширение файла или тратить время на загрузку полного изображения. - person Kache; 31.12.2009

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

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

Раймонд Чен написал об этом статью для своего блога The Old New Thing. .

person R Samuel Klatchko    schedule 30.12.2009
comment
Я не думаю, что это будет проблемой. Это приложение с графическим интерфейсом для конечных пользователей, позволяющее читать изображения, как если бы они были страницами в книге, поэтому все это будет локально. В худшем случае я думаю, что это будет просто внешний жесткий диск или ближайшая локальная сеть. - person Kache; 31.12.2009