将扫描线写入文件 C++ 时出现 libjpeg-turbo 分段错误

libjpeg-turbo segmentation fault when writing scanlines to file c++

我在 QT Creator 的 windows 10 上有以下代码 运行,我正在尝试使用 libjpeg-turbo 库将 rgb 格式的数据写入 jpeg 文件

#include <stdio.h>
#include <jpeglib.h>

void writeJpeg(const char *filename, std::vector<unsigned char> &image, uint w, uint h) {
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;

    FILE *outfile;
    JSAMPROW row_pointer[1];
    int row_stride;

    cinfo.err = jpeg_std_error(&jerr);

    jpeg_create_compress(&cinfo);

    if ((outfile = fopen(filename, "wb")) == NULL) {
    fprintf(stderr, "can't open %s\n", filename);
    exit(1);
    }
    jpeg_stdio_dest(&cinfo, outfile);

    cinfo.image_width = w;
    cinfo.image_height = h;
    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);


    row_stride = w * 3;

    JSAMPLE *arr = image.data();


    while (cinfo.next_scanline < cinfo.image_height) {
        row_pointer[0] = &arr[cinfo.next_scanline * row_stride];
        (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
      }



    jpeg_finish_compress(&cinfo);

    fclose(outfile);


    jpeg_destroy_compress(&cinfo);
}
在这部分代码中

并在 (void)jpeg_write_scanlines(&cinfo, row_pointer, 1); 上获得 SIGSEGV

while (cinfo.next_scanline < cinfo.image_height) {
        row_pointer[0] = &arr[cinfo.next_scanline * row_stride];
        (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
      }

我试过调试,但我不完全确定最好的方法是什么。

我发现它在 15 次循环迭代后崩溃,我最好的猜测是我将数据从向量转换为指针数组的效果很差。

无论如何,我不知道如何更好地分配内存,或者这是否是问题所在

任何关于我做错了什么的想法以及任何关于将来如何实际调试它的提示都将不胜感激。

编辑

我将 true 更改为 TRUE 并像这样打印出数组中的每个字节

while (cinfo.next_scanline < cinfo.image_height) {
        row_pointer[0] = &arr[cinfo.next_scanline * row_stride];

        QString out = "";
        for (int i = 0; i<row_stride; i++)
            out += QString::number(row_pointer[0][i]) + " ";
        qDebug() << "\n\n==============" << cinfo.next_scanline << "==============\n\n";
        qDebug() << out;


        (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
      }

在逐步执行后,它能够输出所有字节,但仍然在 write_jpeg_scanlines

上崩溃

我还注意到在每条扫描线的末尾打印了一些随机文本 前任: 255 255 255 25520003200!-�U3 第 12 行

255 255 255 255eencoded�/�Rf 第 13 行

231 230 230 255,autoder�)�Pu 第 15 行,崩溃的数据

不确定这是否只是指针末尾的垃圾,或者 qDebug 的症状,但它可以证实 antons 图像数据损坏的想法

除了在这些调用中传递的是 C++ 布尔值 true 而不是 C 值 TRUE 外,我没有发现您的代码有任何问题:

    jpeg_set_quality(&cinfo, 100, true);
    ...
    jpeg_start_compress(&cinfo, true);

有时可能会导致奇怪的崩溃。

此外,在这种情况下,我首先要尝试的是 - 如果只是在某个地方输出每行的所有字节 arr[cinfo.next_scanline * row_stride] - 它会崩溃吗?如果是,则可能是您在准备图像数据的其他代码中出错。

UPD.: 原始代码的问题很可能是 #include <jpeglib.h> - 应该强制在系统目录而不是 libjpeg 中搜索 jpeglib.h -涡轮目录。这可以通过使用 #include "jpeglib.h" 并指定 libjpeg-turbo include 编译器目录的路径来解决。

感谢所有帮助,正如@AntonMalyshev 指出的那样,问题是 libjpeg 的使用不正确。

首先,我安装了 libjpeg-turbo,虽然它包含一个用于 libjpeg 的库,但我确信更好的做法是直接安装 libjpeg。我最终使用了 #include <turbojpeg.h>.

其次,我发布的示例代码似乎只与基础兼容 libjpeg 使用这个 post and the libjpeg-turbo api 我能够想出一个可行的解决方案。

谢谢,伊桑