2013-12-22 4 views
0

Я нашел следующий код в Интернете для чтения и записи файла JPEG с использованием библиотеки libjpeg.Ошибка сегментации при сохранении файла JPEG (из массива данных RGB)

Я изменил функцию у oid write_JPEG_file (char * filename, int quality) на следующее:

void write_JPEG_vetor (JSAMPLE * image_data, int height, int width, int quality) 
{ 
    printf("%s\n","write_JPEG_vetor"); 
    /* This struct contains the JPEG compression parameters and pointers to 
    * working space (which is allocated as needed by the JPEG library). 
    * It is possible to have several such structures, representing multiple 
    * compression/decompression processes, in existence at once. We refer 
    * to any one struct (and its associated working data) as a "JPEG object". 
    */ 
    struct jpeg_compress_struct cinfo; 
    /* This struct represents a JPEG error handler. It is declared separately 
    * because applications often want to supply a specialized error handler 
    * (see the second half of this file for an example). But here we just 
    * take the easy way out and use the standard error handler, which will 
    * print a message on stderr and call exit() if compression fails. 
    * Note that this struct must live as long as the main JPEG parameter 
    * struct, to avoid dangling-pointer problems. 
    */ 
    struct jpeg_error_mgr jerr; 
    /* More stuff */ 
    FILE * outfile;  /* target file */ 
    JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ 
    int row_stride;  /* physical row width in image buffer */ 

    printf ("%s\n","Step 1: allocate and initialize JPEG compression object */"); 

    /* We have to set up the error handler first, in case the initialization 
    * step fails. (Unlikely, but it could happen if you are out of memory.) 
    * This routine fills in the contents of struct jerr, and returns jerr's 
    * address which we place into the link field in cinfo. 
    */ 
    cinfo.err = jpeg_std_error(&jerr); 
    /* Now we can initialize the JPEG compression object. */ 
    jpeg_create_compress(&cinfo); 

    printf ("%s\n","/* Step 2: specify data destination (eg, a file) */"); 
    /* Note: steps 2 and 3 can be done in either order. */ 

    /* Here we use the library-supplied code to send compressed data to a 
    * stdio stream. You can also write your own code to do something else. 
    * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that 
    * requires it in order to write binary files. 
    */ 

    char * filename = {"novo_arquivo.jpeg"}; 

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

    printf ("%s\n","/* Step 3: set parameters for compression */"); 

    /* First we supply a description of the input image. 
    * Four fields of the cinfo struct must be filled in: 
    */ 
    cinfo.image_width = width; /* image width and height, in pixels */ 
    cinfo.image_height = height; 
    cinfo.input_components = 3;  /* # of color components per pixel */ 
    cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ 
    /* Now use the library's routine to set default compression parameters. 
    * (You must set at least cinfo.in_color_space before calling this, 
    * since the defaults depend on the source color space.) 
    */ 
    jpeg_set_defaults(&cinfo); 
    /* Now you can set any non-default parameters you wish to. 
    * Here we just illustrate the use of quality (quantization table) scaling: 
    */ 
    jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); 

    printf ("%s\n","/* Step 4: Start compressor */"); 

    /* TRUE ensures that we will write a complete interchange-JPEG file. 
    * Pass TRUE unless you are very sure of what you're doing. 
    */ 
    jpeg_start_compress(&cinfo, TRUE); 

    printf ("%s\n","/* Step 5: while (scan lines remain to be written) */"); 
    /*   jpeg_write_scanlines(...); */ 

    /* Here we use the library's state variable cinfo.next_scanline as the 
    * loop counter, so that we don't have to keep track ourselves. 
    * To keep things simple, we pass one scanline per call; you can pass 
    * more if you wish, though. 
    */ 
    row_stride = width * 3; /* JSAMPLEs per row in image_buffer */ 

    while (cinfo.next_scanline < cinfo.image_height) { 
    printf ("%s\n","Loop WHILE"); 
    /* jpeg_write_scanlines expects an array of pointers to scanlines. 
    * Here the array is only one element long, but you could pass 
    * more than one scanline at a time if that's more convenient. 
    */ 

    row_pointer[0] = &image_data[cinfo.next_scanline * row_stride]; 
    (void) jpeg_write_scanlines(&cinfo, row_pointer, row_stride); 
    } 

    printf ("%s\n","/* Step 6: Finish compression */"); 

    jpeg_finish_compress(&cinfo); 
    /* After finish_compress, we can close the output file. */ 
    fclose(outfile); 

    printf ("%s\n","/* Step 7: release JPEG compression object */"); 

    /* This is an important step since it will release a good deal of memory. */ 
    jpeg_destroy_compress(&cinfo); 

    /* And we're done! */ 
} 

Теперь, когда я запускаю программу (в среде Linux), я получаю ошибку сегментации Fault. Кто-то может понять, почему это происходит? Мой главный подозреваемый код:

while (cinfo.next_scanline < cinfo.image_height) { 
    printf ("%s\n","Loop WHILE"); 
    /* jpeg_write_scanlines expects an array of pointers to scanlines. 
    * Here the array is only one element long, but you could pass 
    * more than one scanline at a time if that's more convenient. 
    */ 

    row_pointer[0] = &image_data[cinfo.next_scanline * row_stride]; 
    (void) jpeg_write_scanlines(&cinfo, row_pointer, row_stride); 
    } 

, но я не уверен, что и не может найти решение, чтобы решить эту проблему, несмотря на хорошо провести время, пытаясь.

=== UPDATE === я включил код последующей отладки в этой части кода:

while (cinfo.next_scanline < cinfo.image_height) { 
    printf ("%s\n","Loop WHILE"); 
    /* jpeg_write_scanlines expects an array of pointers to scanlines. 
    * Here the array is only one element long, but you could pass 
    * more than one scanline at a time if that's more convenient. 
    */ 

    printf ("%s\n","parte 1.1"); 
    row_pointer[0] = &image_data[cinfo.next_scanline * row_stride]; 
    printf ("%s\n","parte 1.2"); 
    printf ("%s\n","parte 2.1"); 
    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); 
    printf ("%s\n","parte 2.2"); 
    } 

И таким образом, выход при запуске програма является:

Loop WHILE 
parte 1.1 
parte 1.2 
parte 2.1 

=== UPDATE 2 === Для записи в моей программе эта функция принимает возвращаемое значение этой функции:

JSAMPLE * inverte_imagem() 
{ 
    int tamanho = image_height*image_width*image_colors; 
    int i; 
    JSAMPLE * vetor = malloc(sizeof(JSAMPLE)*(image_height*image_width*image_colors)); 
    for(i=0; i<tamanho; i++) 
    vetor [i] = image_buffer [tamanho - (i+1)]; 
} 
+0

Для этого вы используете отладчик и видите, что не так и почему. \ – bmargulies

ответ

0

ОК, я решить проблему кладя вызов для write_JPEG_vector внутри функции inverte_imagem(). Я не знаю почему, но когда я вызываю эту функцию из своей основной функции, возникает проблема с памятью (ошибка сегментации ошибок в Linux).

0

Это выглядит не так:

(void) jpeg_write_scanlines(&cinfo, row_pointer, row_stride); 

Этот последний параметр является количество строк для записи, а не длину строки. Вы, вероятно, хотите:

(void) jpeg_write_scanlines(&cinfo, row_pointer, 1); 
+0

ОК, я снова меняю эту строку (это была моя первая попытка) и ошибка все еще происходит. Поместите код отладки в эту часть кода (см. UPDATE выше) и появляется проблема с линией. –

+0

Кстати, когда я включаю строку отладки «printf («% s \ n », & image_data [cinfo.next_scanline * row_stride]); после первого printf программа показывает «parte 1.1» и сбой. Может быть, проблема может быть с переменной image_data? –

+0

Имеет ли значение 'image_colors' значение 3 в' inverte_imagem'? –