/* 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;
}
libjpeg(2)
最新推荐文章于 2021-05-26 09:50:38 发布