Невозможно использовать Boost GIL для определения типа файла изображения (исключение не перехвачено)

Мне нужно проверить, является ли файл JPEG или PNG, и я не могу доверять расширению файла, потому что оно может быть неправильным. Для этого я решил использовать GIL.

Вот заголовочный файл, объявляющий (и определяющее) boost::gil::png_read_dimensions. В нем четко указано, что boost::gil::png_read_dimensions "Выдает std::ios_base::failure, если местоположение не соответствует допустимому файлу PNG". И действительно, это похоже на фактическое поведение функций.

Проблема связана с boost::gil::jpeg_read_dimensions, которую вы можете увидеть здесь< /а>. В нем также четко указано, что он "выдает std::ios_base::failure, если местоположение не соответствует допустимому файлу JPEG". Однако, похоже, это не так! Исключение не выдается, вместо этого libjpeg выводится на стандартный вывод или стандартный вывод, а затем завершает работу программы.

См. следующий код:

#include <iostream>
#include <string>

#include <boost/gil/extension/io/jpeg_io.hpp>
#include <boost/gil/extension/io/png_io.hpp>

using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::ios_base;

namespace bg = boost::gil;

int main(int, char**) {
  const string not_jpeg_or_png ("image.gif");

  cout << "bg::png_read_dimensions:" << endl;
  try {
    bg::png_read_dimensions(not_jpeg_or_png);
  } catch(const ios_base::failure &ib_f) {
    cerr << "what: " << ib_f.what() << endl;
  }

  cout << "\nbg::jpeg_read_dimensions:" << endl;
  try {
    bg::jpeg_read_dimensions(not_jpeg_or_png);
  } catch(const ios_base::failure &ib_f) {
    cerr << "what: " << ib_f.what() << endl;
  }

  cout << "\nDone." << endl;

  return 0;
}

Вывод программы:

bg::png_read_dimensions:
what: png_check_validity: invalid png file: unspecified iostream_category error

bg::jpeg_read_dimensions:
Not a JPEG file: starts with 0x62 0x6c

Обратите внимание, что what: ... yadiyadiyada ... и Done. не печатаются.

Я пытался сделать } catch(...) { вместо } catch(const ios_base::failure &ib_f) {, чтобы убедиться, что ни одно исключение не проходит незамеченным, но безуспешно. Никаких исключений не выбрасывается!

Я пропустил что-то действительно очевидное здесь...? Я делаю что-то неправильно? Есть ли обходной путь?


person Community    schedule 15.05.2015    source источник


Ответы (2)


Я не понимаю, почему выброшенное исключение, по-видимому, не может быть поймано. Это может быть ошибка.

Однако для выполнения задачи я бы предложил

  • libmagic or
  • identify (из ImageMagick)

который делает то, что предлагает другой ответ.

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

person sehe    schedule 15.05.2015
comment
Я задам этот вопрос день или два здесь, в StackOverflow, и если к тому времени не будет дано удовлетворительного ответа, я посмотрю, смогу ли я опубликовать его в Boost Trac. Если получится, я обязательно размещу здесь ссылку на билет. - person ; 15.05.2015
comment
Я открыл тикет здесь. Я пытаюсь изучить это сам, потому что я нашел этот комментарий в соответствующем коде: // lbourdev: Может ли это вернуть ошибку? Вам нужно проверить и бросить. Проверьте все другие библиотечные методы, которые могут возвращать состояние ошибки...... :) - person ; 17.05.2015

Самый простой способ — прочитать первые несколько битов файла и посмотреть, соответствуют ли они сигнатуре типа файла.

89 50 4E 47 0D 0A 1A 0A => PNG

FF D8 FF => JPEG

person user3344003    schedule 15.05.2015
comment
Я попробую, спасибо за предложение. 89 50 4Е...; вы написали это как шестнадцатеричные пары, верно? - person ; 15.05.2015