【发布时间】:2021-08-30 20:42:32
【问题描述】:
我在 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 认为图像数据损坏的想法
【问题讨论】:
-
你能尝试更小的
row_stride值吗?试试你目前使用的一半,即w * 3。试试( w * 3 ) / 2。我更感兴趣的是是否停止segfault然后图像是否正确生成。 -
我尝试设置
row_stride = (w*3)/2;并将 while 循环更改为cinfo.next_scanline < cinfo.image_height/2两者仍然导致段错误。我还尝试在函数开始时将宽度和高度除以二,这也会导致错误。 -
我只是尝试在函数开始时将
w和h设置为1,并且程序不再在jpeg_write_scanlines上出错,而是在jpeg_finish_compress处出错
标签: c++ segmentation-fault libjpeg libjpeg-turbo