如何使用cairomm png流读写?

问题描述 投票:0回答:1

我将

Cairo::ImageSurface
保存为二进制文件的一部分。从
surface->get_data()
写入像素效果很好,但与我使用
surface->write_to_png(std::string name)
写入时相比,它会生成更大的文件。所以我尝试使用
surface->write_to_png_stream(const SlotWriteFunc &write_func);
Cairo::ImageSurface::create_from_png_stream(const SlotReadFunc &read_func)
;

最初,Cairo::Surface::SlotWriteFunc回调对我来说很有意义,它在写入表面时被调用多次,并提供参数

const unsigned char*
作为数据和
unsigned int
作为长度,但是Cairo::Surface: :SlotReadFunc 让我感到困惑,因为它还提供了一个
unsigned int
来确定它想要读取多少数据。为什么不是
unsigned int&
,以便我可以根据文件判断长度?这让我得出一个结论,我也不明白
SlotWriteFunc

请解释如何使用

SlotWriteFunc
SlotReadFunc

谢谢您的帮助。

以下示例可以正常写入文件,但在我调用

create_from_png_stream
:

时抛出错误
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted
#include <fstream>
#include <iostream>
#include <cairomm/cairomm.h>


class PNGStream {
public:

    std::fstream *file;
    

    Cairo::ErrorStatus write(const unsigned char *data, unsigned int length) {
        std::cout << length << std::endl;

        file->write(reinterpret_cast<char *>(&length), sizeof(length));
        file->write(reinterpret_cast<const char*>(data), length);

        return Cairo::ErrorStatus::CAIRO_STATUS_SUCCESS;
    }

    Cairo::ErrorStatus read(unsigned char *data, unsigned int length) {
        std::cout << length << std::endl;

        // I'm not sure, what comes here

        return Cairo::ErrorStatus::CAIRO_STATUS_SUCCESS;
    }
};

int main() {
    std::fstream file;
    PNGStream png_stream;
    png_stream.file = &file;
    auto surface = Cairo::ImageSurface::create(Cairo::Surface::Format::ARGB32, 1920, 1080);
    auto cr = Cairo::Context::create(surface);
    
    cr->set_source_rgb(0, 0, 0);
    cr->paint();
    file.open("test.png", std::ios::binary | std::ios::out);
    surface->write_to_png_stream(sigc::mem_fun(png_stream, &PNGStream::write));
    file.close();
    
    file.open("test.png", std::ios::binary | std::ios::in);
    auto surface2 = Cairo::ImageSurface::create_from_png_stream(sigc::mem_fun(png_stream, &PNGStream::read)); //error
    file.close();
    
    return 0;
}
c++ cairo
1个回答
0
投票

PNG 文件具有已知的格式,它由块组成,每个块以其长度为前缀,cairo 可以逐块读取它,直到读取失败指示文件结尾。

对于您编写的代码,您应该只从流中读取

length
字节,然后如果读取不成功,则文件流将设置错误标志,这意味着它将评估为
false

    Cairo::ErrorStatus read(unsigned char *data, unsigned int length) {
        std::cout << length << std::endl;

        file->read(data, length);
        if (!*file) // read failed
        {
          return Cairo::ErrorStatus::CAIRO_STATUS_READ_ERROR;
        }
        Cairo::ErrorStatus::CAIRO_STATUS_SUCCESS;
    }

如果您有一个大小与 png 大小完全相同的文件流,那么这将起作用,但如果您在同一个文件中“打包”了其他任何内容,那么您需要计算读取了多少字节并手动限制读取的字节。

© www.soinside.com 2019 - 2024. All rights reserved.