Что делать, когда cairo просит прочитать больше данных, чем у меня есть при создании и ImageSurface из png?

Я использую cairomm версии 1.12.0 с cairo версии 1.14.6.

Я пытаюсь создать ImageSurface в cairo из png, который я сохранил в памяти как вектор байтов. В большинстве случаев это работает, но иногда Cairo передает моей функции чтения (лямбда) длину для чтения (параметр длины), превышающую то, что осталось в векторе. Когда я отлаживаю это в Visual Studio, конечно, я получаю ошибочное утверждение об отладке Expression: cannot seek vector iterator after end

Cairo::RefPtr<Cairo::ImageSurface> someFunc(const std::vector<BYTE>& src)
{
  Cairo::RefPtr<Cairo::ImageSurface> ret;
  if (src.size() > 0)
  {
    unsigned int read = 0;
    ret = Cairo::ImageSurface::create_from_png_stream([&src, &read](unsigned char* data, unsigned int length) {
      std::copy_n(src.begin() + read, length, data);
      read += length;
      return CAIRO_STATUS_SUCCESS;
    });
  }
  return ret;
}

Если я попытаюсь изменить свою функцию чтения, чтобы скопировать минимум оставшихся данных и длину, которую Cairo запросил для чтения, я получаю CAIRO_STATUS_NO_MEMORY, что вызывает исключение std::bad_alloc.

Cairo::RefPtr<Cairo::ImageSurface> someFunc(const std::vector<BYTE>& src)
{
  Cairo::RefPtr<Cairo::ImageSurface> ret;
  if (src.size() > 0)
  {
    unsigned int read = 0;
    ret = Cairo::ImageSurface::create_from_png_stream([&src, &read](unsigned char* data, unsigned int length) {
      length = std::min((unsigned int)src.size() - read, length); // added
      std::copy_n(src.begin() + read, length, data);
      read += length;
      return CAIRO_STATUS_SUCCESS;
    });
  }
  return ret;
}

Я думаю, это как-то связано с вызовом _cairo_output_stream_write в stream_read_func в cairo-png.c, поскольку он передает тот же размер, что и мою функцию чтения, поэтому, вероятно, ожидается, что там будут какие-то данные.

...
status = png_closure->read_func (png_closure->closure, data, size);
...
_cairo_output_stream_write (png_closure->png_data, data, size);

Должен ли я писать null или что-то еще, чтобы заполнить разницу в байтах?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если cairo запрашивает больше данных, чем у вас есть, ваш PNG неисправен. Cairo запрашивает столько байтов, сколько запрашивает libpng, и, предположительно, libpng знает, что делает (tm), и запрашивает нужное количество байтов. Если у вас недостаточно байтов, вы должны вернуть CAIRO_STATUS_READ_ERROR из функции чтения.

Спасибо. Я выгрузил png в файл, проверил его в шестнадцатеричном редакторе и обнаружил, что его окончательный блок IDAT имеет длину 8192 байта, но на самом деле он составляет всего 7725 байт. Мне придется добавить некоторую обработку ошибок и посмотреть, почему данные были потеряны ранее в конвейере.

Kittenmittons 03.05.2019 22:43

Другие вопросы по теме