A.在解压JPEG文件的过程中,需要先读取JPEG文件。读取JPEG文件的函数在jdatasrc.c文件中,名为fill_input_buffer,代码如下图所示:
在读取jpeg文件解码过程中,有一个缓冲区专门用于解码操作,当这个缓冲区为空时,fill_input_buffer函数就会被调用
在上图标记为1的代码行中,INPUT_BUF_SIZE宏的值是4096,JFREAD是一个fread相关的宏,因此这句代码是从jpeg文件中读取4096个字节并保存到指定的缓冲区中
上图标记为2的代码段,用于处理读取到文件尾端的情况。在大多数情况下,最好的方案是产生一个警告信息并且插入一个伪EOI标记(EOI为jpeg文件末尾的标记)。但是有一种情况,比如解压的jpeg文件实际上是一个0字节的空文件,此时必须调用ERREXIT强行退出。
当正确读取文件数据到缓冲区后,需要重新设置缓冲区操作的相关指针,如上图标记为3的代码所示。其中next_input_type是指下一次进行缓冲区操作指向的指针,bytes_in_buffer代表当前缓冲区中实际有效的字节数。因为在fill_input_buffer中已经读取了文件,因此start_of_file必须设置为FALSE;
在fill_input_bufer函数中下断点,同时运行jpg转bmp的程序,即可看到如下调用堆栈:
B.在BMP转JPG文件过程中,需要将编码的内容保存到jpeg文件中,将数据写入文件的代码在文件jdatadst.c中,包含empty_output_buffer和term_destination。当缓冲区填充满的时候,程序就会调用empty_output_buffer函数,当在编码末尾调用jpeg_finish_compress时,在jpeg_finish_compress函数中就会调用term_destination,将缓冲区最后的数据写入到文件中。
empty_output_buffer函数的代码如下图所示:
在上图代码段1中,将缓冲区中OUTPUT_BUF_SIZE(4096)个字节写入到jpeg文件中。若写入文件的返回值不等于OUTPUT_BUF_SIZE,则意味着当前不是清空缓冲区到文件的时候(需要在term_destination函数中写入文件),调用ERREXIT退出。
在上图代码段2中,重置缓冲区参数。next_output_byte指向下一次缓冲区操作的指针,free_in_buffer代表当前缓冲区空闲未用的字节数
在empty_output_buffer函数中下断点,运行bmp转jpg文件的程序,可以看到如下调用堆栈
term_destination函数的代码如下图所示:
在Bmp转jpg的程序中,在term_destination函数中下断点,运行,可以看到如下的堆栈