如何将Boost::GIL的rgb8_image_t转换为opj_image_t实现通用格式转JPEG2000
实现方案
你参考的BMP转opj_image_t逻辑可以直接复用,只需要调整两个和存储格式相关的差异即可:
- BMP文件的像素行是从下到上倒序存储,而
boost::gil::rgb8_image_t默认是从上到下正序存储,不需要做行翻转 - BMP的24位像素是
B/G/R顺序排列,而boost::gil::rgb8_image_t的像素是R/G/B顺序排列,不需要做通道顺序交换
步骤1:先完成opj_image_t实例初始化
转换前你需要先创建并初始化符合参数要求的opj_image_t对象:
// 先从gil图像中拿到基础参数 int width = _img.width(); int height = _img.height(); opj_image_cmptparm_t cmpt_param[3]; memset(cmpt_param, 0, sizeof(cmpt_param)); for(int i=0; i<3; i++) { cmpt_param[i].prec = 8; // 每个分量8位 cmpt_param[i].bpp = 8; cmpt_param[i].sgnd = 0; // 无符号 cmpt_param[i].dx = 1; cmpt_param[i].dy = 1; cmpt_param[i].w = width; cmpt_param[i].h = height; } // 创建sRGB颜色空间的opj_image_t对象 opj_image_t* opj_img = opj_image_create(3, cmpt_param, OPJ_CLRSPC_SRGB); if(!opj_img) { // 自定义错误处理逻辑 }
步骤2:实现转换逻辑
直接参考BMP转换逻辑调整行遍历顺序和通道索引即可:
void gil_rgb8_to_opj_image(const boost::gil::rgb8_image_t& gil_img, opj_image_t* opj_img) { OPJ_UINT32 width = opj_img->comps[0].w; OPJ_UINT32 height = opj_img->comps[0].h; // 拿到gil图像的首指针,默认是交错存储的连续内存 const OPJ_UINT8* p_src = reinterpret_cast<const OPJ_UINT8*>(boost::gil::interleaved_view(gil_img).row_ptr(0)); OPJ_UINT32 stride = width * 3; // 一行的字节数,gil默认无行对齐填充 int index = 0; for (OPJ_UINT32 y = 0; y < height; y++) { for (OPJ_UINT32 x = 0; x < width; x++) { opj_img->comps[0].data[index] = (OPJ_INT32)p_src[3 * x + 0]; // R opj_img->comps[1].data[index] = (OPJ_INT32)p_src[3 * x + 1]; // G opj_img->comps[2].data[index] = (OPJ_INT32)p_src[3 * x + 2]; // B index++; } p_src += stride; } }
注意事项
- 确保初始化
opj_image_t时传入的宽高和你要转换的boost::gil::rgb8_image_t宽高完全一致,避免内存越界 - 如果你的
gil图像使用了非交错存储格式,需要先通过boost::gil::copy_and_convert_pixels转成交错的rgb8_image_t再执行转换 - 转换完成后
opj_image_t使用完毕,必须调用opj_image_destroy(opj_img)释放内存,避免泄漏
内容的提问来源于stack exchange,提问作者BunRieuCua
相关产品推荐
相关产品推荐

