libjpeg(2)

/* JPEG解压缩的示例程序。我们假定源文件名被传入。我们想要成功返回1,错误为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;


void my_error_exit (j_common_ptr cinfo)
{
  /* cinfo-> err真的指向一个my_error_mgr结构,所以强制指针*/
  my_error_ptr myerr = (my_error_ptr) cinfo->err;

  /*始终显示消息。*/
  /*如果我们选择,我们可以推迟这个,直到返回。*/
  (*cinfo->err->output_message) (cinfo);

  /*将控制返回到setjmp点*/
  longjmp(myerr->setjmp_buffer, 1);
}

int read_JPEG_file (char *filename)
{
  /*此结构体包含JPEG解压缩参数和指针工作空间(由JPEG库根据需要分配)*/
  struct jpeg_decompress_struct cinfo;
  /*我们使用我们的专用扩展JPEG错误处理程序。
   *请注意,此结构体必须与主要的JPEG参数一样的生存周期,以避免指针问题。
   */
  struct my_error_mgr jerr;

  FILE *infile;                 /* 源文件 */
  JSAMPARRAY buffer;            /* 输出行缓冲区*/
  int row_stride;               /* 输出缓冲区中的物理行宽 */

  /*在这个例子中,我们要做任何事情之前打开输入文件,
   *所以下面的setjmp()错误恢复可以假定文件是打开的。
   *使用“b”选项来fopen()要求它读取二进制文件。
   */
  if ((infile = fopen(filename, "rb")) == NULL) {
    fprintf(stderr, "can't open %s\n", filename);
    return 0;
  }

   /*步骤1:分配和初始化JPEG解压缩对象*/

  /*我们设置正常的JPEG错误例程,然后覆盖error_exit。*/
  cinfo.err = jpeg_std_error(&jerr.pub);
  jerr.pub.error_exit = my_error_exit;
  
   /*建立my_error_exit使用的setjmp返回上下文。*/
  if (setjmp(jerr.setjmp_buffer))
  {
    /*如果我们到达这里,JPEG代码发出了一个错误信号。
     *我们需要清理JPEG对象,关闭输入文件并返回。
     */
    jpeg_destroy_decompress(&cinfo);
    fclose(infile);
    return 0;
  }
   /*现在我们可以初始化JPEG解压缩对象。*/
  jpeg_create_decompress(&cinfo);

  /*步骤2:指定数据源(例如,文件)*/
  jpeg_stdio_src(&cinfo, infile);

  /*步骤3:使用jpeg_read_header()*/

  (void) jpeg_read_header(&cinfo, TRUE);
  /*我们可以忽略来自jpeg_read_header的返回值
   *(a)stdio数据源不可能暂停,
   *(b)我们通过TRUE来拒绝仅表格的JPEG文件作为错误。
   */

   /*步骤4:设置解压缩参数*/

   /*在本示例中,我们不需要更改任何设置的默认值
    * jpeg_read_header(),所以我们什么也不做。
    */

  /*步骤5:启动解压缩器*/

  (void) jpeg_start_decompress(&cinfo);
   /*我们可以忽略返回值,因为暂停是不可能的与stdio数据源。*/

  /*在阅读之前,我们可能需要做一些我们自己的设置数据。
   *在jpeg_start_decompress()之后,我们有正确的缩放
   *输出图像尺寸可用,以及输出颜色图
   *如果我们要求颜色量化。
   *在这个例子中,我们需要制作一个正确大小的输出工作缓冲区。
   */
   
  /*输出缓冲区中每行的JSAMPLE */
  row_stride = cinfo.output_width * cinfo.output_components;
  /*制作一行高的样本数组,当完成图像*/
  buffer = (*cinfo.mem->alloc_sarray)
                ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);

  /*步骤6:while(扫描线仍然被读取)*/
  /* jpeg_read_scanlines(...); */

  /*这里我们使用库的状态变量cinfo.output_scanline作为循环计数器*/
  while (cinfo.output_scanline < cinfo.output_height)
  {
    /* jpeg_read_scanlines需要一组指向扫描线的指针。
     *这里的数组只有一个元素长,但你可以要求一次扫描线一次,如果这样更方便。
     */
    (void) jpeg_read_scanlines(&cinfo, buffer, 1);
    /*假设put_scanline_someplace需要一个指针和样本计数。*/
    put_scanline_someplace(buffer[0], row_stride);
  }

  /*步骤7:完成减压*/
  (void) jpeg_finish_decompress(&cinfo);
  
   /*我们可以忽略返回值,因为暂停是不可能的与stdio数据源。*/
   
   /*第8步:释放JPEG解压缩对象*/

   /*这是一个重要的步骤,因为它会释放大量的内存。*/
  jpeg_destroy_decompress(&cinfo);

  /*在finish_decompress之后,我们可以关闭输入文件。
   *这里我们推迟它,直到没有更多的JPEG错误是可能的,以便简化上面的setjmp错误逻辑。
   */
  fclose(infile);

 /*此时,您可能需要检查是否有损坏的数据发生警告(测试jerr.pub.num_warnings是否为零)*/

  return 1;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值