You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows下使用libtiff高效获取unsigned char*字节数据的方案

优化libtiff内存写入,直接获取unsigned char*的方案

原方案通过std::ostringstream中转,会产生至少两次数据拷贝(写入流时的内部拷贝、调用str()生成字符串拷贝),效率较低。可以改用TIFFClientOpen直接绑定自定义内存缓冲区,跳过标准流的中间层,直接拿到unsigned char*。

实现步骤

  1. 定义结构体管理内存缓冲区和当前读写位置:
struct TiffBuffer {
    std::vector<unsigned char> data;
    toff_t pos = 0;
};
  1. 实现libtiff要求的回调函数(用于读写、定位、关闭等操作):
static tsize_t tiff_write(thandle_t handle, void* buffer, tsize_t size) {
    auto& buf = *static_cast<TiffBuffer*>(handle);
    const auto old_size = buf.data.size();
    buf.data.resize(old_size + size);
    std::memcpy(buf.data.data() + old_size, buffer, size);
    buf.pos += size;
    return size;
}

static tsize_t tiff_read(thandle_t /*handle*/, void* /*buffer*/, tsize_t /*size*/) {
    // 仅写入场景,无需实现读逻辑
    return 0;
}

static toff_t tiff_seek(thandle_t handle, toff_t offset, int origin) {
    auto& buf = *static_cast<TiffBuffer*>(handle);
    toff_t new_pos = 0;
    switch (origin) {
        case SEEK_SET: new_pos = offset; break;
        case SEEK_CUR: new_pos = buf.pos + offset; break;
        case SEEK_END: new_pos = buf.data.size() + offset; break;
        default: return -1;
    }
    // 写入时若偏移超出当前缓冲区大小,自动扩容
    if (new_pos > static_cast<toff_t>(buf.data.size())) {
        buf.data.resize(new_pos);
    }
    buf.pos = new_pos;
    return new_pos;
}

static int tiff_close(thandle_t /*handle*/) {
    // 缓冲区由外部管理,无需在此释放
    return 0;
}

static toff_t tiff_size(thandle_t handle) {
    auto& buf = *static_cast<TiffBuffer*>(handle);
    return buf.data.size();
}
  1. 使用TIFFClientOpen创建内存TIFF句柄并写入数据:
TiffBuffer tiff_buf;

TIFF* ofo = TIFFClientOpen(
    "MemTIFF",
    "w",
    &tiff_buf,
    tiff_read,
    tiff_write,
    tiff_seek,
    tiff_close,
    tiff_size,
    nullptr,
    nullptr
);

if (!ofo) {
    // 错误处理逻辑
    return;
}

// 执行TIFF写入操作(设置图像参数、写入扫描线等)
// 示例:设置基础图像属性
TIFFSetField(ofo, TIFFTAG_IMAGEWIDTH, 1920);
TIFFSetField(ofo, TIFFTAG_IMAGELENGTH, 1080);
TIFFSetField(ofo, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(ofo, TIFFTAG_SAMPLESPERPIXEL, 3);
TIFFSetField(ofo, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
// ... 其他写入操作(如写入扫描线)

TIFFClose(ofo);

// 直接获取unsigned char*,无额外拷贝
unsigned char* tiff_data = tiff_buf.data.data();
size_t tiff_data_len = tiff_buf.data.size();

方案优势

  • 零额外拷贝:所有写入操作直接复制到std::vector的内存区域,没有std::ostringstream的中间层拷贝。
  • 直接获取指针:通过vector::data()直接拿到连续内存的unsigned char*,无需转换字符串。
  • 动态扩容:std::vector自动适配TIFF数据大小,无需提前预估缓冲区尺寸。

注意事项

  • 回调函数必须是静态函数(或符合C语言函数指针规范),因为libtiff的API是C风格的。
  • 确保在TIFFClose后再访问缓冲区,libtiff可能在关闭时完成最后的收尾写入。
  • 若需要支持读写场景,只需补充实现tiff_read函数即可。

内容的提问来源于stack exchange,提问作者JaSHin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 16:36:20