I have the following code running on windows 10 in QT Creator, I am trying to write rgb formatted data to a jpeg file using the libjpeg-turbo library
#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);
}
and get SIGSEGV
on (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
in this portion of the code
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = &arr[cinfo.next_scanline * row_stride];
(void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
I have tried debugging, but im not entirely sure what the best way to do that is.
I have found out that it crashes after 15 iterations of the loop and my best guess is that I have converted the data poorly from the vector into the pointer array.
Anyways, I cannot figure out how to better allocate the memory or if this is even the problem
Any ideas on what I'm doing wrong plus any tips on how to actually debug this in the future would be greatly appreciated.
EDIT
I changed true
to TRUE
and printed out every byte in the array like so
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);
}
and after stepping through its execution, it is able to output all the bytes, yet still crashes on write_jpeg_scanlines
I also noticed some random text being printed out at the end of each scanline
ex:
255 255 255 25520003200!-�U3
on row 12
255 255 255 255eencoded�/�Rf
on row 13
231 230 230 255,autoder�)�Pu
on row 15, the data where it crashes
not sure if this is just garbage at the end of the pointer, or a symptom of qDebug
but it could confirm antons idea of corrupted image data
I see nothing wrong in your code, except C++ bool value true
is passed instead of C value TRUE
in these calls:
jpeg_set_quality(&cinfo, 100, true);
...
jpeg_start_compress(&cinfo, true);
It may lead to weird crashes sometimes.
Also, the first thing I would try in this case - what if just to output somewhere all the bytes of every row arr[cinfo.next_scanline * row_stride]
- does it crash? If it does, possibly you have error in other code preparing the image data.
UPD.: most probably the problem with original code was #include <jpeglib.h>
- that should force to search for jpeglib.h in system directories instead of the libjpeg-turbo directories. That could be solved by using #include "jpeglib.h"
and specifying the path to libjpeg-turbo include directory to compiler.