首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在使用libjpeg读取JPEG文件时需要帮助

在使用libjpeg读取JPEG文件时需要帮助
EN

Stack Overflow用户
提问于 2011-04-11 02:26:10
回答 4查看 34.4K关注 0票数 11

我遵循libjpeg示例文件中的示例代码,但是无法读取图像数据。

我有以下的结构,我创建了这个结构的一个实例。

代码语言:javascript
复制
 struct ImageData {
        unsigned char *pixels;
        long  width;
        long height;
    };

    ImageData *imageData;

下面是我的read_JPEG_file函数:

代码语言:javascript
复制
int read_JPEG_file (char * filename)
{
    struct jpeg_decompress_struct cinfo;
    struct my_error_mgr jerr;

    /* More stuff */
    FILE * infile;      /* source file */
    JSAMPARRAY buffer;      /* Output row buffer */
    int row_stride;     /* physical row width in output buffer */

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

    /* Step 1: allocate and initialize JPEG decompression object */

    /* We set up the normal JPEG error routines, then override error_exit. */
    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = my_error_exit;
    /* Establish the setjmp return context for my_error_exit to use. */
    if (setjmp(jerr.setjmp_buffer)) {

        jpeg_destroy_decompress(&cinfo);
        fclose(infile);
        return 0;
    }
    /* Now we can initialize the JPEG decompression object. */
    jpeg_create_decompress(&cinfo);

    /* Step 2: specify data source (eg, a file) */

    jpeg_stdio_src(&cinfo, infile);

    /* Step 3: read file parameters with jpeg_read_header() */

    (void) jpeg_read_header(&cinfo, TRUE);
    /* Step 4: set parameters for decompression */

    /* In this example, we don't need to change any of the defaults set by
     * jpeg_read_header(), so we do nothing here.
     */

    /* Step 5: Start decompressor */

    (void) jpeg_start_decompress(&cinfo);


    row_stride = cinfo.output_width * cinfo.output_components;
    /* Make a one-row-high sample array that will go away when done with image */
    buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);

    imageData = new ImageData;
    imageData->width = cinfo.output_width;
    imageData->height = cinfo.output_height;

    imageData->pixels = new unsigned char [cinfo.output_width * cinfo.output_height * cinfo.output_components];
    long counter = 0;

   //step 6, read the image line by line
    while (cinfo.output_scanline < cinfo.output_height) {
        //IT ALWAYS crash ON THIS JPEG_READ_SCANLINES FUNCTION CALL BELOW
        (void) jpeg_read_scanlines(&cinfo, (JSAMPARRAY)(imageData->pixels), 1);
        counter +=row_stride;

    }
       /* Step 7: Finish decompression */

    (void) jpeg_finish_decompress(&cinfo);
    /* Step 8: Release JPEG decompression object */

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

    fclose(infile);
    /* And we're done! */
    return 1;
}

在上面的步骤6中,在这个JPEG_READ_SCANLINES函数上总是失败。我在那条线上有一个"EXC_BAD_ACCESS“信号。

有谁知道,或者有一些关于使用libjpeg读取.jpg文件的工作示例,您可以在这里共享吗?我检查了imageData->像素的大小,并将其与jpeg文件本身的大小进行了比较,并且它具有相同的大小。这个变量的内存也是动态分配的,所以我知道它不是内存问题。

有什么想法吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-04-11 03:24:21

jpeg_read_scanlines函数接收指针数组(而不是图像数据->像素等像素的直接指针)。因此,我们应该首先创建一个JSAMPARRAY:

代码语言:javascript
复制
int buffer_height = 1;
JSAMPARRAY buffer = (JSAMPARRAY)malloc(sizeof(JSAMPROW) * buffer_height);
buffer[0] = (JSAMPROW)malloc(sizeof(JSAMPLE) * row_stride);

在您的代码中,您创建了一个带有"cinfo.mem->alloc_sarray“的”缓冲区“,但您从未使用过它。最后一步是将“缓冲区”作为jpeg_read_scanlines的参数传递:

代码语言:javascript
复制
while (cinfo.output_scanline < cinfo.output_height) {
  jpeg_read_scanlines(&cinfo, buffer, 1);
  memcpy(imageData->pixels+counter, buffer[0], row_stride);
  counter += row_stride;
}

请注意,我们使用的是“imageData->像素+计数器”,而不仅仅是代码中的“imageData->像素”。通过这种方式,我们在整个“imageData->像素”内存块中逐行写入。

票数 6
EN

Stack Overflow用户

发布于 2014-03-17 19:22:14

下面是读取jpeg图像的示例:

代码语言:javascript
复制
/***************************************************
    To read a jpg image file and download
    it as a texture map for openGL
    Derived from Tom Lane's example.c
    -- Obtain & install jpeg stuff from web 
    (jpeglib.h, jerror.h jmore.h, jconfig.h,jpeg.lib)
****************************************************/
#include <jpeglib.h>    
#include <jerror.h>
//================================
GLuint LoadJPEG(char* FileName)
//================================
{
  unsigned long x, y;
  unsigned int texture_id;
  unsigned long data_size;     // length of the file
  int channels;               //  3 =>RGB   4 =>RGBA 
  unsigned int type;  
  unsigned char * rowptr[1];    // pointer to an array
  unsigned char * jdata;        // data for the image
  struct jpeg_decompress_struct info; //for our jpeg info
  struct jpeg_error_mgr err;          //the error handler

  FILE* file = fopen(FileName, "rb");  //open the file

  info.err = jpeg_std_error(& err);     
  jpeg_create_decompress(& info);   //fills info structure

  //if the jpeg file doesn't load
  if(!file) {
     fprintf(stderr, "Error reading JPEG file %s!", FileName);
     return 0;
  }

  jpeg_stdio_src(&info, file);    
  jpeg_read_header(&info, TRUE);   // read jpeg file header

  jpeg_start_decompress(&info);    // decompress the file

  //set width and height
  x = info.output_width;
  y = info.output_height;
  channels = info.num_components;
  type = GL_RGB;
  if(channels == 4) type = GL_RGBA;

  data_size = x * y * 3;

  //--------------------------------------------
  // read scanlines one at a time & put bytes 
  //    in jdata[] array. Assumes an RGB image
  //--------------------------------------------
  jdata = (unsigned char *)malloc(data_size);
  while (info.output_scanline < info.output_height) // loop
  {
    // Enable jpeg_read_scanlines() to fill our jdata array
    rowptr[0] = (unsigned char *)jdata +  // secret to method
            3* info.output_width * info.output_scanline; 

    jpeg_read_scanlines(&info, rowptr, 1);
  }
  //---------------------------------------------------

  jpeg_finish_decompress(&info);   //finish decompressing

  //----- create OpenGL tex map (omit if not needed) --------
  glGenTextures(1,&texture_id);
  glBindTexture(GL_TEXTURE_2D, texture_id);
  gluBuild2DMipmaps(GL_TEXTURE_2D,3,x,y,GL_RGB,GL_UNSIGNED_BYTE,jdata);

  jpeg_destroy_decompress(&info);
  fclose(file);                    //close the file
  free(jdata);

  return texture_id;    // for OpenGL tex maps
}
票数 13
EN

Stack Overflow用户

发布于 2012-09-07 21:19:56

就像达卡普说的,它期待着一个JSAMPARRAY。尽管如此,如果您愿意,可以直接写入imageData->像素数组。你只需要这样做:

代码语言:javascript
复制
// Allocate imageData->pixels to be the correct size, start decompress and all
// that jazz, like you did in your code. Skip allocating buffer though.
// ...

JSAMPROW output_data;
unsigned int scanline_len = cinfo.output_width * cinfo.output_components;

unsigned int scanline_count = 0;
while (cinfo.output_scanline < cinfo.output_height)
{
    output_data = (imageData->pixels + (scanline_count * scanline_len));
    jpeg_read_scanlines(&cinfo, &output_data, 1);
    scanline_count++;
}

然后,您可以跳过整个缓冲区的分配。使用memcpy很好,但是如果不需要额外的拷贝,为什么还要额外复制呢?

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5616216

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档