当cairo要求读取的数据比从png创建和ImageSurface读取的数据多时,该怎么办?

时间:2019-05-03 18:48:39

标签: c++ png cairo

我正在使用cairomm版本1.12.0和cairo版本1.14.6。

我正在尝试从png中在开罗中创建ImageSurface,我将其作为字节向量存储在内存中。在大多数情况下,这是可行的,但有时Cairo会给我的read函数(lambda)传递一个要读取的长度(长度参数),该长度要大于向量中剩余的长度。当我在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-png.c中_cairo_output_stream_write中对stream_read_func的调用有关,因为它传递的大小与传递我的读取函数的大小相同,因此很可能希望有一些数据。

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

我应该写空值还是用一些东西来填补字节差?

1 个答案:

答案 0 :(得分:0)

如果cairo要求的数据量超过您的数据量,则您的PNG已损坏。开罗请求的字节数与libpng请求的字节数相同,并且libpng知道它在做什么(tm),并要求正确的字节数。如果没有足够的字节,则应从读取函数返回CAIRO_STATUS_READ_ERROR