-1

これは、jpeg-trubo の example.c からわずかに変更されたコードです (そのコードにはエラーが含まれていました)。

画像データをファイルに書き込もうとすると、cinfo.next_scanline==9 のときに失敗し、jpeg_write_scanlines でオンラインでクラッシュします。エラー: SigSegv エラーです。cinfo.image_height は 404 に設定されています。読み取りループ問題ないようです。問題を解決するのを手伝ってもらえますか?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libjpeg-turbo\libjpeg-turbo-gcc\include\jerror.h"

#include "libjpeg-turbo\libjpeg-turbo-gcc\include\jpeglib.h"
#include <setjmp.h> // optional error recovery mechanism
//# include "conversions.h" // color conversion functions

extern JSAMPLE * image_buffer;  // Points to large array of R,G,B-order data
int image_height;     // Number of rows
int image_width;      // Number of columns

int read_JPEG_file(char * filename, unsigned char * image_buffer);
void write_JPEG_file(char * filename, unsigned char * image_buffer, int quality);

int main()
{
    char * filename1 = "source.jpg";
    char * filename2 = "target.jpg";
    unsigned char * image_buffer; // Final image
    read_JPEG_file(filename1, image_buffer);
    write_JPEG_file(filename2, image_buffer, 95);
    return 0;
}

struct my_error_mgr {
  struct jpeg_error_mgr pub;    /* "public" fields */

  jmp_buf setjmp_buffer;        /* for return to caller */
};
typedef struct my_error_mgr * my_error_ptr;

METHODDEF(void) my_error_exit (j_common_ptr cinfo)
{
  my_error_ptr myerr = (my_error_ptr) cinfo->err;
  (*cinfo->err->output_message) (cinfo);
  longjmp(myerr->setjmp_buffer, 1);
}

GLOBAL(int)
read_JPEG_file (char * filename, unsigned char * image_buffer)
{
  struct jpeg_decompress_struct cinfo;
  struct my_error_mgr jerr;
  FILE * infile;                // source file
  JSAMPARRAY rows_buffer;  // Output row rows_buffer
  int row_stride_len;  // physical row width in output rows_buffer

  if ((infile = fopen(filename, "rb")) == NULL) {
    fprintf(stderr, "can't open %s\n", filename);
    return 0;
  }

  cinfo.err = jpeg_std_error(&jerr.pub);
  jerr.pub.error_exit = my_error_exit;
  if (setjmp(jerr.setjmp_buffer)) {
    jpeg_destroy_decompress(&cinfo);
    fclose(infile); // close the input file and return
    return 0;
  }

  jpeg_create_decompress(&cinfo);
  jpeg_stdio_src(&cinfo, infile);

  (void) jpeg_read_header(&cinfo, TRUE);

  (void) jpeg_start_decompress(&cinfo); // no errors possible
  row_stride_len = cinfo.output_width * cinfo.output_components;
  rows_buffer = (*cinfo.mem->alloc_sarray)
                ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride_len, 1);

  size_t counter=0;
  size_t raw_size = row_stride_len;
  image_buffer = (unsigned char*) malloc( row_stride_len*cinfo.output_height );
  while (cinfo.output_scanline < cinfo.output_height) {
    (void) jpeg_read_scanlines(&cinfo, rows_buffer, 1);
    memcpy(image_buffer+counter, rows_buffer[0], raw_size);
    counter += row_stride_len;
  }

  // Save global values for later use
  image_width=cinfo.image_width;
  image_height=cinfo.image_height;

  (void) jpeg_finish_decompress(&cinfo); // Finish decompression, no errors possible
  jpeg_destroy_decompress(&cinfo); // 8) Release JPEG decompression object
  fclose(infile);
  return 1;
}

GLOBAL(void)
write_JPEG_file(char * filename, unsigned char * image_buffer, int quality)
{
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
  FILE * outfile;  // target file
  JSAMPROW rows_buffer[1];  // pointer to JSAMPLE row[s]
  int row_stride_len;  // physical row width in image rows_buffer
  cinfo.err = jpeg_std_error(&jerr);
  jpeg_create_compress(&cinfo); // initialize the JPEG compression object
  if ((outfile = fopen(filename, "wb")) == NULL) {
    fprintf(stderr, "can't open %s\n", filename);
    exit(1);
  }
  jpeg_stdio_dest(&cinfo, outfile);
  cinfo.image_width  = image_width;
  cinfo.image_height = image_height;
  cinfo.input_components = 3;
  cinfo.in_color_space = JCS_RGB;
  jpeg_set_defaults(&cinfo); // set default compression parameters
  jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
  jpeg_start_compress(&cinfo, TRUE); // TRUE - write a complete interchange-JPEG file.
  row_stride_len = cinfo.image_width * 3; /* JSAMPLEs per row in image_buffer */

  // pass array of pointers to scan lines
  while (cinfo.next_scanline < cinfo.image_height) {
    rows_buffer[0] = & image_buffer[cinfo.next_scanline * row_stride_len];
    (void) jpeg_write_scanlines(&cinfo, rows_buffer, 1);
  }

  jpeg_finish_compress(&cinfo);
  fclose(outfile);
  jpeg_destroy_compress(&cinfo);
}
4

1 に答える 1

1

画像バッファーにスペースを割り当てread_JPEG_file、その関数の引数にポインターを格納しますimage_bufferが、その値は関数が戻るときに失われます。のimage_buffer変数mainは別の変数であり、への呼び出しによって変更されませんread_JPEG_file。inのimage_buffer変数は初期化も値の割り当ても行われないため、有効なポインタではなくmain、初期化されていない値を に渡します。write_JPEG_file

また、例の開始近くimage_bufferへのポインターとして宣言されているグローバル変数も、別の変数です。JSAMPLEこの変数は、サンプル プログラムでは完全に使用されていません。

既にグローバル変数を使用して画像の幅read_JPEG_fileと関数間の高さを伝達してwrite_JPEG_fileいるため、問題に対する単純な修正 (ただし、必ずしも最適であるとは限りません) は、画像データへのポインターにもグローバル変数を使用することです。グローバル変数の型をimage_bufferからJSAMPLE *に変更し、 fromunsigned char *の定義を削除し、関数およびから引数を削除します。これにより、画像データへのポインターを格納するためにグローバル変数が使用されます。image_buffermainimage_bufferread_JPEG_filewrite_JPEG_fileimage_buffer

例えば:

...

unsigned char * image_buffer;  // Points to large array of R,G,B-order data
int image_height;     // Number of rows
int image_width;      // Number of columns

int read_JPEG_file(char * filename);
void write_JPEG_file(char * filename, int quality);

int main()
{
    char * filename1 = "source.jpg";
    char * filename2 = "target.jpg";
    read_JPEG_file(filename1);
    write_JPEG_file(filename2, 95);
    return 0;
}

...

GLOBAL(int)
read_JPEG_file (char * filename)
{
    ...
}

GLOBAL(void)
write_JPEG_file(char * filename, int quality)
{
    ...
}
于 2015-01-28T22:51:58.647 に答える