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

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

Я пытаюсь создать ImageSurface в Каире из png, который я сохранил в памяти как вектор байтов.В большинстве случаев это работает, но иногда Каир передает моей функции чтения (лямбда) длину для чтения (параметр длины) больше, чем осталось в векторе.Конечно, когда я отлаживаю это в 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_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);

Должен ли я писать ноль или что-то для заполненияразница в байтах?

1 Ответ

0 голосов
/ 03 мая 2019

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

...