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

使用libjpeg C++导出JPEG时每1080像素出现竖线问题排查

libjpeg导出JPEG每隔1080像素出现竖线问题排查

问题背景

使用libjpeg在C++中导出JPEG文件时,图像每隔1080像素就会出现一条竖线。已尝试修改生成函数的循环边界、调整导出质量,问题仍未解决。

竖线示例

竖线示例

导出函数代码

void export_jpg(std::vector<std::vector<int>> grid) {
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;

    cinfo.err = jpeg_std_error(&jerr);    

    FILE* outfile = fopen("swg_test.jpg", "wb");
    if (!outfile) {
        exit(1);
    }
    
    jpeg_create_compress(&cinfo);
    jpeg_stdio_dest(&cinfo, outfile);

    cinfo.image_width = width;
    cinfo.image_height = height;
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;

    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, 100, TRUE);

    jpeg_start_compress(&cinfo, TRUE);

    while (cinfo.next_scanline < cinfo.image_height) {
        JSAMPROW row_buffer = new JSAMPLE[cinfo.image_width * 3];

        for (int x = 0; x < width; x++) {
            row_buffer[x * 3] = 0;
            row_buffer[x * 3 + 2] = 0;
            row_buffer[x * 3 + 1] =  grid[cinfo.next_scanline][x] ? 255 : 0;

        }
        jpeg_write_scanlines(&cinfo, &row_buffer, 1);
        delete[] row_buffer;
    }
    jpeg_finish_compress(&cinfo);
    fclose(outfile);
    jpeg_destroy_compress(&cinfo);
}

问题排查与解决方向

  • 统一宽度变量:代码中同时使用width和cinfo.image_width,若两者数值不一致,循环x < width会导致写入超出row_buffer分配的空间(cinfo.image_width *3),破坏内存引发异常。建议将循环边界改为cinfo.image_width,确保缓冲区操作不越界:
    for (int x = 0; x < cinfo.image_width; x++) {
        row_buffer[x * 3] = 0;
        row_buffer[x * 3 + 2] = 0;
        row_buffer[x * 3 + 1] = grid[cinfo.next_scanline][x] ? 255 : 0;
    }
    
  • 检查JPEG块对齐:JPEG编码以8x8或16x16块为处理单位,若图像宽度不是块大小的整数倍,部分libjpeg版本可能出现边界处理错误。可以:
    1. 调整图像宽度为8的整数倍;
    2. 初始化时设置cinfo.dct_method = JDCT_FLOAT;优化块处理逻辑。
  • 验证源数据完整性:检查grid中对应竖线位置的数值是否异常,比如x=1080附近的grid[cinfo.next_scanline][x]是否存在错误取值,导致颜色突变。
  • 优化内存操作:每次循环新建删除缓冲区可能引发内存问题,可将缓冲区分配移到循环外重复使用:
    JSAMPROW row_buffer = new JSAMPLE[cinfo.image_width * 3];
    while (cinfo.next_scanline < cinfo.image_height) {
        memset(row_buffer, 0, cinfo.image_width * 3 * sizeof(JSAMPLE));
        for (int x = 0; x < cinfo.image_width; x++) {
            row_buffer[x * 3 + 1] = grid[cinfo.next_scanline][x] ? 255 : 0;
        }
        jpeg_write_scanlines(&cinfo, &row_buffer, 1);
    }
    delete[] row_buffer;
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 14:06:29