![](/kaifa.jpg)
winrar注册-360安全卫士下载 软件
![丢失ijl15 dll](/uploads/image/0046.jpg)
2023年3月30日发(作者:百度云资源分享群)
第一章准备
一、需要以下的三个库
动态链接库(),
引入库(),
头文件(IJL.H).
二、建立IJL应用程序的步骤
1.在每一个将调用IJL函数的模块中包含头文件IJL.H
2.在项目中增加
3.编译程序。
第二章结构描述
现在最多的JPEG模式是基本基线模式和扩展基线模式的连续离散余弦变换。IJL1.5完全支
持这两种模式的编码及解码,
一、IJL的I/O数据结构体系
1.内存中含有一个常规的象素buffer.
2.一个标准的I/O文件包含JPEGbitstream.
3.一个内存buffer包含一个JPEGbitstream.
二、支持的数据格式
1、Top-downorbottom-uppixelbuffers.
在Windows中,device-independentbitmaps(DIBs)数据在内存中有两种排列方式
bottom-upandtop-down。bottom-upDIB,buffer是从最底行的最左象素开始,接着是次底
行.而顶行的数据是在buffer的最后。GDI使用的Bottom-upDIB。top-downDIB的排列
顺序是颠倒的.最顶行最左侧的象素是buffer的第一个字节,而最底行的象素在buffer的最
后。DirectDraw使用top-downDIBs。RGBDIBs,图象的排列方式由
"/en-us/library/"BITMAPINFOHEADER结构的
成员变量biHeight来指示。如biHeight是正数,图象是bottom-up.如果biHeight是负数,
图象是top-down。YUV格式的DIBs总是top-down,biHeight的符号被忽略。
2、象素缓冲区与自定义行尾填充。
3、使用普通象素缓冲之内的一个矩形。
4、从一个大的JPEG图象中指定矩形解码。
5、JPEG文件交换格式(JFIF)的编码和解码
IJL提供JFIFfiles的解码,JFIF规格版本是1.01and1.02。编码是JFIFversion1.01.。
IJL也支持解码嵌入式的未压缩的缩略图,使用1or3bytes/pixel适应JFIFversions1.01
and1.02.压缩的缩略图未被支持。
数据精度必须是每颜色通道8-bits。
三、JPEG属性和数据存贮
IJL的“JPEG属性”包括全局的和图象属性的JPEG信息。控制结构确定I/O特性的处理
选项,象二次抽样和颜色转换需求。
IJL使用JPEG_CORE_PROPERTIES结构存放JPEG属性数据。这个结构被描述为两
个部分,第一部份由一组封包的共用库参数组成,另一部份由低级的嵌入的结构组成。Figure3-2
与附件B-DataStructureandTypeDefinitions).
用户必须尊循以下的两个JPEG_CORE_PROPERTIES规则:
1.用户必须提供(allocate)JPEG_CORE_PROPERTIES数据结构。
2.同样的JPEG_CORE_PROPERTIES数据结构可能被一连串的JPEGencodings和/或
decodings在初始化时和清理时再生。
JPEG_PROPERTIES是低级的数据结构且它包含一个在JPEG_CORE_PROPERTIES中
每个高级数据结构的复本及一些附加字段。IJL内部使用JPEG_PROPERTIES,而不是
JPEG_CORE_PROPERTIES,所以这个结构隔离了内部的变量。
对于高级用户JPEG_PROPERTIES数据结构可能会使用一些扩充的接口性能。例如:用户
可能要自定义的Huffman表或量化表(quantizationtables)直接至JPEG_PROPERTIES,而
越过默认表(Chapter7,AdvancedIJLFeatures有更多的信息)。
JPEG_CORE_PROPERTIESandJPEG_PROPERTIES数据结构的默认值在头文件IJL.H中的
注释中
四、多线程支持
JPEG_CORE_PROPERTIES被设计在局部为单线程。是“锁定”的无参数将允许多个线
程访问相同的JPEG_CORE_PROPERTIES结构。但是,所有的实现细节,IJL允许多个
JPEG_CORE_PROPERTIES存储和代码访问由多个线程。
第三章接口详述
IJL提供标准C的函数,其模仿简单的读/写栈来建立JPEG_CORE_PROPERTIES数据结
构。
JPEG_CORE_PROPERTIES的内部函数负责初始化、释放内存,及与IJL交换数据及参数。
IJL函数调用失败时返回一个错误码;调用成功返回的是正的(IJL_OK,IJL_INTERRUPT_OK,
IJL_ROI_OK)成功码。了解详情参看AppendixB-DataStructureandTypeDefinitions。转换
错误码至一个文本描述,使用函数ijlErrorStr()。
函数ijlGetLibVersion()返回IJL库的版本及其它相关信息。
注意,ijlErrorStr()和ijlGetLibVersion()函数返回的是一个指向静态变量的指针,所以应用程
序不需要释放这些指针。
TheIntel®JPEGLibraryApplicationProgrammingInterface
//初始化IJL.
IJLERRijlInit(JPEG_CORE_PROPERTIES*jcprops);
//CleanuptheIJL.
IJLERRijlFree(JPEG_CORE_PROPERTIES*jcprops);
//UsetheIJLtoreaddatafromabufferorafile.
IJLERRijlRead(JPEG_CORE_PROPERTIES*jcprops,IJLIOTYPEiotype);
//UsetheIJLtowritedataintoabufferorafile.
IJLERRijlWrite(JPEG_CORE_PROPERTIES*jcprops,IJLIOTYPEiotype);
//ReturntheversionnumberoftheIJL.
constIJLibVersion*ijlGetLibVersion();
//Returnapointertoastringwitherrordescription.
constchar*ijlErrorStr(IJLERRcode);
此段描述设计及执行一些IJL的共用特性,及一些例子。
一、初始化
在使用之前,IJL必须初始化,使用ijlInit()完成初始化。在每一个分配
JPEG_CORE_PROPERTIES数据结构的时候,只能进行一次初始化。
如果一个程序需要调用多个编、解码函数,应用程序需要在任一调用之前调用ijlInit()更多的
初始化需要在每个编、解码调用之间进行。
使用ijlFree()释放JPEG_CORE_PROPERTIES且必须与初始化一一对应。
二、释放
用ijlFree()释放内存及相关的系统资源。
三、读数据
使用ijlRead(JPEG_CORE_PROPERTIES*jcprops,IJLIOTYPEiotype)函数访问JPEG的
压缩数据。第二个参数用来指定在解码期间的JPEG的数据单元(如:一个文件或一个缓存区),
访问模式(modeofaccess),及缩放比例。
有如下两种约定:XXXX代表访问模式
_JBUFF_XXXX(表示JPEG数据是一个缓存).
_JFILE_XXXX(表示JPEG数据是一个标准文件).
读数据时,访问模式必须是:READPARAMS,READHEADER,READENTROPY,
READWHOLEIMAGE,,READONEHALF,READONEQUARTER,READONEEIGHTH,
READTHUMBNAIL。
IJLIOTYPE描述
IJL_JXXXX_READPARAMS表示读JPEG参数如:高,宽,通道数量,二次抽样等。,
例如如下的分析:
SOI|[tables/misc]likeAPPnandDQT|
SOF|[tables/misc]likeDHT|stopsatSOS
Note:bitstreammuststartwithSOImarker.
IJL_JXXXX_READHEADER表示读一些特征数据,如:霍夫曼表,量化表,其它杂项。
例如:
SOI|[tables/misc]|EOI(orstopsatSOForSOS)
Note:bitstreammuststartwithSOImarker.
IJL_JXXXX_READENTROPY表示读压缩图片的格式。与READWHOLEIMAGE相同,
除了位流可能包含的特征表。.
Forexample:
SOI|[tables/misc]|SOF[tables/misc]likeDHT|SOS|
EOI
Note:inthiscaseonly(READENTROPY),APP0
segmentsareskippedover.
IJL_JXXXX_READWHOLEIMAGE表示读压缩图片数据的交换格式,如:整个的JPEG位流。
例如:
SOI|[tables/misc]likeAPPnandDQT|
SOF[tables/misc]likeDHT|SOS|EOI
IJL_JXXXX_READONEHALF图象解码比例是½
(SeeREADENTROPY).
IJL_JXXXX_READONEQUARTER图象解码比例是¼.
(SeeREADENTROPY).
IJL_JXXXX_READONEEIGHTH图象解码比例是1/8
(SeeREADENTROPY).
IJL_JXXXX_READTHUMBNAIL试图解码在数据流中嵌入的缩略图
(SeeREADPARAMS).
READPARAMS被用来确定JPEG的高和宽,用以分配输出的缓存或显示引擎。然后,读
其余的数据使用READWHOLEIMAGEorREADENTROPY。
READHEADER被用于分析压缩数据规格表,之后使用READENTROPY来得到压缩的图
象数据。
READHEADER/READENTROPY参数对是一个最优的读取JPEG解码格式的方案。
WhendecodingaJPEGbitstreamthefollowingmarkers,andtheircorresponding
segmentsifapplicable,arenotprocessedbytheIJL(i.e.,theyareskippedover):APPn(except
APP0andAPP14),DAC,DHP,DNL,EXP,JPGn,RES,SOFn(exceptSOF0,SOF1,and
SOF2),nmarkers(exceptSOF0,SOF1,andSOF2)willcausethe
IJL_UNSUPPORTED_FRAMEerror.
四、写数据
ijlWrite(JPEG_CORE_PROPERTIES*,IJLIOTYPEiotype)是写入数据的接口函数。第二个
参数是访问方式,但不能指定图象的比例及嵌入式缩略图。
_JBUFF_XXXX(指定JPEG压缩数据的内存缓存区).
_JFILE_XXXX(指定JPEG数据的文件).
写入数据时,访问方式必须是WRITEHEADER,WRITEENTROPY,or
WRITEWHOLEIMAGE。
详细描述见下表:
IJLIOTYPE描述
IJL_JXXXX_WRITEHEADER指定数据流的压缩格式规格表。
下面的标志将被写入:
SOI|tablesDQTandDHT|EOI
IJL_JXXXX_WRITEENTROPY指定压缩图片数据。
与WRITEWHOLEIMAGE相同,只是不包含规格表
数据。
下面的标志将被写入:
SOI|SOF|[DRI]|SOS|EOI
IJL_JXXXX_WRITEWHOLEIMAGE指定写入JPEG文件交换格式(如:JPEGusing
JFIF).
下面的标志将被写入:
SOI|tables/miscAPP0,DQT,DHT|SOF|[DRI]|
SOS|EOI
WRITEHEADER通常被用于写入压缩格式规格表,它与WRITEENTROPY一般成对使用
于JPEG编码。当编码时,IJL写入COM标志片段,如果未指定该片段,将写入默认的“Intel®
JPEGLibrary,[
五、打开一个JPEG图片
普通的解码算法:
1.分配JPEG_CORE_PROPERTIES
2.初始化IJL.
3.得到JPEG图象尺寸及其它
4.设置显示参数,分配输出缓存.
5.得到JPEG数据
6.关闭IJL
下面的代码使用IJL解码一个JPEG图象文件。请参照AppendixB-DataStructureand
TypeDefinitions以得到IJL数据结构的定义,默认值,数据类型定义和错误码的详细的信息。
//----------------------------------------------------------
//AnexampleusingtheIntelRJPEGLibrary:
//--DecodeaJPEGimagefromaJFIFfiletogeneralpixelbuffer.
//----------------------------------------------------------
BOOLDecodeJPGFileToGeneralBuffer(
LPCSTRlpszPathName,
DWORD*width,
DWORD*height,
DWORD*nchannels,
BYTE**buffer)
{
BOOLbres;//returnValue
IJLERRjerr;
DWORDx=0;//pixelsinscanline
DWORDy=0;//numberofscanlines
DWORDc=0;//numberofchannels
DWORDwholeimagesize;
BYTE*pixel_buf=NULL;
//AllocatetheIJLJPEG_CORE_PROPERTIESstructure.
JPEG_CORE_PROPERTIESjcprops;
bres=TRUE;
__try
{
//InitializetheIntelRJPEGLibrary.
jerr=ijlInit(&jcprops);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
//GetinformationontheJPEGimage(i.e.,width,height,andchannels).
e=const_cast
jerr=ijlRead(&jcprops,IJL_JFILE_READPARAMS);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
//Setuplocaldata.
x=th;
y=ght;
c=3;//Decodeintoa3channelpixelbuffer.
//Computesizeofdesiredpixelbuffer.
wholeimagesize=(x*y*c);
//Allocatememorytoholdthedecompressedimagedata.
pixel_buf=newBYTE[wholeimagesize];
if(NULL==pixel_buf)
{
bres=FALSE;
__leave;
}
//SetuptheinfoonthedesiredDIBproperties.
th=x;
ght=y;//Impliesabottom-upDIB.
nnels=c;
or=IJL_BGR;
Bytes=0;
es=pixel_buf;
//设置JPG色彩空间…这总是有一些推策,因为JPEG是个“色盲”
//(也就是说位流中没有告诉你是什么色彩空间)设置JPEG色彩空间,
//本例中我们假定JFIF图象文件是3个通道YCbCr色彩空间和1个通道的Y色彩空间.
switch(nnels)
{
case1:
{
or=IJL_G;
break;
}
case3:
{
or=IJL_YCBCR;
break;
}
default:
{
//Thiscatcheseverythingelse,
//butnocolortwistwillbeperformedbytheIJL.
or=(IJL_COLOR)IJL_OTHER;
or=(IJL_COLOR)IJL_OTHER;
break;
}
}
//NowgettheactualJPEGimagedataintothepixelbuffer.
jerr=ijlRead(&jcprops,IJL_JFILE_READWHOLEIMAGE);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
}//__try
__finally
{
if(FALSE==bres)
{
if(NULL!=pixel_buf)
{
delete[]pixel_buf;
pixel_buf=NULL;
}
}
//CleanuptheIntelRJPEGLibrary.
ijlFree(&jcprops);
*width=x;
*height=y;
*nchannels=c;
*buffer=pixel_buf;
}//__finally
returnbres;
}//DecodeJPGFileToGeneralBuffer()
注意:这段代码是解码一个JPEG图象到一个“常规的象素缓存”因而这个缓存不是专用的。
前面讲过,Chapter3,ArchitectureDescription,IJL被设计为工作于普通的缓存,需要用户自行
处理缓存的分配及数据保存,IJL负责读或写缓存。缓存的地址通过IJL的
JPEG_CORE_PROPERTIES结构中DIBBytes字段来传递。
本例中用户要解码到一个Windows*DIB,这个缓存的尺寸计算可能会是错误的,如果用户
需要确保一个WindowsDIB的4字节队列的缓存,可以使用包含在ijl.h头文件中的
IJL_DIB_PAD_BYTES宏,这个宏定义是:
#defineIJL_DIB_PAD_BYTES(width,nchannels)
(((width*nchannels)+(sizeof(DWORD)-1))&(~(sizeof(DWORD)-1))-(width*
nchannels))
相应的DIBPadBytes的值能够容易的计算:
Bytes=IJL_DIB_PAD_BYTES(width,nchannels)
其中width是图象的象素宽度,nchannels是通道的数量。
下面的代码举例说明如何从一个图象解码到一个WindowsDIB.
//----------------------------------------------------------
//AnexampleusingtheIntelRJPEGLibrary:
//--DecodeaJPEGimagefromaJFIFfiletoWindowsDIB.
//----------------------------------------------------------
BOOLDecodeJPGFileToDIB(
LPCSTRlpszPathName,
BITMAPINFOHEADER**dib)
{
BOOLbres;
IJLERRjerr;
DWORDwidth;
DWORDheight;
DWORDnchannels;
DWORDdib_line_width;
DWORDdib_pad_bytes;
DWORDwholeimagesize;
BYTE*buffer=NULL;
BITMAPINFOHEADER*bmih=NULL;
//AllocatetheIJLJPEG_CORE_PROPERTIESstructure.
JPEG_CORE_PROPERTIESjcprops;
bres=TRUE;
__try
{
//InitializetheIntelRJPEGLibrary.
jerr=ijlInit(&jcprops);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
//GetinformationontheJPEGimage
//(i.e.,width,height,andchannels).
e=const_cast
jerr=ijlRead(&jcprops,IJL_JFILE_READPARAMS);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
//Setuplocaldata.
width=th;
height=ght;
nchannels=3;//Decodeintoa3channelpixelbuffer.
//ComputeDIB填充
dib_line_width=width*nchannels;
dib_pad_bytes=IJL_DIB_PAD_BYTES(width,nchannels);
//Computesizeofdesiredpixelbuffer.
wholeimagesize=(dib_line_width+dib_pad_bytes)*height;
//Allocatememorytoholdthedecompressedimagedata.
buffer=newBYTE[sizeof(BITMAPINFOHEADER)+wholeimagesize];
if(NULL==buffer)
{
bres=FALSE;
__leave;
}
bmih=reinterpret_cast
bmih->biSize=sizeof(BITMAPINFOHEADER);
bmih->biWidth=width;
bmih->biHeight=height;
bmih->biPlanes=1;
bmih->biBitCount=24;
bmih->biCompression=BI_RGB;
bmih->biSizeImage=0;
bmih->biXPelsPerMeter=0;
bmih->biYPelsPerMeter=0;
bmih->biClrUsed=0;
bmih->biClrImportant=0;
//SetuptheinfoonthedesiredDIBproperties.
th=width;
ght=height;//Impliesabottom-upDIB.
nnels=nchannels;
or=IJL_BGR;
Bytes=dib_pad_bytes;
es=reinterpret_cast
//SettheJPGcolorspace...thiswillalwaysbe
//somewhatofaneducatedguessatbestbecauseJPEG
//is"colorblind"(i.e.,nothinginthebitstream
//tellsyouwhatcolorspacethedatawasencodedfrom).
//However,inthisexampleweassumethatweare
//readingJFIFfileswhichmeansthat3channelimages
//areintheYCbCrcolorspaceand1channelimagesare
//intheYcolorspace.
switch(nnels)
{
case1:
{
or=IJL_G;
break;
}
case3:
{
or=IJL_YCBCR;
break;
}
default:
{
//Thiscatcheseverythingelse,butno
//colortwistwillbeperformedbytheIJL.
or=(IJL_COLOR)IJL_OTHER;
or=(IJL_COLOR)IJL_OTHER;
break;
}
}
//NowgettheactualJPEGimagedataintothepixelbuffer.
jerr=ijlRead(&jcprops,IJL_JFILE_READWHOLEIMAGE);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
}//__try
__finally
{
if(FALSE==bres)
{
if(NULL!=buffer)
{
delete[]buffer;
buffer=NULL;
}
}
//CleanuptheIntelRJPEGLibrary.
ijlFree(&jcprops);
*dib=bmih;
}//__finally
returnbres;
}//DecodeJPGFileToDIB()
六、建立JPEG图象
此段代码针对普通的JPEG图象:
1.初始化IJL.
2.设置编码参数(如果与默认值不同).
3.写图象数据给IJL.
4.关闭IJL.
下面的代码段举例说明如何使用IJL从一个JFIF图象缓存编码。请参照AppendixB-Data
StructureandTypeDefinitions查看更多有关数据结构等信息。
//----------------------------------------------------------
//AnexampleusingtheIntelRJPEGLibrary:
//--EncodeaJFIFfilefromWindowsDIB.
//----------------------------------------------------------
BOOLEncodeJPGFileFromDIB(
LPCSTRlpszPathName,
BITMAPINFOHEADER*bmih)
{
BOOLbres;
IJLERRjerr;
DWORDdib_pad_bytes;
//AllocatetheIJLJPEG_CORE_PROPERTIESstructure.
JPEG_CORE_PROPERTIESjcprops;
bres=TRUE;
__try
{
//InitializetheIntelRJPEGLibrary.
jerr=ijlInit(&jcprops);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
if(bmih->biBitCount!=24)
{
//notsupportedpaletteimages
bres=FALSE;
__leave;
}
dib_pad_bytes=IJL_DIB_PAD_BYTES(bmih->biWidth,3);
//Setupinformationtowritefromthepixelbuffer.
th=bmih->biWidth;
ght=bmih->biHeight;//Impliesabottom-upDIB.
es=reinterpret_cast
sizeof(BITMAPINFOHEADER);
Bytes=dib_pad_bytes;
//Note:thefollowingaredefaultvaluesandthus
//donotneedtobeset.
nnels=3;
or=IJL_BGR;
e=const_cast
//SpecifyJPEGfilecreationparameters.
th=bmih->biWidth;
ght=bmih->biHeight;
//Note:thefollowingaredefaultvaluesandthus
//donotneedtobeset.
nnels=3;
or=IJL_YCBCR;
sampling=IJL_411;//4:1:1subsampling.
ty=75;//Select"good"imagequality
//WritetheactualJPEGimagefromthepixelbuffer.
jerr=ijlWrite(&jcprops,IJL_JFILE_WRITEWHOLEIMAGE);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
}//__try
__finally
{
//CleanuptheIntelRJPEGLibrary.
ijlFree(&jcprops);
}
returnbres;
}//EncodeJPGFileFromDIB()
七、中断编码或解码
IJL可以在编码和解码时中断,它可以被JPEG_PROPERTIES中定义的中断标志在任一时间
中断。
IJL将在完成当前的最小编码单位(MCU)时返回状态标志IJL_INTERRUPT_OK。编解码过程
也可以在原位恢复执行,只需使用ijlRead()或ijlWrite()函数即可恢复。用户可以通过
JPEG_PROPERTIES中的roiIJL_RECT结构的left和top变量计算出定位。
下面的例子中,程序读一个JPEG数据中的最小片段至指定的缓存区,然后程序返回并重复
这个过程,直到整个图象被解码完成。这个函数可以用做定时的中止JPEG的编解码过程。
//----------------------------------------------------------
//AnexampleusingtheIntelRJPEGLibrary:
//--Interrupteddecoding.
//----------------------------------------------------------
//Inthisexample,wearedoingfullscaledecoding.
//Itcouldalsobeanyofthescaleddecodingmodes.
BOOLDecodeJPGFileInterrupted(LPCSTRlpszPathName)
{
BOOLbres;
IJLERRjerr;
DWORDwidth;
DWORDheight;
DWORDnchannels;
DWORDwholeimagesize;
BYTE*pixel_buf=NULL;
//AllocatetheIJLJPEG_CORE_PROPERTIESstructure.
JPEG_CORE_PROPERTIESjcprops;
bres=TRUE;
__try
{
//InitializetheIntelRJPEGLibrary.
jerr=ijlInit(&jcprops);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
e=const_cast
//GetinformationontheJPEGimage
//(i.e.,width,height,andchannels).
jerr=ijlRead(&jcprops,IJL_JFILE_READPARAMS);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
//Setuplocaldata.
width=th;
height=ght;
nchannels=3;//Decodeintoa3channelpixelbuffer.
//Computesizeofdesiredpixelbuffer.
wholeimagesize=(width*height*nchannels);
//Allocatememorytoholdthedecompressedimagedata.
pixel_buf=newBYTE[wholeimagesize];
if(NULL==pixel_buf)
{
bres=FALSE;
__leave;
}
//SetuptheinfoonthedesiredDIBproperties.
th=width;
ght=height;//Impliesabottom-upDIB.
nnels=nchannels;
or=IJL_BGR;
Bytes=0;
es=pixel_buf;
//SettheJPGcolorspace...thiswillalwaysbe
//somewhatofaneducatedguessatbestbecauseJPEG
//is"colorblind"(i.e.,nothinginthebitstream
//tellsyouwhatcolorspacethedatawasencodedfrom).
//However,inthisexampleweassumethatweare
//readingJFIFfileswhichmeansthat3channelimages
//areintheYCbCrcolorspaceand1channelimagesare
//intheYcolorspace.
switch(nnels)
{
case1:
{
or=IJL_G;
break;
}
case3:
{
or=IJL_YCBCR;
break;
}
default:
{
//Thiscatcheseverythingelse,butno
//colortwistwillbeperformedbytheIJL.
or=(IJL_COLOR)IJL_OTHER;
or=(IJL_COLOR)IJL_OTHER;
break;
}
}
do
{
//SincetheROIvaluesareupdatedfollowing
//to"reset"theROI
//valuessothatwecontinuetoprocessover
//theentireimage.
=0;
=0;
=0;
=0;
upt=TRUE;
jerr=ijlRead(&jcprops,IJL_JFILE_READENTROPY);
}while(IJL_INTERRUPT_OK==jerr);
//
//...nowyouprobablywanttodosomethingwiththe
//decompressedimagelikedisplayit...
//
}//__try
__finally
{
if(NULL!=pixel_buf)
{
delete[]pixel_buf;
}
//CleanuptheIntelRJPEGLibrary.
ijlFree(&jcprops);
}
returnbres;
}//DecodeJPGFileInterrupted()
//----------------------------------------------------------
//AnexampleusingtheIntelRJPEGLibrary:
//--Decodeimagerowbyrow.
//----------------------------------------------------------
BOOLDecodeRowByRow(
LPCSTRlpszJpgName,
LPCSTRlpszBmpName)
{
intcnt;
intwidth;
intheight;
intnchannels;
intbmp_pad;
intbmp_row_size;
intbmp_buf_size;
intcurrent_row;
BOOLbres;
IJLERRjerr;
FILE*out_file=NULL;
BYTE*bmp_bits=NULL;
BYTE*bmp_row=NULL;
BYTE*bmp_buf=NULL;
LPBITMAPFILEHEADERlpbmfh=NULL;
LPBITMAPINFOHEADERlpbmih=NULL;
IJL_RECTlocal_roi;
JPEG_CORE_PROPERTIESjcprops;
bres=TRUE;
__try
{
//InitializetheIntel(R)JPEGLibrary.
jerr=ijlInit(&jcprops);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
e=const_cast
//GetinformationontheJPEGimage(i.e.,width,height,and
channels).
jerr=ijlRead(&jcprops,IJL_JFILE_READPARAMS);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
width=th;
height=ght;
nchannels=3;
bmp_pad=IJL_DIB_PAD_BYTES(width,nchannels);
bmp_row_size=(width*nchannels)+bmp_pad;
//allocatebuffertoholdonerowDIBdata
bmp_row=newBYTE[bmp_row_size];
if(NULL==bmp_row)
{
bres=FALSE;
__leave;
}
memset(bmp_row,0,bmp_row_size);
bmp_buf_size=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
+bmp_row_size*height;
//allocatebuffertoholdentireDIB
bmp_buf=newBYTE[bmp_buf_size];
if(NULL==bmp_buf)
{
bres=FALSE;
__leave;
}
bmp_bits=reinterpret_cast
sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER));
th=width;
ght=height;
nnels=nchannels;
or=IJL_BGR;
Bytes=bmp_pad;
es=bmp_row;
//SettheJPGcolorspace...thiswillalwaysbe
//somewhatofaneducatedguessatbestbecauseJPEG
//is"colorblind"(i.e.,nothinginthebitstream
//tellsyouwhatcolorspacethedatawasencodedfrom).
//However,inthisexampleweassumethatweare
//readingJFIFfileswhichmeansthat3channelimages
//areintheYCbCrcolorspaceand1channelimagesare
//intheYcolorspace.
switch(nnels)
{
case1:
{
or=IJL_G;
break;
}
case3:
{
or=IJL_YCBCR;
break;
}
default:
{
//Thiscatcheseverythingelse,butno
//colortwistwillbeperformedbytheIJL.
or=(IJL_COLOR)IJL_OTHER;
or=(IJL_COLOR)IJL_OTHER;
break;
}
}
//
//Belowismaincodetodecodeimagerowbyrow
//
current_row=0;
do
{
//ROIisonerow
local_=0;
local_=current_row;
local_=width;
local_=current_row+1;
=local_roi;
//decodeROI
jerr=ijlRead(&jcprops,IJL_JFILE_READENTROPY);
if(IJL_ROI_OK!=jerr)
{
bres=FALSE;
__leave;
}
//copyrowdataandreverseroworder,toobtainbottom-left
DIB.
memcpy(bmp_bits+(height-1-current_row)*
bmp_row_size,bmp_row,bmp_row_size);
//advancetonextrow
current_row++;
}while(current_row!=height);
//
//Nowwehavedecodedimage,anddoanythingonit.
//Forexamplewritetofile...
//
lpbmfh=reinterpret_cast
lpbmfh->bfType='MB';
lpbmfh->bfSize=bmp_buf_size;
lpbmfh->bfReserved1=0;
lpbmfh->bfReserved2=0;
lpbmfh->bfOffBits=sizeof(BITMAPFILEHEADER)+
sizeof(BITMAPINFOHEADER);
lpbmih=reinterpret_cast
sizeof(BITMAPFILEHEADER));
lpbmih->biSize=sizeof(BITMAPINFOHEADER);
lpbmih->biWidth=width;
lpbmih->biHeight=height;
lpbmih->biPlanes=1;
lpbmih->biBitCount=24;
lpbmih->biCompression=BI_RGB;
lpbmih->biSizeImage=0;
lpbmih->biXPelsPerMeter=0;
lpbmih->biYPelsPerMeter=0;
lpbmih->biClrUsed=0;
lpbmih->biClrImportant=0;
out_file=fopen(lpszBmpName,"wb");
if(NULL==out_file)
{
bres=FALSE;
__leave;
}
cnt=fwrite(bmp_buf,sizeof(BYTE),lpbmfh->bfSize,out_file);
if(cnt!=lpbmfh->bfSize)
{
bres=FALSE;
__leave;
}
}//__try
__finally
{
if(NULL!=bmp_row)
{
delete[]bmp_row;
}
if(NULL!=bmp_buf)
{
delete[]bmp_buf;
}
if(NULL!=out_file)
{
fclose(out_file);
}
//CleanuptheIntelRJPEGLibrary.
ijlFree(&jcprops);
}
returnbres;
}//DecodeRowByRow()
//----------------------------------------------------------
//AnexampleusingtheIntelRJPEGLibrary:
//--EncodeimagebyoneMCUatatime.
//----------------------------------------------------------
/*
//get_dib_parameters()
//
//Purpose
//getsimagesizesfromBMPfile
//
//Parameters
//FILE*bmp_file-inputBMPfiletogetsdatafrom
//int*width-pointertovariabletostoreimagewidth
//int*height-pointertovariabletostoreimageheight
//int*nchannels-pointertovariabletostoreimagenumberof
channels
//
//Returns
//0-ifreadwassuccessfully,ifbmp_fileisvalid24bitsper
pixelbitmap
//-1-iferrorhasoccured
//
*/
staticintget_dib_parameters(
FILE*bmp_file,
int*width,
int*height,
int*nchannels)
{
intres;
intcnt;
BITMAPFILEHEADERbfh;
BITMAPINFOHEADERbih;
cnt=fread(&bfh,sizeof(BYTE),sizeof(BITMAPFILEHEADER),bmp_file);
if(cnt!=sizeof(BITMAPFILEHEADER))
{
res=-1;
gotoExit;
}
if(!='MB')
{
res=-1;
gotoExit;
}
cnt=fread(&bih,sizeof(BYTE),sizeof(BITMAPINFOHEADER),bmp_file);
if(cnt!=sizeof(BITMAPINFOHEADER))
{
res=-1;
gotoExit;
}
if(ount!=24||ression!=BI_RGB)
{
res=-1;
gotoExit;
}
*width=h;
*height=ht;
*nchannels=3;
res=0;
Exit:
returnres;
}//get_dib_parameters()
/*
//get_dib_chunk_data()
//
//Purpose
//getschunkofdatafromBMPfile.
//
//Parameters
//FILE*bmp_file-inputBMPfiletogetsdatafrom
//intdib_chunk_size-sizeofchunkofdata
//BYTE*dib_chunk_ptr-pointertostoredata
//
//Return
//0-ifreadwassuccessfully,evenifhavereachedtheendofa
file
//-1-iferrorhasoccured
//
//Note
//Itisassumedthatthefilepointerhasacorrectposition.
//Forbottom-upDIBs,itisnecessarytoinverttheorderofscan
lines
//rsimplificationwedonotmake
it.
//
*/
staticintget_dib_chunk_data(
FILE*bmp_file,
intdib_chunk_size,
BYTE*dib_chunk_ptr)
{
intcnt;
intres;
res=0;
cnt=fread(dib_chunk_ptr,sizeof(BYTE),dib_chunk_size,bmp_file);
if(cnt
{
res=ferror(bmp_file);
if(0!=res)
{
res=-1;
}
}
returnres;
}//get_dib_chunk_data()
/*
//ijl_compress_large_dib()
//
//Purpose
//todemonstrateonetechniquestocompresslargeDIBs
//onmculinebymculinebasis.
//
//Parameters
//char*bmp_file-ASCIIZstringwithinputBMPfilename
//char*jpg_file-ASCIIZstringwithoutputJPGfilename
//
//Returns
//0-ifsuccess
//-1-iferrorhasoccured
//
*/
staticintijl_compress_large_dib(
char*bmp_name,
char*jpg_name)
{
inti;
intj;
intres;
intwidth;
intheight;
intmcu_width;
intmcu_height;
intnum_x_mcu;
intnum_y_mcu;
intdib_line_size;
intnchannels;
intdib_chunk_size;
BYTE*dib_chunk_ptr;
FILE*bmp_file;
IJLERRjerr;
JPEG_CORE_PROPERTIESjcprops;
dib_chunk_ptr=NULL;
bmp_file=fopen(bmp_name,"rb");
if(NULL==bmp_file)
{
res=-1;
gotoExit;
}
//readsourceimageparameters
res=get_dib_parameters(bmp_file,&width,&height,&nchannels);
if(res!=0)
{
gotoExit;
}
jerr=ijlInit(&jcprops);
if(IJL_OK!=jerr)
{
res=-1;
gotoExit;
}
nnels=nchannels;
th=width;
ght=height;
Bytes=IJL_DIB_PAD_BYTES(width,nchannels);
or=IJL_BGR;
sampling=(IJL_DIBSUBSAMPLING)IJL_NONE;
e=jpg_name;
es=NULL;
eBytes=0;
nnels=nchannels;
th=width;
ght=height;
or=IJL_YCBCR;
sampling=IJL_411;
ty=75;
//sizesofmcudependonsubsampling
switch(sampling)
{
caseIJL_NONE:
mcu_width=8;
mcu_height=8;
break;
caseIJL_422:
mcu_width=16;
mcu_height=8;
break;
caseIJL_411:
mcu_width=16;
mcu_height=16;
break;
default:
res=-1;
gotoExit;
}
//calculatenumberofmcuinimage
num_x_mcu=(width+mcu_width-1)/mcu_width;
num_y_mcu=(height+mcu_height-1)/mcu_height;
dib_line_size=width*nchannels+
IJL_DIB_PAD_BYTES(width,nchannels);
dib_chunk_size=dib_line_size*mcu_height;
//allocatememorytoholdonemculine
dib_chunk_ptr=newBYTE[dib_chunk_size];
if(NULL==dib_chunk_ptr)
{
res=-1;
gotoExit;
}
//makeillusiontoIJL,thatitisworkwithbuffer
es=dib_chunk_ptr;
//processnum_y_mculine
for(j=0;j
{
//getnextmculinefromBMPfile
res=get_dib_chunk_data(bmp_file,dib_chunk_size,dib_chunk_ptr);
if(res!=0)
{
gotoExit;
}
//itisactuallyusedpointer
_ptr=dib_chunk_ptr;
//processnum_x_mcuinmculine
for(i=0;i
{
//interruptaftereachmcu
upt=1;
//compresscurrentmcu(advancepointertonextmcuisinternal
job)
jerr=ijlWrite(&jcprops,IJL_JFILE_WRITEWHOLEIMAGE);
if(IJL_INTERRUPT_OK==jerr)
{
//currentmcuwasencodedsuccessfully
continue;
}
if(IJL_OK==jerr)
{
//jobiscomplete:allimageisprocessed
res=0;
break;
}
if(IJL_OK>jerr)
{
//erroroccured
res=-1;
break;
}
}
}
//ifafterprocessingnum_y_mculinesthelibraryreturns
IJL_INTERRUPT_OK,
//itistomeanthatsomedataarestillkeepingininternal
flushit.
if(IJL_INTERRUPT_OK==jerr)
{
//flushdatafrominternalbuffers
upt=1;
jerr=ijlWrite(&jcprops,IJL_JFILE_WRITEWHOLEIMAGE);
if(IJL_OK!=jerr)
{
res=-1;
gotoExit;
}
}
res=0;
Exit:
if(NULL!=bmp_file)
{
fclose(bmp_file);
}
if(NULL!=dib_chunk_ptr)
{
delete[]dib_chunk_ptr;
}
ijlFree(&jcprops);
returnres;
}//ijl_compress_large_dib()
八、关注矩形的解码(Rectangle-of-InterestDecoding)
经常会有需要解压缩和显示一部分图像的情况。使用这个模式,可以使应用程序变得更有效
率,且使用更短的时间。
为了获得这样的效率,在解码图像之前,应用程序需要请求一个被JPEG_PROPERTIES中的IJL_RECT
结构填充的“关注矩形解码(ROI)”。
下面的示例演示了如何使用ROI。
//----------------------------------------------------------
//AnexampleusingtheIntelRJPEGLibrary:
//--DecodeaJPEGimagefromaJFIFfileusing
//theRectangle-Of-Interest(ROI)method.
//----------------------------------------------------------
BOOLDecodeJPGFileByROI(LPCSTRlpszPathName)
{
BOOLbres;
IJLERRjerr;
DWORDwidth;
DWORDheight;
DWORDnchannels;
DWORDwholeimagesize;
BYTE*pixel_buf=NULL;
IJL_RECTlocal_roi;
//AllocatetheIJLJPEG_CORE_PROPERTIESstructure.
JPEG_CORE_PROPERTIESjcprops;
bres=TRUE;
__try
{
//InitializetheIntelRJPEGLibrary.
jerr=ijlInit(&jcprops);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
e=const_cast
//GetinformationontheJPEGimage
//(i.e.,width,height,andchannels).
jerr=ijlRead(&jcprops,IJL_JFILE_READPARAMS);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
//Setuplocaldata.
width=th;
height=ght;
nchannels=3;
//Decodeintoa3channelpixelbuffer.
//Forthisexample,wewillallocateanimagebufferhalf
//,wewilldecodethe
//tophalfandbottomhalfoftheimageseparately.
//Thiscouldofcoursebeextendedtopartitiontheimage
//intoseveralrectangulartileswhichwouldrequireasmall
//(orfixedsize)chniqueyields
//greatlyincreasedmemoryperformanceformost
//applications!
wholeimagesize=width*((height+1)>>1)*nchannels;
//Allocatememorytoholdthedecompressedimagedata.
pixel_buf=newBYTE[wholeimagesize];
if(NULL==pixel_buf)
{
bres=FALSE;
__leave;
}
//SetuptheinfoonthedesiredDIBproperties.
th=width;
//Setabottom-upDIBofhalftheoriginalimagesize.
ght=(height+1)>>1;
nnels=nchannels;
or=IJL_BGR;
Bytes=0;
es=pixel_buf;
//SettheJPGcolorspace...thiswillalwaysbe
//somewhatofaneducatedguessatbestbecauseJPEG
//is"colorblind"(i.e.,nothinginthebitstream
//tellsyouwhatcolorspacethedatawasencodedfrom).
//However,inthisexampleweassumethatweare
//readingJFIFfileswhichmeansthat3channelimages
//areintheYCbCrcolorspaceand1channelimagesare
//intheYcolorspace.
switch(nnels)
{
case1:
{
or=IJL_G;
break;
}
case3:
{
or=IJL_YCBCR;
break;
}
default:
{
//Thiscatcheseverythingelse,butno
//colortwistwillbeperformedbytheIJL.
or=(IJL_COLOR)IJL_OTHER;
or=(IJL_COLOR)IJL_OTHER;
break;
}
}
//Getthetophalfoftheimage.
local_=0;
local_=0;
local_=width;
local_=(height+1)>>1;
=local_roi;
//NowactuallygetthetophalfoftheJPEGimagedata
//intothepixelbuffer.
jerr=ijlRead(&jcprops,IJL_JFILE_READENTROPY);
if(IJL_ROI_OK!=jerr)
{
bres=FALSE;
__leave;
}
//...nowyouprobablywanttodosomethingwiththe
//decompressedtophalfoftheimagelikedisplayit...
//Next,getthebottomhalfoftheimage.
local_=0;
local_=(height+1)>>1;//=(height+1)/2;
local_=width;
local_=height;
=local_roi;
//NowactuallygetthebottomhalfoftheJPEGimagedata
//intothepixelbuffer.
jerr=ijlRead(&jcprops,IJL_JFILE_READENTROPY);
if(IJL_ROI_OK!=jerr)
{
bres=FALSE;
__leave;
}
//...nowyouprobablywanttodosomethingwiththe
//decompressedbottomhalfoftheimagelikedisplayit...
//
}//__try
__finally
{
if(NULL!=pixel_buf)
{
delete[]pixel_buf;
}
//CleanuptheIntelRJPEGLibrary.
ijlFree(&jcprops);
}
returnbres;
}//DecodeJPGFileByROI()
九、比例解码
很多JPEG会被解码为原大小的1/2,1/4,or1/8。这叫做“scaleddecoding”,这意味着比解
码整个图象至少会快两倍以上。IJL支持并行处理比例解码和关注矩形解码及不断编、解码。
实际应用时,比例解码常用于为那些没有嵌入式缩略图的JPEG图像生成缩略图。
下面的表格列出如何计算比例:
Table5-1ScaledDecodingCalculations
Scaled
DecodingType
ResultingWidth’&Height’I/OTypeSpecifier
1/2SizeWidth’=INT((Width+1)/2)
Height’=INT((Height+1)/2)
IJL_JXXXX_READONEHALF
1/4SizeWidth’=INT((Width+3)/4)
Height’=INT((Height+3)/4)
IJL_JXXXX_READONEQUARTER
1/8SizeWidth’=INT((Width+7)/8)
Height’=INT((Height+7)/8)
IJL_JXXXX_READONEEIGHTH
计算图像的比例使用下列的宏,该宏位于ijl.h文件中:
IJL_DIB_SCALE_SIZE(jpgsize,scale)=(((jpgsize)+(scale)-1)/(scale))
例如:一个2407x491象素的图像的1/8图像是301x62pixels。
下面的示例是解码得到一个原始图像的1/8的JPEG图像。
//----------------------------------------------------------
//AnexampleusingtheIntelRJPEGLibrary:
//--DecodeaJPEGimagefromaJFIFfile.
//usingthescaleddecodingmethod.
//----------------------------------------------------------
BOOLDecodeJPGFileOneEighth(LPCSTRlpszPathName)
{
BOOLbres;
IJLERRjerr;
DWORDwidth;
DWORDheight;
DWORDnchannels;
DWORDwholeimagesize;
BYTE*pixel_buf=NULL;
//AllocatetheIJLJPEG_CORE_PROPERTIESstructure.
JPEG_CORE_PROPERTIESjcprops;
bres=TRUE;
__try
{
//InitializetheIntelRJPEGLibrary.
jerr=ijlInit(&jcprops);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
e=const_cast
//GetinformationontheJPEGimage
//(i.e.,width,height,andchannels).
jerr=ijlRead(&jcprops,IJL_JFILE_READPARAMS);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
//Setuplocaldata.
//Note:Inthiscase,widthandheightarerounded
//tothenearestfactorofeight.
width=(th+7)>>3;
height=(ght+7)>>3;
nchannels=3;//Decodeintoa3channelpixelbuffer.
wholeimagesize=(width*height*nchannels);
//Allocatememorytoholdthedecompressedimagedata.
pixel_buf=newBYTE[wholeimagesize];
if(NULL==pixel_buf)
{
bres=FALSE;
__leave;
}
//SetuptheinfoonthedesiredDIBproperties.
th=width;
ght=height;//Impliesabottom-upDIB.
nnels=nchannels;
or=IJL_BGR;
Bytes=0;
es=pixel_buf;
//SettheJPGcolorspace...thiswillalwaysbe
//somewhatofaneducatedguessatbestbecauseJPEG
//is"colorblind"(i.e.,nothinginthebitstream
//tellsyouwhatcolorspacethedatawasencodedfrom).
//However,inthisexampleweassumethatweare
//readingJFIFfileswhichmeansthat3channelimages
//areintheYCbCrcolorspaceand1channelimagesare
//intheYcolorspace.
switch(nnels)
{
case1:
{
or=IJL_G;
break;
}
case3:
{
or=IJL_YCBCR;
break;
}
default:
{
//Thiscatcheseverythingelse,butno
//colortwistwillbeperformedbytheIJL.
or=(IJL_COLOR)IJL_OTHER;
or=(IJL_COLOR)IJL_OTHER;
break;
}
}
//NowgettheactualJPEGimagedataintothepixelbuffer
//andscaletheoutputto1/8ththeoriginalsize.
jerr=ijlRead(&jcprops,IJL_JFILE_READONEEIGHTH);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
//
//...nowyouprobablywanttodosomethingwiththe
//decompressedscaledimagelikedisplayit...
//
}
__finally
{
if(NULL!=pixel_buf)
{
delete[]pixel_buf;
}
//CleanuptheIntelRJPEGLibrary.
ijlFree(&jcprops);
}
returnbres;
}//DecodeJPGFileOneEighth()
十、嵌入的缩略图解码E
IJL支持嵌入至JFIF图像文件的未压缩的RGB缩略图(1字节/象素或3字节/象素)的解码,
并且JFIF的版本是1.01和1.02的。
压缩的缩略图现在不被支持。
在解码之前,用户必须提供一个24bit的DIB,且至少有256x256象素。这是因为,JFIF嵌入
缩略图的最大尺寸256x256象素。同样,用户如果需要一个缩略图是24bitRGB,DIBColor段必须
被设置为IJL_RGB。当调用ijlRead()时IJLIOTYPE参数设为IJL_JXXXX_READTHUMBNAIL。
这个IJLIOTYPE可以与IJL_JXXXX_READPARAMS交替的使用。结果该函数调用之后,
JPEG_CORE_PROPERTIES数据结构的更新如下:
1.缩略图的宽、高被保存在JPGThumbWidth和JPGThumbHeight,如果值为0则表示没有缩
略图或格式不支持。
es段取代了表示象素值缓存的指针。
实际上,IJL不支持缩略图的所有者属情。
十一、渐进图像支持(ProgressiveImageSupport)
IJL解码支持基于渐进离散余弦变换的JPEG图像。但IJL不支持图像的渐进显示。从1.5版
之后,IJL支持图像的渐进编码。建立一个渐进的JPEG图像,用户将调用ijlWrite()函数并使
JPEG_PROPERTIES中的progressive_found段设为。如下面的代码:
...
JPEG_CORE_PROPERTIESjcprops;
...
ijlInit(&jcprops);
....
//Requesttocreateaprogressiveimage
ssive_found=1;
ijlWrite(&jcprops,IJL_JXXXX_WRITEWHOLEIMAGE);
使用IJL_JFILE_WRITEWHOLEIMAGE或IJL_JBUFF_WRITEWHOLEIMAGE调用ijlWrite()把图像写入一
个文件,或分配至一段缓存。
渐进编码算法,是采用逐渐逼进法或频谱法,扫描次数被固定在库中,并不能被改变。这些
参数的设置依靠通道的数量和色彩空间。
这个库支持下列的渐进编码参数:
1-通道的IJL_G图像:
scancountis6,withparameterspereachpassas
1scan;DCcomponent0;ss=0,se=63;ah=0,al=1
2scan;ACcomponent0;ss=1,se=5;ah=0,al=2
3scan;ACcomponent0;ss=6,se=63;ah=0,al=2
4scan;ACcomponent0;ss=1,se=63;ah=2,al=1
5scan;DCcomponent0;ss=0,se=63;ah=1,al=0
6scan;ACcomponent0;ss=1,se=63;ah=1,al=0
for3-channelIJL_YCBCRimages:
scancountis10,withparameterspereachpassas
1scan;DCcomponents0,1,2;ss=0,se=63;ah=0,al=1
2scan;ACcomponent0;ss=1,se=5;ah=0,al=2
3scan;ACcomponent2;ss=1,se=63;ah=0,al=2
4scan;ACcomponent1;ss=1,se=63;ah=0,al=2
5scan;ACcomponent0;ss=6,se=63;ah=0,al=2
6scan;ACcomponent0;ss=1,se=63;ah=2,al=1
7scan;DCcomponents0,1,2;ss=0,se=63;ah=1,al=0
8scan;ACcomponent2;ss=1,se=63;ah=1,al=0
9scan;ACcomponent1;ss=1,se=63;ah=1,al=0
10scan;ACcomponent0;ss=1,se=63;ah=1,al=0
for3-channelIJL_RGBimages:
scancountis8,withparameterspereachpassas
1scan;DCcomponents0,1,2;ss=0,se=63;ah=0,al=1
2scan;ACcomponent0;ss=1,se=5;ah=0,al=0
3scan;ACcomponent1;ss=1,se=5;ah=0,al=0
4scan;ACcomponent2;ss=1,se=5;ah=0,al=0
5scan;DCcomponent0,1,2;ss=0,se=63;ah=1,al=0
6scan;ACcomponent0;ss=6,se=63;ah=0,al=0
7scan;ACcomponent1;ss=6,se=63;ah=0,al=0
8scan;ACcomponent2;ss=6,se=63;ah=0,al=0
for3-channelIJL_OTHERimages:
scancountis8,withparameterspereachpassas
1scan;DCcomponents0,1,2;ss=0,se=63;ah=0,al=1
2scan;ACcomponent0;ss=1,se=5;ah=0,al=0
3scan;ACcomponent1;ss=1,se=5;ah=0,al=0
4scan;ACcomponent2;ss=1,se=5;ah=0,al=0
5scan;DCcomponent0,1,2;ss=0,se=63;ah=1,al=0
6scan;ACcomponent0;ss=6,se=63;ah=0,al=0
7scan;ACcomponent1;ss=6,se=63;ah=0,al=0
8scan;ACcomponent2;ss=6,se=63;ah=0,al=0
for4-channelIJL_RGBA_FPXimages:
scancountis10,withparameterspereachpassas
1scan;DCcomponents0,1,2,3;ss=0,se=63;ah=0,al=1
2scan;ACcomponent0;ss=1,se=5;ah=0,al=0
3scan;ACcomponent1;ss=1,se=5;ah=0,al=0
4scan;ACcomponent2;ss=1,se=5;ah=0,al=0
5scan;ACcomponent3;ss=1,se=5;ah=0,al=0
6scan;DCcomponent0,1,2,3;ss=0,se=63;ah=1,al=0
7scan;ACcomponent0;ss=6,se=63;ah=0,al=0
8scan;ACcomponent1;ss=6,se=63;ah=0,al=0
9scan;ACcomponent2;ss=6,se=63;ah=0,al=0
10scan;ACcomponent3;ss=6,se=63;ah=0,al=0
for4-channelIJL_YCBCRA_FPXimages:
scancountis11,withparameterspereachpassas
1scan;DCcomponents0,1,2,3;ss=0,se=63;ah=0,al=1
2scan;ACcomponent0;ss=1,se=5;ah=0,al=2
3scan;ACcomponent2;ss=1,se=63;ah=0,al=1
4scan;ACcomponent1;ss=1,se=63;ah=0,al=1
5scan;ACcomponent3;ss=1,se=63;ah=0,al=0
6scan;ACcomponent0;ss=6,se=63;ah=0,al=2
7scan;ACcomponent0;ss=1,se=63;ah=2,al=1
8scan;DCcomponents0,1,2,3;ss=0,se=63;ah=1,al=0
9scan;ACcomponent2;ss=1,se=63;ah=1,al=0
10scan;ACcomponent1;ss=1,se=63;ah=1,al=0
11scan;ACcomponent0;ss=1,se=63;ah=1,al=0
for4-channelIJL_OTHERimages:
scancountis10,withparameterspereachpassas
1scan;DCcomponents0,1,2,3;ss=0,se=63;ah=0,al=1
2scan;ACcomponent0;ss=1,se=5;ah=0,al=0
3scan;ACcomponent1;ss=1,se=5;ah=0,al=0
4scan;ACcomponent2;ss=1,se=5;ah=0,al=0
5scan;ACcomponent3;ss=1,se=5;ah=0,al=0
6scan;DCcomponent0,1,2,3;ss=0,se=63;ah=1,al=0
7scan;ACcomponent0;ss=6,se=63;ah=0,al=0
8scan;ACcomponent1;ss=6,se=63;ah=0,al=0
9scan;ACcomponent2;ss=6,se=63;ah=0,al=0
10scan;ACcomponent3;ss=6,se=63;ah=0,al=0
上面列出的符号意义是:
ss–第一个选择谱带的索引;thefirstindexinthespectralselectionband;
se–最后一个选择谱带的索引;thelastindexinthespectralselectionband;
ah–逐渐逼近法的最高位;thehighestbitinthesuccessiveapproximation;
al–逐渐逼近法的最低位;thelowestbitinthesuccessiveapproximation.
十二、JPEG图像的内存操作
JPEG在FlashPix和TIFF6.0中被作为一个压缩标准,所以IJL也支持从这些格解码。
FlashPix、TIFF编码可提取JPEG数据并且提供给IJL一个缓存区域,或是从缓存中得到JPEG
数据。IJL允许在所有的访问模式中从缓存读或写JPEG数据。
把JPEG数据写入到buffer中,以下列方式进行:
分配一个足够大小的buffer(通常这个buffer的大小等于未经压缩图像的大小)。如果这个
buffer的大小不够大,IJL将返回一个错误码IJL_BUFFER_TOO_SMALL。
设置JPEG_CORE_PROPERTIES结构的相关字段:
JPGFile=NULL
JPGBytes=buffer的指针
JPGSizeBytes=buffer的大小(按字节的)
IJL_BUFF_WRITEWHOLEIMAGE作为参数调用ijlWrite()函数。这个buffer将包含JPEG数据,并
且JPGSizeBytes的值是实际的JPEG数据的字节数。注意!早期的IJL库返回的是缓存中的一个
错误的数据字节数,它被指向buffer的指针取代了。ThisbugwasfixedintheIJLversion1.5.
从一个buffer解码JPEG数据参看下面的步骤:
得到有JPEG数据的buffer;
设置JPEG_CORE_PROPERTIES结构的相关字段:
JPGFile=NULL
JPGBytes=buffer的指针
JPGSizeBytes=buffer的大小(按字节的)
以IJL_BUFF_READEWHOLEIMAGE做为参数调用ijlRead()函数。
下面示例演示如何从buffer读,或写数据。
//----------------------------------------------------------
//AnexampleusingtheIntel(R)JPEGLibrary:
//--DecodeimagefromaJFIFbuffer.
//----------------------------------------------------------
BOOLDecodeFromJPEGBuffer(
BYTE*lpJpgBuffer,
DWORDdwJpgBufferSize,
BYTE**lppRgbBuffer,
DWORD*lpdwWidth,
DWORD*lpdwHeight,
DWORD*lpdwNumberOfChannels)
{
BOOLbres;
IJLERRjerr;
DWORDdwWholeImageSize;
BYTE*lpTemp=NULL;
//AllocatetheIJLJPEG_CORE_PROPERTIESstructure.
JPEG_CORE_PROPERTIESjcprops;
bres=TRUE;
__try
{
//InitializetheIntel(R)JPEGLibrary.
jerr=ijlInit(&jcprops);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
//GetinformationontheJPEGimage
//(i.e.,width,height,andchannels).
e=NULL;
es=lpJpgBuffer;
eBytes=dwJpgBufferSize;
jerr=ijlRead(&jcprops,IJL_JBUFF_READPARAMS);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
//SettheJPGcolorspace...thiswillalwaysbe
//somewhatofaneducatedguessatbestbecauseJPEG
//is"colorblind"(i.e.,nothinginthebitstream
//tellsyouwhatcolorspacethedatawasencodedfrom).
//However,inthisexampleweassumethatweare
//readingJFIFfileswhichmeansthat3channelimages
//areintheYCbCrcolorspaceand1channelimagesare
//intheYcolorspace.
switch(nnels)
{
case1:
{
or=IJL_G;
or=IJL_RGB;
nnels=3;
break;
}
case3:
{
or=IJL_YCBCR;
or=IJL_RGB;
nnels=3;
break;
}
default:
{
//Thiscatcheseverythingelse,butno
//colortwistwillbeperformedbytheIJL.
or=IJL_OTHER;
or=IJL_OTHER;
nnels=nnels;
break;
}
}
//Computesizeofdesiredpixelbuffer.
dwWholeImageSize=th*ght*
nnels;
//Allocatememorytoholdthedecompressedimagedata.
lpTemp=newBYTE[dwWholeImageSize];
if(NULL==lpTemp)
{
bres=FALSE;
__leave;
}
//SetuptheinfoonthedesiredDIBproperties.
th=th;
ght=ght;
Bytes=0;
es=lpTemp;
//NowgettheactualJPEGimagedataintothepixelbuffer.
jerr=ijlRead(&jcprops,IJL_JBUFF_READWHOLEIMAGE);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
}//__try
__finally
{
if(FALSE==bres)
{
if(NULL!=lpTemp)
{
delete[]lpTemp;
lpTemp=NULL;
}
}
//CleanuptheIntel(R)JPEGLibrary.
ijlFree(&jcprops);
*lpdwWidth=th;
*lpdwHeight=ght;
*lpdwNumberOfChannels=nnels;
*lppRgbBuffer=lpTemp;
}//__finally
returnbres;
}//DecodeFromJPEGBuffer()
//----------------------------------------------------------
//AnexampleusingtheIntel(R)JPEGLibrary:
//--EncodeWindowsDIBtoJPEGbuffer.
//----------------------------------------------------------
BOOLEncodeToJPEGBuffer(
BYTE*lpRgbBuffer,
DWORDdwWidth,
DWORDdwHeight,
BYTE**lppJpgBuffer,
DWORD*lpdwJpgBufferSize)
{
BOOLbres;
IJLERRjerr;
DWORDdwRgbBufferSize;
BYTE*lpTemp;
//AllocatetheIJLJPEG_CORE_PROPERTIESstructure.
JPEG_CORE_PROPERTIESjcprops;
bres=TRUE;
__try
{
//InitializetheIntel(R)JPEGLibrary.
jerr=ijlInit(&jcprops);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
dwRgbBufferSize=dwWidth*dwHeight*3;
lpTemp=newBYTE[dwRgbBufferSize];
if(NULL==lpTemp)
{
bres=FALSE;
__leave;
}
//Setupinformationtowritefromthepixelbuffer.
th=dwWidth;
ght=dwHeight;//Impliesabottom-upDIB.
es=lpRgbBuffer;
Bytes=0;
nnels=3;
or=IJL_RGB;
th=dwWidth;
ght=dwHeight;
e=NULL;
es=lpTemp;
eBytes=dwRgbBufferSize;
nnels=3;
or=IJL_YCBCR;
sampling=IJL_411;//4:1:1subsampling.
ty=75;//Select"good"imagequality
//WritetheactualJPEGimagefromthepixelbuffer.
jerr=ijlWrite(&jcprops,IJL_JBUFF_WRITEWHOLEIMAGE);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
}//__try
__finally
{
if(FALSE==bres)
{
if(NULL!=lpTemp)
{
delete[]lpTemp;
lpTemp=NULL;
}
}
*lppJpgBuffer=lpTemp;
*lpdwJpgBufferSize=eBytes;
//CleanuptheIntel(R)JPEGLibrary.
ijlFree(&jcprops);
}
returnbres;
}//EncodeToJPEGBuffer()
十三、OddDataFormats
Mostoftoday’sJPEGfilesarestoredintheJPEGFileInterchangeFormat(JFIF),andtheIJL
aminimalfileformatthatenablesJPEGbitstreamstobe
tureofJFIFisthatit
lesarestoredusingeitherthe3-channel
luminance/chrominancecolorspace(YCbCrasdefinedbyCCIR601(256levels)),orthe
1-channelgrayscalecolorspace(onlytheYcomponentofYCbCr).
However,theJPEGinterchangeformat(notJFIF)definescompresseddatastorageformats
itstreammay
havemanymeaningsotherthanthecommonJFIF3-channel,2-Dinterleavedplaneimage
data.
AJPEGimagedoesnotnecessarilycontainanyinformationthatspecifiesthecolorspaceof
Gdecoderisthusforcedtomakeassumptionsaboutthecolorformat
fileformatslikeTIFF6.0andFlashPixcontainenoughcolor
spaceinformationtoavoidthisambiguity.
JPEGisoftencalled“colorblind”.ThisisbecausenothingwithinaJPEGbitstreamindicates
ecolorformatofaJPEGimage
isunknown,ornotsupportedbytheIJL(i.e.,Adobe’s*CMYK),itissuggestedthattheuser
specifytheIJL_OTHERcolorspaceformatforboththeJPGColorandDIBColorfieldsinthe
JPEG_CORE_chniquepreventstheIJLfromapplyingacolor
,itbecomestheuser’sresponsibilitytoperformtheirowncolorspace
manipulation(ifsodesired)outsideoftheIJL.
IfaJPEGbitstreamindicatesthatdatawillbestoredinseparateplanes,theIJLwillpresent
ycauseunexpectedresults,especiallyfordata
representedusingmultiplescans(i.e.,onescanperblock-row).
第四章预处理及后处理
一、DIBs
设备无关位图(DIB)图像数据存贮为一个字节型的交叉存取格式,每通道的一个字节(8
位)。Windows24-bitDIB,存贮形式如下图:
IJL可以从一个buffer得到数据,也可以解码一个JPEG数据至一个buffer。用户需要关心色彩
通道的数量,色彩空间的解释,和行末的填充。
IJL支持输入数据:
隔行扫描的色彩平面,Interleavedcolorplanes.
非二次抽样Non-subsampled)数据(除了IJL_YCBCR色彩空间以外,这个空间仅支持
4:2:2二次抽样象素的隔行扫描)。
颜色值是1to255。
图像宽度是1to65,535。
图像高度是-65,535to65,535(值>0表示bottom-upDIB).
行尾填充,或填充字节,必须>=0.
缩略图的输出DIBs,宽和高的绝对值不能超过255,色彩空间必须是3通道的IJL_RGBor
IJL_BGR。
二、IJLColorSpaces
下列表格举例说明IJL支持的不同的DIBandJPEG色彩空间。
Table6-1IJLSupportedColorSpaces
IJLColorSpaceValidIJLDIB
ColorSpace?
ValidIJLJPEG
ColorSpace?
Description
IJL_GYesYes灰度图像,只有一个亮度通道.
IJL_RGBYesYesRGB(red-green-blue)3or4channelcolor
space
IJL_BGRYesNoRGB3channelcolorspace,但顺序是BGR.
IJL_RGBA_FPXYesYesFlashPixRGB4channelcolorspacewith
pre-multipliedopacity.
IJL_YCBCRYesYesCCIR601YCbCr(luminance-chrominance)
ngfromversion
1.5,theIJLsupportsthespecific4:2:2
subsampledpixelinterleavedformatused
bothasinputdataformatforencoding,and
case
thedatasequenceissettobeY0-Cb0-Y1-
Cr0-Y2-Cb1-Y3-Cr1-....
IJL_YCBCRA_FPXNoYesFlashPixYCbCr4channelcolorspacewith
pre-multipliedopacityandtheYCbCrvalues
arestored"flipped"(i.e.,X'=255-X).
IJL_OTHERYesYesUnknowncolorspacewheretheuser
specifiesthenumberofchannels.
IJL_G色彩空间指定DIB存贮为一个只有亮度的每通道8位的格式。这个空间被定义为只有亮度
或YCbCr色彩空间的Y分量,且亮度级是256级。
IJL_RGB色彩空间是每通道8位的,被sRGB定义的,数据存贮是按每像素由低到高Red,Green,Blue
存放的。.
IJL_BGR与IJL_RGB类似,只是排列顺序按照Blue,Green,Red。IJL_BGR支持从Windows
DIBsandBitmaps(使用BGR顺序的)快速的输入输出。
IJL_RGBA_FPX和IJL_YCBCRA_FPX颜色是FlashPix4通道色彩空间和自左乘不透明的,并
提供FlashPixJPEG压缩文件很大的兼容性。
IJL_YCBCR色彩空间是一个标准的YCbCr色彩空间,被CCIR601定义为256级(8-bit)
每通道。这是在JPEG图像中使用最多的并且被JFIF,EXIF,TIFF,FlashPix,andSPIFF文件格
式支持。它被推荐用来处理JPEG图像,即使是单色或灰度图。
IJL_YCBCRA_FPX色彩空间不支持DIB格式的编码。
IJL_OTHER色彩空间被用于自定义或不知道的DIB色彩空间,IJL并不处理颜色转换,只是从
JPEG图像数据中简单的复制适当数量的通道。
三、二次取样
一个通道的灰度空间不允许二级采样。
三个通道的色彩空间允许使用4:1:1或4:2:2格式时行二次采样。4:1:1格式是同时在第二
和第三通道使用一个水平的采样因子“2”,和一个垂直的采样因子“2”。4:2:2格式同时在第二和第
三通道使用一个水平的采样因子“2”,和一个垂直的采样因子“1”。非二次采样格式或1:1:1,是表
示三个通道的水平和垂直方向都使用采样因子“1”。
四通道的色彩空间允许使用4:1:1:4或4:2:2:4的二次采样格式。4:1:1:4格式是同时在第二
和第三通道使用一个水平的采样因子“2”,和一个垂直的采样因子“2”。4:2:2:4格式同时在第二
和第三通道使用一个水平的采样因子“2”,和一个垂直的采样因子“1”。非二次采样格式或1:1:1,是
表示三个通道的水平和垂直方向都使用采样因子“1”。
备注:
RGB12色,每个像素用1位表示,需要调色板
RGB416色,每个像素用4位表示,需要调色板
RGB8256色,每个像素用8位表示,需要调色板
RGB565每个像素用16位表示,RGB分量分别使用5位、6位、5位
RGB555每个像素用16位表示,RGB分量都使用5位(剩下的1位不用)
RGB24每个像素用24位表示,RGB分量各使用8位
RGB32每个像素用32位表示,RGB分量各使用8位(剩下的8位不用)
ARGB32每个像素用32位表示,RGB分量各使用8位(剩下的8位用于表示Alpha通
道值)
YUY2YUY2格式,以4:2:2方式打包
YUYVYUYV格式(实际格式与YUY2相同)
YVYUYVYU格式,以4:2:2方式打包
UYVYUYVY格式,以4:2:2方式打包
AYUV带Alpha通道的4:4:4YUV格式
Y41PY41P格式,以4:1:1方式打包
Y411Y411格式(实际格式与Y41P相同)
Y211Y211格式
IF09IF09格式
IYUVIYUV格式
YV12YV12格式
YVU9YVU9格式
下面分别介绍各种RGB格式。
¨RGB1、RGB4、RGB8都是调色板类型的RGB格式,在描述这些媒体类型的格式细节时,
通常会在BITMAPINFOHEADER数据结构后面跟着
一个调色板(定义一系列颜色)。它们的图像数据并不是真正的颜色值,而是当前像素颜色
值在调色板中的索引。以RGB1(2色位图
)为例,比如它的调色板中定义的两种颜色值依次为0x000000(黑色)和0xFFFFFF(白
色),那么图像数据…(每个像
素用1位表示)表示对应各像素的颜色为:黑黑白白黑白黑白黑白白白…。
¨RGB565使用16位表示一个像素,这16位中的5位用于R,6位用于G,5位用于B。
程序中通常使用一个字(WORD,一个字等于两个字
节)来操作一个像素。当读出一个像素后,这个字的各个位意义如下:
高字节低字节
RRRRRGGGGGGBBBBB
可以组合使用屏蔽字和移位操作来得到RGB各分量的值:
#defineRGB565_MASK_RED0xF800
#defineRGB565_MASK_GREEN0x07E0
#defineRGB565_MASK_BLUE0x001F
R=(wPixel&RGB565_MASK_RED)>>11;//取值范围0-31
G=(wPixel&RGB565_MASK_GREEN)>>5;//取值范围0-63
B=wPixel&RGB565_MASK_BLUE;//取值范围0-31
¨RGB555是另一种16位的RGB格式,RGB分量都用5位表示(剩下的1位不用)。使
用一个字读出一个像素后,这个字的各个位意义如下:
高字节低字节
XRRRRGGGGGBBBBB(X表示不用,可以忽略)
可以组合使用屏蔽字和移位操作来得到RGB各分量的值:
#defineRGB555_MASK_RED0x7C00
#defineRGB555_MASK_GREEN0x03E0
#defineRGB555_MASK_BLUE0x001F
R=(wPixel&RGB555_MASK_RED)>>10;//取值范围0-31
G=(wPixel&RGB555_MASK_GREEN)>>5;//取值范围0-31
B=wPixel&RGB555_MASK_BLUE;//取值范围0-31
¨RGB24使用24位来表示一个像素,RGB分量都用8位表示,取值范围为0-255。注意在
内存中RGB各分量的排列顺序为:BGRBGRBGR
…。通常可以使用RGBTRIPLE数据结构来操作一个像素,它的定义为:
typedefstructtagRGBTRIPLE{
BYTErgbtBlue;//蓝色分量
BYTErgbtGreen;//绿色分量
BYTErgbtRed;//红色分量
}RGBTRIPLE;
¨RGB32使用32位来表示一个像素,RGB分量各用去8位,剩下的8位用作Alpha通道
或者不用。(ARGB32就是带Alpha通道的RGB32。)
注意在内存中RGB各分量的排列顺序为:BGRABGRABGRA…。通常可以使用RGBQUAD
数据结构来操作一个像素,它的定义为:
typedefstructtagRGBQUAD{
BYTErgbBlue;//蓝色分量
BYTErgbGreen;//绿色分量
BYTErgbRed;//红色分量
BYTErgbReserved;//保留字节(用作Alpha通道或忽略)
}RGBQUAD;
下面介绍各种YUV格式。YUV格式通常有两大类:打包(packed)格式和平面(planar)
格式。前者将YUV分量存放在同一个数组中,
通常是几个相邻的像素组成一个宏像素(macro-pixel);而后者使用三个数组分开存放YUV
三个分量,就像是一个三维平面一样。表
2.3中的YUY2到Y211都是打包格式,而IF09到YVU9都是平面格式。(注意:在介绍各
种具体格式时,YUV各分量都会带有下标,如Y0、
U0、V0表示第一个像素的YUV分量,Y1、U1、V1表示第二个像素的YUV分量,以此类
推。)
¨YUY2(和YUYV)格式为每个像素保留Y分量,而UV分量在水平方向上每两个像素采
样一次。一个宏像素为4个字节,实际表示2个像
素。(4:2:2的意思为一个宏像素中有4个Y分量、2个U分量和2个V分量。)图像数据
中YUV分量排列顺序如下:
Y0U0Y1V0Y2U2Y3V2…
¨YVYU格式跟YUY2类似,只是图像数据中YUV分量的排列顺序有所不同:
Y0V0Y1U0Y2V2Y3U2…
¨UYVY格式跟YUY2类似,只是图像数据中YUV分量的排列顺序有所不同:
U0Y0V0Y1U2Y2V2Y3…
¨AYUV格式带有一个Alpha通道,并且为每个像素都提取YUV分量,图像数据格式如下:
A0Y0U0V0A1Y1U1V1…
¨Y41P(和Y411)格式为每个像素保留Y分量,而UV分量在水平方向上每4个像素采样
一次。一个宏像素为12个字节,实际表示8个像
素。图像数据中YUV分量排列顺序如下:
U0Y0V0Y1U4Y2V4Y3Y4Y5Y6Y8…
¨Y211格式在水平方向上Y分量每2个像素采样一次,而UV分量每4个像素采样一次。
一个宏像素为4个字节,实际表示4个像素。图像
数据中YUV分量排列顺序如下:
Y0U0Y2V0Y4U4Y6V4…
¨YVU9格式为每个像素都提取Y分量,而在UV分量的提取时,首先将图像分成若干个4x
4的宏块,然后每个宏块提取一个U分量和一
个V分量。图像数据存储时,首先是整幅图像的Y分量数组,然后就跟着U分量数组,以
及V分量数组。IF09格式与YVU9类似。
¨IYUV格式为每个像素都提取Y分量,而在UV分量的提取时,首先将图像分成若干个2x
2的宏块,然后每个宏块提取一个U分量和一
个V分量。YV12格式与IYUV类似。
¨YUV411、YUV420格式多见于DV数据中,前者用于NTSC制,后者用于PAL制。YUV411
为每个像素都提取Y分量,而UV分量在水平方向
上每4个像素采样一次。YUV420并非V分量采样为0,而是跟YUV411相比,在水平方
向上提高一倍色差采样频率,在垂直方向上以U/V间
隔的方式减小一半色差采样,如图2.12所示。
四、不采样
IJL解压缩图像可以采用任意的采样因子,每个最小编码单位中最多有10个块,同样也适应JPEG
标准。缺省的二次采样解码算法是IJL_BOX_FILTER,这意谓着在解码像素值是象把采样因子复制
很多倍一样。如果水平及垂直的采样因子没有超过2,那么可以使用不采样和三角滤波器,这会产
生更好的结果。为实现这个意图,设置IJL_TRIANGLE_FILTER的JPEG_CORE_PROPERTIES的
upsampling_type字段。
在比例二次采样解码图像中,适当匹配采样因子(即水平和垂直因子且不等于2),不采样能被
大尺寸的DCT取代,这能提供更快的高质量解码。
四、解码及后处理矩阵
下表列出IJL中色彩空间解码集合及后处理选项。
JPEG色彩空
间
JPEG
通道数
DIB色彩空
间
DIB通
道数
解码数据格式后处理
IJL_G1IJL_G1Y,Y,…CCNo&USNo
IJL_G1IJL_RGB3YYY,YYY,…CCNo&USNo
IJL_G1IJL_BGR3
YYY,YYY,…
(seenote1below)
CCNo&USNo
IJL_G1
IJL_RGBA_
FPX
4YYYO,YYYO,…CCNo&USNo
IJL_RGB3IJL_RGB3RGB,RGB,…
1:1:1CCNo&USNo
4:1:1CCNo&USYes
4:2:2CCNo&USYes
IJL_RGB3IJL_BGR3BGR,BGR,…
1:1:1CCNo&USNo
4:1:1CCNo&USYes
4:2:2CCNo&USYes
IJL_RGB3IJL_RGBA_FP
X
4RGBO,RGBO,…1:1:1CCNo&USNo
4:1:1CCNo&USYes
4:2:2CCNo&USYes
IJL_RGBA_
FPX
4
IJL_RGBA_
FPX
4
RGBA,RGBA,…
(seenote2below)
1:1:1:1CCNo&USNo
4:1:1:4CCNo&USYes
4:2:2:4CCNo&USYes
IJL_YCBCR3IJL_G1Y,Y,…
1:1:1CCNo&USNo
4:1:1CCNo&USYes
4:2:2CCNo&USYes
IJL_YCBCR3IJL_YCBCR3
Y0-Cb0-Y1-Cr0-
Y2-Cb1-...
(seenote4below)
4:2:2CCNo&USNo
IJL_YCBCR3IJL_RGB3RGB,RGB,…
1:1:1CCYes&USNo
4:1:1CCYes&USYes
4:2:2CCYes&USYes
IJL_YCBCR3IJL_BGR3BGR,BGR,…1:1:1CCYes&USNo
4:1:1CCYes&USYes
4:2:2CCYes&USYes
IJL_YCBCR3
IJL_RGBA_
FPX4RGBO,RGBO,…
1:1:1CCYes&USNo
4:1:1CCYes&USYes
4:2:2CCYes&USYes
IJL_YCBCRA_
FPX4
IJL_RGBA_
FPX4
RGBA,RGBA,…
(seenote3below)
1:1:1:1CCYes&USNo
4:1:1:4CYes&USYes
4:2:2:4CYes&USYes
IJL_OTHERnIJL_OTHER
1<=m<
n
X0..X(m-1),
X0..X(m-1),
…
CCNo&USifneeded
IJL_OTHERnIJL_OTHERm=n
X0..X(n-1),
X0..X(n-1),
…
CCNo&USifneeded
IJL_OTHERnIJL_OTHERm>n
X0..X(n-1)En..E(m-1),
X0..X(n-1)En..E(m-1),
…
CCNo&USifneeded
符号说明:
符号描述
Y亮度通道
CbCr色度通道(遮盖红色至兰绿域coveringtheredtoblue-greenrange)
CrCb色度通道(遮盖兰色至黄域(coveringthebluetoyellowrange)
R红通道
G绿通道
B兰通道
E空值(i.e.,theexistingmemorycontentsarenotoverwritten)
O不透明值(i.e.,for8-bitsamples,itequals255)
X通道任意值
CC色彩空间转换
US不采样
SS二次采样
注解:
1.注意,这个描述是正确的,就象IJL_G至IJL_RGB。
nttotheFlashPixspecification,thepre-multipliedopacityispreserved.
nttotheFlashPixspecification,an"inverseflip"(thatis,X=255–X')isperformedand
thepre-multipliedopacityispreserved.
ngfromversion1.5,theIJLsupportsIJL_YCBCRDIBcolorspace(currentlyfor
DIBSubsampling=IJL_422only).DecodingisimplementedonlyforJPGSubsampling=IJL_422.
五、编码及预处理矩阵
下表列出IJL中色彩空间编码集合及预处理选项。
DIB色彩空间
DIB
通道
JPEG色彩空间
JPEG
通道
编码数据格式预处理
IJL_G1IJL_G1Y,Y,…CCNo&SSNo
IJL_G1IJL_YCBCR3
Y00,Y00,…
(seenote1below)
1:1:1CCNo&SSNo
4:1:1CCNo&SSYes
4:2:2CCNo&SSYes
IJL_RGB3IJL_G1Y,Y,…CCYes&SSNo
IJL_RGB3IJL_RGB3RGB,RGB,…
1:1:1CCNo&SSNo
4:1:1CCNo&SSYes
4:2:2CCNo&SSYes
IJL_RGB3IJL_YCBCR3YCbCr,YCbCr,…
1:1:1CCYes&SSNo
4:1:1CCYes&SSYes
4:2:2CCYes&SSYes
IJL_RGB4IJL_YCBCR3
YCbCr,YCbCr,…
(seenote2below)
1:1:1CCYes&SSNo
4:1:1CCYes&SSYes
4:2:2CCYes&SSYes
IJL_BGR3IJL_G1Y,Y,…CCYes&SSNo
IJL_BGR3IJL_RGB3RGB,RGB,…
1:1:1CCNo&SSNo
4:1:1CCNo&SSYes
4:2:2CCNo&SSYes
IJL_BGR3IJL_YCBCR3YCbCr,YCbCr,…
1:1:1CCYes&SSNo
4:1:1CCYes&SSYes
4:2:2CCYes&SSYes
IJL_YCBCR3IJL_YCBCR3
YCbCr,YCbCr,…
(seenote5below)
4:2:2CCNo&SSYes
IJL_RGBA_FPX4IJL_RGBA_FPX4RGBA,RGBA,…
(seenote3below)
1:1:1:1CCNo&SSNo
4:1:1:4CCNo&SSYes
4:2:2:4CCNo&SSYes
IJL_RGBA_FPX4IJL_YCBCRA_FPX4
YCbCrA,YCbCrA,…
(seenote4below)
1:1:1:1CCYes&SSNo
4:1:1:4CCYes&SSYes
4:2:2:4CCYes&SSYes
IJL_OTHERnIJL_OTHER1<=m
X0..X(m-1),
X0..X(m-1),
…
CCNo&SSifneeded
IJL_OTHERnIJL_OTHERm=n
X0..X(n-1),
X0..X(n-1),
CCNo&SSifneeded
…
注释,:
1.亮度值被保留,色度值被清零。
2.假定没有左乘不透明度。
nttotheFlashPixspecification,thepre-multipliedopacityispreserved.
nttotheFlashPixspecification,a"flip"(i.e.,X'=255-X)isperformedandthe
pre-multipliedopacityispreserved.
aencodingfromDIBColor=IJL_YCBCRtoJPGColor=IJL_YCBCRiscurrently
supportedonlyforDIBSubsampling=IJL_422.
第五章IJL高级特性
一、使用CPU代码
IJL检测处理器的类型并自动选择是好的CPU特定的代码(这是默认选项)。例如:如果你
使用IJL在一个Intel®Pentium®4处理器的系统中,库将利用专门针对此CPU优化的代码。
通过设置系统注册表的USECPU键值,你可以指引库使用需要的代码:
0–混合代码(选项针对所有以前的CPU)
4-PentiumII优化代码;
5-PentiumIII优化代码;
6-Pentium4优化代码;
USECPU是DWORD类型,位置在:HKEY_LOCAL_MACHINESoftwareIntel
CorporationPLSuiteIJLib。
二、设置DCT算法
IJL支持两种不同的DCT算法。一个是设置IJL_AAN字段的值,这是基于Araietal工作的。
see[Arai].这个算法相当快,但有一些精度的限制。另一个算法提供足够的速度及高精度,源自
IntelIntegratedPerformancePrimitives并针对Intel体系结构。默认的选项设置后调用ijlInit().
使用前一个算法,必须设置JPEG_CORE_PROPERTIES结构的e字
段为IJL_AAN。并且需在调用ijlInit()之后,在调用jlRead()或ijlWrite()这前。
三、写和读JPEG注释块
这里介绍两个新的JPEG_CORE_PROPERTIES结构中的字段:
jpeg_comment是指向注释字符串的指针
jpeg_comment_size是注释字符串的长度,包括尾部的zero.
当IJL初始化是,这两个设置被调为“0”,这意味着下面的注释字符串将被插入到编码数据中:
“Intel®JPEGLibrary,[
字符串你需要设置指针指向一个缓存区并指明长度。当注释成功的读取并放置到这个缓存区,
jpeg_comment_size的值是写入字串的长度。万一缓存的长度不足,IJL将写数据直至缓存区满,
并返回错误码IJL_ERR_COM_BUFFER。如果没有注释字段,IJL将不改变缓存的内容及大小。
应用程序必须负责分配和释放缓存所占的内存。
四、自定义JPEG表
IJL允许规定霍夫曼(Huffman)和量化表以实现一些特殊的用途。通过JPEG_PROPERTIES结构
设定。
五、自定义量化表
IJL可以接受4个自定义的量化表。IJL通过一个8bitunsignedchar型的行为主或不专弯的
形式的8X8的数组来设定量化表。默认是,标准的量化表。在JPEG编码程序中默认使用标准的
量化表,就象下面的描述:
staticunsignedcharDefaultLuminanceQuantTbl[]=
{
16,11,12,14,12,10,16,14,
13,14,18,17,16,19,24,40,
26,24,22,22,24,49,35,37,
29,40,58,51,61,60,57,51,
56,55,64,72,92,78,64,68,
87,69,55,56,80,109,81,87,
95,98,103,104,103,62,77,113,
121,112,100,120,92,101,103,99
};
staticunsignedcharDefaultChrominanceQuantTbl[]=
{
17,18,18,24,21,24,47,26,
26,47,99,66,56,66,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99
};
每一个量化因子被IJL内部质量水平乘法器调节,并且用于除以输入的数据以减少精度(减
小存贮空间)。在图像内部的某一个频率Theentriesinthequantizationarrayscorrespondto
multipliersappliedtocertainspatialfrequencieswithintheimage.
Thelowest-order(DC)lowingcode
illustratesaddingcustomquantizationtablespriortoauthoringaJPEGimage.
//----------------------------------------------------------
//AnexampleusingtheIntelRJPEGLibrary:
//--AuthoraJPEGimageusingcustomquantizationtables.
//----------------------------------------------------------
//Yourspecialquantizationtablegoeshere!
staticBYTEHQLumQuantTable[]=
{
16,11,12,14,12,10,16,14,
13,14,18,17,16,19,24,40,
26,24,22,22,24,49,35,37,
29,40,58,51,61,60,57,51,
56,55,64,72,92,78,64,68,
87,69,55,56,80,109,81,87,
95,98,103,104,103,62,77,113,
121,112,100,120,92,101,103,99
};
//Yourspecialquantizationtablegoeshere!
staticBYTEHQChromQuantTable[]=
{
17,18,18,24,21,24,47,26,
26,47,99,66,56,66,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99
};
BOOLEncodeJPGFileWithCustomQuantization(
LPCSTRlpszPathName,
DWORDwidth,
DWORDheight,
DWORDnchannels,
BYTE*pixel_buf)
{
BOOLbres;
IJLERRjerr;
//AllocatetheIJLJPEG_CORE_PROPERTIESstructure.
JPEG_CORE_PROPERTIESjcprops;
bres=TRUE;
__try
{
//InitializetheIntelRJPEGLibrary.
jerr=ijlInit(&jcprops);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
//sexamplewe
//assigntwocustomtables,althoughuptofourarepossible.
//Herewealsoassumethetablesspecifyluminanceand
//chrominancequantizationfactors(asinaYCbCrimage).
ntindex=2;
es=2;
nttables[0].quantizer=HQLumQuantTable;
nttables[0].ident=0;
nttables[1].quantizer=HQChromQuantTable;
nttables[1].ident=1;
//Nowthatwehaveassignedthetables,weneedtodecidewhich
//colorchannelsoftheauthoredimagewillusewhichtables.
//Theidentmemberofrawquanttablesspecifiesaunique
//identifierforeachtable;wereferencethequant_selmemberof
//eachframe(image)componenttothisidentifier.
[0].quant_sel=0;
[1].quant_sel=1;
[2].quant_sel=1;
[3].quant_sel=1;
th=width;
ght=height;
nnels=nchannels;//nchannelsMUSTBE3!
or=IJL_BGR;
es=pixel_buf;
e=const_cast
//SpecifyJPEGfilecreationparameters.
th=width;
ght=height;
//Note:thefollowingaredefaultvaluesandthus
//donotneedtobeset.
//nnels=3;
//or=IJL_YCBCR;
//sampling=IJL_411;//4:1:1subsampling.
//ty=75;//Select"good"imagequality
//WritetheactualJPEGimagefromthepixelbuffer.
jerr=ijlWrite(&jcprops,IJL_JFILE_WRITEWHOLEIMAGE);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
}//__try
__finally
{
//CleanuptheIntelRJPEGLibrary.
ijlFree(&jcprops);
}
returnbres;
}//EncodeJPGFileWithCustomQuantization()
IJL格式内部的量化表在使用任何数据之前被使用。因此这个表只需在第一次调用ijlWrite()之
前传递至IJL。
六、自定义霍夫曼表
IJL允许每幅图有4个霍夫曼表。霍夫曼表用来测定JPEG编码过程运行周期的熵代码。
霍夫曼表被成对的指定:一个表用于一个图像通道的每个直流和交流的频率成份。每个表需
要两个结构,一个表示每个符号必须的的位,一个表示实际符号的值。这些结构中的数据格式是
与每个JPEG规格中嵌入的霍夫曼表同样的。
下面的代码示例是使用自定义霍夫曼表的
//----------------------------------------------------------
//AnexampleusingtheIntelRJPEGLibrary:
//--AuthoraJPEGimageusingcustomHuffmantables.
//----------------------------------------------------------
//YourspecialHuffmanDCSymbolLengthtablegoeshere!
staticBYTECustomLuminanceDCBits[]=
{
0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
//YourspecialHuffmanDCSymboltablegoeshere!
staticBYTECustomLuminanceDCValues[]=
{
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,
0x0b
};
//YourspecialHuffmanDCSymbolLengthtablegoeshere!
staticBYTECustomChrominanceDCBits[]=
{
0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x01,
0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00
};
//YourspecialHuffmanDCSymboltablegoeshere!
staticBYTECustomChrominanceDCValues[]=
{
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,
0x0b
};
//YourspecialHuffmanACSymbolLengthtablegoeshere!
staticBYTECustomLuminanceACBits[]=
{
0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,
0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7d
};
//YourspecialHuffmanACSymboltablegoeshere!
staticBYTECustomLuminanceACValues[]=
{
0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,
0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,
0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,
0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,
0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,
0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,
0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,
0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,
0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,
0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,
0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
0xf9,0xfa
};
//YourspecialHuffmanACSymbolLengthtablegoeshere!
staticunsignedcharCustomChrominanceACBits[]=
{
0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,
0x07,0x05,0x04,0x04,0x00,0x01,0x02,0x77
};
//YourspecialHuffmanACSymboltablegoeshere!
staticunsignedcharCustomChrominanceACValues[]=
{
0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,
0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,
0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,
0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,
0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,
0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,
0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,
0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,
0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,
0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,
0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,
0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,
0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
0xf9,0xfa
};
BOOLEncodeJPGFileWithCustomHuffman(
LPCSTRlpszPathName,
DWORDwidth,
DWORDheight,
DWORDnchannels,
BYTE*pixel_buf)
{
BOOLbres;
IJLERRjerr;
//AllocatetheIJLJPEG_CORE_PROPERTIESstructure.
JPEG_CORE_PROPERTIESjcprops;
bres=TRUE;
__try
{
//InitializetheIntelRJPEGLibrary.
jerr=ijlInit(&jcprops);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
//sexample,we
//assigntwosetsofcustomtables,thoughuptofourare
//assumethetablesspecifyluminanceand
//chrominanceHuffmanfactors(asinaYCbCrimage).
ctables=2;
ctables=2;
findex=2;
ftables[0].bits=CustomLuminanceDCBits;
ftables[0].vals=CustomLuminanceDCValues;
ftables[0].hclass=0;
ftables[0].ident=0;
ftables[1].bits=CustomLuminanceACBits;
ftables[1].vals=CustomLuminanceACValues;
ftables[1].hclass=1;
ftables[1].ident=0;
ftables[2].bits=CustomChrominanceDCBits;
ftables[2].vals=CustomChrominanceDCValues;
ftables[2].hclass=0;
ftables[2].ident=1;
ftables[3].bits=CustomChrominanceACBits;
ftables[3].vals=CustomChrominanceACValues;
ftables[3].hclass=1;
ftables[3].ident=1;
//Nowthatwehaveassignedthetables,weneedtodecidewhich
//channelsoftheauthoredimagewillusewhichtables.
//Theidentmemberofrawhufftablesspecifiesaunique
//identifierforeachtable;wereferencetheHuffIdentifier
//memberofeachimage(whichappliestoeachcomponentin
//increasingorder)tothisidentifier.
entifierAC[0]=0;
entifierDC[0]=0;
entifierAC[1]=1;
entifierDC[1]=1;
entifierAC[2]=1;
entifierDC[2]=1;
entifierAC[3]=1;
entifierDC[3]=1;
th=width;
ght=height;
nnels=nchannels;//only3isvalid
or=IJL_BGR;
es=pixel_buf;
//SpecifyJPEGfilecreationparameters.
th=width;
ght=height;
e=const_cast
//Note:thefollowingaredefaultvaluesandthus
//donotneedtobeset.
//nnels=3;
//or=IJL_YCBCR;
//sampling=IJL_411;//4:1:1subsampling.
//ty=75;//Select"good"imagequality
//WritetheactualJPEGimagefromthepixelbuffer.
jerr=ijlWrite(&jcprops,IJL_JFILE_WRITEWHOLEIMAGE);
if(IJL_OK!=jerr)
{
bres=FALSE;
__leave;
}
}//__try
__finally
{
//CleanuptheIntelRJPEGLibrary.
ijlFree(&jcprops);
}
returnbres;
}//EncodeJPGFileWithCustomHuffman()
IJL在任何写数据之前格式化霍夫曼表。所以,需要在第一次调用ijlWrite()的时候传递表至IJL。
七、扩展基线解码
这段描述的技术是格式表信息交叉多IJL使用最小表处理和内存开销。
多数图像格式分开了头,表,和熵信息。一些“瓷片”格式的图像,就象FlashPix,可以把图像
分成很多“瓷片”,每个一个参照JPEG表存贮在文件的另外的地方。优化编码需要这些表信息,以
不处理每个“瓷片”,而应保持译码器格式表。之后,霍夫曼或量化表被解码和格式化,这些格式
表示要求存贮在IJL的外部。在图象解码之前,格式化表再被复制回JPEG_PROPERTIES结构的适
当的位置。
更多的信息请参考白皮书“UsingtheIJLwithJPEGCompressedFlashPixFiles”.
HUFFMAN_TABLEandQUANT_TABLE结构包含进行适当的解码器格式的霍夫曼和量化表。这
些表在JPEG_PROPERTIES定位象下面的片段://////////////////////////////////////////////////////////////////
//...acodefragmentfromtheJPEG_PROPERTIESdatastructure...
//////////////////////////////////////////////////////////////////
//Tables
DWORDnqtables;
DWORDmaxquantindex;
DWORDnhuffActables;
DWORDnhuffDctables;
DWORDmaxhuffindex;
QUANT_TABLEjFmtQuant[4];
HUFFMAN_TABLEjFmtAcHuffman[4];
HUFFMAN_TABLEjFmtDcHuffman[4];
short*jEncFmtQuant[4];
HUFFMAN_TABLE*jEncFmtAcHuffman[4];
HUFFMAN_TABLE*jEncFmtDcHuffman[4];
//Allowuser-definedtables.
DWORDuse_default_htables;
DWORDuse_default_qtables;
JPEGQuantTablerawquanttables[4];
JPEGHuffTablerawhufftables[8];
BYTEHuffIdentifierAC[4];
BYTEHuffIdentifierDC[4];
重要的成员是jFmtQuant,jFmtAcHuffman,和jFmtDcHuffman。解码之后,这些表使用
IJL_JXXXX_READHEADER,复制它们到你的持久化存储器。
接下来,解码一个JPEG比特流(即至少假定为简短格式压缩的图像数据),用户复制格式化
表回到JPEG_PROPERTIES成员并调用ijlRead(),使用IJL_JXXXX_READWHOLEIMAGE。
复制保留表到JPEG_PROPERTIES,要快于在每次调用解码器的时候强制处理和格式化和附加
一个表到每个JPEG数据流的前面。
八、参考
[Arai]Arai,Agui,andNakajima,,vol.E71(11),pp.1095-1097,Nov.1988.
附录A词汇表
简短格式AbbreviatedFormat(针对压缩图像数据)–这个格式等于互换格式,只是它可能或不
可能包括解码所需的所有表。这个格式在用户应用中提供一种备选(交错)的机制,用于解码需
要的部分或全部的表规范数据。
简短格式AbbreviatedFormat(针对表规格化数据)–这个格式只包含表规范数据。意味着解码
器中应用的表需要在随后重建一个或更多的图像。
基线模式BaselineMode–(又名基于连续离散余弦变换模式)-被JPEG定义的四种图像压缩
算法中的一种。这个模式是最简单的DCT-basedJPEG编、解码处理,是在所有的DCT-based
JPEG中必须具有的最小能力。图象压缩使用单独扫描,基本的信息如下:
·DCT-basedprocess
·源图像:每层8-bit抽样
·连续的
·Huffmancoding:2ACand2DCtables
·Decoders将处理扫描用1,2,3,and4分量
·隔行和逐行扫描
BitStream–位流。
位流Channel–图像中颜色的单一分量;
已压缩数据CompressedData–任何已压缩的图像图据和表规范数据。
CompressedImageData–AcodedrepresentationofanimageasspecifiedbytheJPEG
specification.
连续色调图象Continuous-toneImage–图像分量大小1位的抽样。
离散余弦变换DCT–
DIB-(设备无关位图)
EntropyCoding–Alosslessprocedurethatconvertsasequenceofinputsymbolsintoa
sequenceofbitssuchthattheaveragenumberofbitspersymbolapproachestheentropyof
theinputsymbols.
ExtendedBaselineMode-AsequentialDCT-basedencodinganddecodingprocessinwhich
deextendstheBaseline
asummaryofitsessentialcharacteristics:
DCT-basedprocess
Sourceimage:8-bitor12-bitsamples
Sequentialorprogressive
Huffmanorarithmeticcoding:4ACand4DCtables
Decodersshallprocessscanswith1,2,3,and4components
Interleavedandnon-interleavedscans
GrayscaleImage–Acontinuous-toneimagethathasonlyonecomponent.
HorizontalSamplingFactor–Therelativenumberofhorizontaldataunitsofaparticular
componentwithrespecttothenumberofhorizontaldataunitsintheothercomponents.
HuffmanTable–ThesetofvariablelengthcodesrequiredintheHuffmancodingprocess.
HuffmanCoding–Anentropycodingprocedurethatassignsavariablelengthcodetoeach
inputsymbol.
IJL-(Intel®JPEGLibrary)TheIJLisasoftwarelibraryforapplicationdevelopersthatprovides
highperformanceJPEGencodinganddecodingoffullcolor,andgrayscale,
IJLwasdevelopedtotakeadvantageofMMX™technologyifpresent.
InterchangeFormat–(terchangeFormatorJIF)AJPEGcompressedimage
databitstreamthatincludesalltablesthatarerequiredbythedecoder(i.e.,Huffmanand
quantizationtables).
Interleaved–Thedescriptivetermappliedtotherepetitivemultiplexingofsmallgroupsofdata
unitsfromeachcomponentinascaninaspecificorder.
JFIF-(JPEGFileInterchangeFormat)AminimalfileformatwhichenablesJPEGbitstreamsto
Fisentirely
compatiblewiththestandardJPEGInterchangeFormat.
JPEG-(JointPhotographicExpertsGroup)UsuallyreferstoISODIS10918-1and10918-2,
“Digitalcompressionandcodingofcontinuous-tonestillimages",thecompressionstandard
thisgroupcreated.
Lossless–Adescriptivetermforencodinganddecodingprocessesandproceduresinwhich
theoutputofthedecodingprocedure(s)isidenticaltotheinputtotheencodingprocedure(s).
Lossy–Adescriptivetermforencodinganddecodingprocesseswhicharenotlossless.
MCU-(MinimumCodedUnit)TheminimalsetofdatawrittentoacompressedJPEGstream.
TheMCUis,forDCT-basedJPEGcodingprocesses,asetofrectangularregionsoverseveral
waysamultipleof8pixelswideand
plingvariouscolorcomponentsofanimagegeneratesMCUswithdimensions
mple,common4:1:1subsampledJPEGimageshavea16x
16pixelMCU.
Non-Interleaved–Thedescriptivetermappliedtothedataunitprocessingsequencewhenthe
scanhasonlyonecomponent.
PixelBuffer–Arectangulararrayofpixelswitheachpixelhavingthesamenumberof
componentvalues(colorchannels).Thenumberofcomponentsandthecolorspace
interpretationofthecomponentsarealsorequired.
Pre-Processing–Theactofapplyingvariousoperationstoanimagepriortosendingittothe
perationstypicallyincludecolorspaceconversionandsubsampling.
Post-Processing–Theactofapplyingvariousoperationstoanimageafterreceivingitfromthe
perationstypicallyincludeupsamplingandinversecolorspace
conversion.
ProgressiveMode–Oneofthefourmaincategoriesofimagecompressionprocessesdefined
deisaDCT-basedcodingprocessthatisachievedbyasequenceofscans,
eachofwhichcodespartofthequantizedDCTcoefficientinformation.
Quantization-AlossyprocedureinwhichtheDCTcoefficientsarelinearlyscaledinorderto
achievecompression.
QuantizationTable–Thesetof64integervaluesusedtoquantizetheDCTcoefficients.
RestartInterval–TheintegernumberofMCUsprocessedasanindependentsequencewithin
ascan.
ROI-(Rectangle-of-Interest)Aparticularrectangularregionoftheimagewhichcanbe
specifiedby(top,left)and(bottom,right)mustbecontainedwithin
theimage,butmayencompassthetotalimage.
Scan–Asinglepassthroughthedataforoneormoreofthecomponentsinanimage.
Subsampling–(mpling)Aprocedurebywhichthespatialresolutionofanimage
isreduced.
TableSpecificationData–Thecodedrepresentationfromwhichthetablesusedintheencoder
anddecoderaregenerated.
Upsampling–Aprocedurebywhichthespatialresolutionofanimageisincreased.
VerticalSamplingFactor–Therelativenumberofverticaldataunitsofaparticularcomponent
withrespecttothenumberofverticaldataunitsintheothercomponents.
Zig-ZagSequence–AspecificsequentialorderingoftheDCTcoefficientsfrom(approximately)
lowestspatialfrequencytohighest.
实时流媒体编程(RTP,RTCP,RTSP)
流媒体指的是在网络中使用流技术传输的连续时基媒体,其特点是在播放前不需要下载整个文件,而
是采用边下载边播放的方式,它是视频会议、IP电话等应用场合的技术基础。RTP是进行实时流媒
体传输的标准协议和关键技术,本文介绍如何在Linux下利用JRTPLIB进行实时流媒体编程。
一、流媒体简介
随着Internet的日益普及,在网络上传输的数据已经不再局限于文字和图形,而是逐渐向声音和视频
等多媒体格式过渡。目前在网络上传输音频/视频(Audio/Video,简称A/V)等多媒体文件时,基本
上只有下载和流式传输两种选择。通常说来,A/V文件占据的存储空间都比较大,在带宽受限的网络
环境中下载可能要耗费数分钟甚至数小时,所以这种处理方法的延迟很大。如果换用流式传输的话,
声音、影像、动画等多媒体文件将由专门的流媒体服务器负责向用户连续、实时地发送,这样用户可
以不必等到整个文件全部下载完毕,而只需要经过几秒钟的启动延时就可以了,当这些多媒体数据在
客户机上播放时,文件的剩余部分将继续从流媒体服务器下载。
流(Streaming)是近年在Internet上出现的新概念,其定义非常广泛,主要是指通过网络传输多
媒体数据的技术总称。流媒体包含广义和狭义两种内涵:广义上的流媒体指的是使音频和视频形成稳
定和连续的传输流和回放流的一系列技术、方法和协议的总称,即流媒体技术;狭义上的流媒体是相
对于传统的下载-回放方式而言的,指的是一种从Internet上获取音频和视频等多媒体数据的新方法,
它能够支持多媒体数据流的实时传输和实时播放。通过运用流媒体技术,服务器能够向客户机发送稳
定和连续的多媒体数据流,客户机在接收数据的同时以一个稳定的速率回放,而不用等数据全部下载
完之后再进行回放。由于受网络带宽、计算机处理能力和协议规范等方面的限制,要想从Internet上
下载大量的音频和视频数据,无论从下载时间和存储空间上来讲都是不太现实的,而流媒体技术的出
现则很好地解决了这一难题。目前实现流媒体传输主要有两种方法:顺序流(progressivestreaming)
传输和实时流(realtimestreaming)传输,它们分别适合于不同的应用场合。
顺序流传输
顺序流传输采用顺序下载的方式进行传输,在下载的同时用户可以在线回放多媒体数据,但给定
时刻只能观看已经下载的部分,不能跳到尚未下载的部分,也不能在传输期间根据网络状况对下载速
度进行调整。由于标准的HTTP服务器就可以发送这种形式的流媒体,而不需要其他特殊协议的支持,
因此也常常被称作HTTP流式传输。顺序流式传输比较适合于高质量的多媒体片段,如片头、片尾或
者广告等。
实时流传输
实时流式传输保证媒体信号带宽能够与当前网络状况相匹配,从而使得流媒体数据总是被实时地
传送,因此特别适合于现场事件。实时流传输支持随机访问,即用户可以通过快进或者后退操作来观
看前面或者后面的内容。从理论上讲,实时流媒体一经播放就不会停顿,但事实上仍有可能发生周期
性的暂停现象,尤其是在网络状况恶化时更是如此。与顺序流传输不同的是,实时流传输需要用到特
定的流媒体服务器,而且还需要特定网络协议的支持。
二、流媒体协议
实时传输协议(Real-timeTransportProtocol,PRT)是在Internet上处理多媒体数据流的一种
网络协议,利用它能够在一对一(unicast,单播)或者一对多(multicast,多播)的网络环境中实现
传流媒体数据的实时传输。RTP通常使用UDP来进行多媒体数据的传输,但如果需要的话可以使用
TCP或者ATM等其它协议,整个RTP协议由两个密切相关的部分组成:RTP数据协议和RTP控制
协议。实时流协议(RealTimeStreamingProtocol,RTSP)最早由RealNetworks和Netscape公
司共同提出,它位于RTP和RTCP之上,其目的是希望通过IP网络有效地传输多媒体数据。
2.1RTP数据协议
RTP数据协议负责对流媒体数据进行封包并实现媒体流的实时传输,每一个RTP数据报都由头部
(Header)和负载(Payload)两个部分组成,其中头部前12个字节的含义是固定的,而负载则可
以是音频或者视频数据。RTP数据报的头部格式如图1所示:
其中比较重要的几个域及其意义如下:
CSRC记数(CC)表示CSRC标识的数目。CSRC标识紧跟在RTP固定头部之后,用来表
示RTP数据报的来源,RTP协议允许在同一个会话中存在多个数据源,它们可以通过RTP混合器合
并为一个数据源。例如,可以产生一个CSRC列表来表示一个电话会议,该会议通过一个RTP混合
器将所有讲话者的语音数据组合为一个RTP数据源。
负载类型(PT)标明RTP负载的格式,包括所采用的编码算法、采样频率、承载通道等。
例如,类型2表明该RTP数据包中承载的是用ITUG.721算法编码的语音数据,采样频率为8000Hz,
并且采用单声道。
序列号用来为接收方提供探测数据丢失的方法,但如何处理丢失的数据则是应用程序自己的
事情,RTP协议本身并不负责数据的重传。
时间戳记录了负载中第一个字节的采样时间,接收方能够时间戳能够确定数据的到达是否受
到了延迟抖动的影响,但具体如何来补偿延迟抖动则是应用程序自己的事情。从RTP数据报的格式
不难看出,它包含了传输媒体的类型、格式、序列号、时间戳以及是否有附加数据等信息,这些都为
实时的流媒体传输提供了相应的基础。RTP协议的目的是提供实时数据(如交互式的音频和视频)的
端到端传输服务,因此在RTP中没有连接的概念,它可以建立在底层的面向连接或面向非连接的传
输协议之上;RTP也不依赖于特别的网络地址格式,而仅仅只需要底层传输协议支持组帧(Framing)
和分段(Segmentation)就足够了;另外RTP本身还不提供任何可靠性机制,这些都要由传输协议
或者应用程序自己来保证。在典型的应用场合下,RTP一般是在传输协议之上作为应用程序的一部分
加以实现的,如图2所示:
2.2RTCP控制协议
RTCP控制协议需要与RTP数据协议一起配合使用,当应用程序启动一个RTP会话时将同时占
用两个端口,分别供RTP和RTCP使用。RTP本身并不能为按序传输数据包提供可靠的保证,也不
提供流量控制和拥塞控制,这些都由RTCP来负责完成。通常RTCP会采用与RTP相同的分发机制,
向会话中的所有成员周期性地发送控制信息,应用程序通过接收这些数据,从中获取会话参与者的相
关资料,以及网络状况、分组丢失概率等反馈信息,从而能够对服务质量进行控制或者对网络状况进
行诊断。
RTCP协议的功能是通过不同的RTCP数据报来实现的,主要有如下几种类型:
SR发送端报告,所谓发送端是指发出RTP数据报的应用程序或者终端,发送端同时也可以是接
收端。
RR接收端报告,所谓接收端是指仅接收但不发送RTP数据报的应用程序或者终端。
SDES源描述,主要功能是作为会话成员有关标识信息的载体,如用户名、邮件地址、电话号码
等,此外还具有向会话成员传达会话控制信息的功能。
BYE通知离开,主要功能是指示某一个或者几个源不再有效,即通知会话中的其他成员自己将退
出会话。
APP由应用程序自己定义,解决了RTCP的扩展性问题,并且为协议的实现者提供了很大的灵活
性。
RTCP数据报携带有服务质量监控的必要信息,能够对服务质量进行动态的调整,并能够对网络拥塞
进行有效的控制。由于RTCP数据报采用的是多播方式,因此会话中的所有成员都可以通过RTCP
数据报返回的控制信息,来了解其他参与者的当前情况。
在一个典型的应用场合下,发送媒体流的应用程序将周期性地产生发送端报告SR,该RTCP数据报
含有不同媒体流间的同步信息,以及已经发送的数据报和字节的计数,接收端根据这些信息可以估计
出实际的数据传输速率。另一方面,接收端会向所有已知的发送端发送接收端报告RR,该RTCP数
据报含有已接收数据报的最大序列号、丢失的数据报数目、延时抖动和时间戳等重要信息,发送端应
用根据这些信息可以估计出往返时延,并且可以根据数据报丢失概率和时延抖动情况动态调整发送速
率,以改善网络拥塞状况,或者根据网络状况平滑地调整应用程序的服务质量。
2.3RTSP实时流协议
作为一个应用层协议,RTSP提供了一个可供扩展的框架,它的意义在于使得实时流媒体数据的受控
和点播变得可能。总的说来,RTSP是一个流媒体表示协议,主要用来控制具有实时特性的数据发送,
但它本身并不传输数据,而是必须依赖于下层传输协议所提供的某些服务。RTSP可以对流媒体提供
诸如播放、暂停、快进等操作,它负责定义具体的控制消息、操作方法、状态码等,此外还描述了与
RTP间的交互操作。
RTSP在制定时较多地参考了HTTP/1.1协议,甚至许多描述与HTTP/1.1完全相同。RTSP之所以特
意使用与HTTP/1.1类似的语法和操作,在很大程度上是为了兼容现有的Web基础结构,正因如此,
HTTP/1.1的扩展机制大都可以直接引入到RTSP中。
由RTSP控制的媒体流集合可以用表示描述(PresentationDescription)来定义,所谓表示是指流媒
体服务器提供给客户机的一个或者多个媒体流的集合,而表示描述则包含了一个表示中各个媒体流的
相关信息,如数据编码/解码算法、网络地址、媒体流的内容等。
虽然RTSP服务器同样也使用标识符来区别每一流连接会话(Session),但RTSP连接并没有被绑
定到传输层连接(如TCP等),也就是说在整个RTSP连接期间,RTSP用户可打开或者关闭多个
对RTSP服务器的可靠传输连接以发出RTSP请求。此外,RTSP连接也可以基于面向无连接的传
输协议(如UDP等)。
RTSP协议目前支持以下操作:
检索媒体允许用户通过HTTP或者其它方法向媒体服务器提交一个表示描述。如表示是组播的,
则表示描述就包含用于该媒体流的组播地址和端口号;如果表示是单播的,为了安全在表示描述中应
该只提供目的地址。
邀请加入媒体服务器可以被邀请参加正在进行的会议,或者在表示中回放媒体,或者在表示中录
制全部媒体或其子集,非常适合于分布式教学。
添加媒体通知用户新加入的可利用媒体流,这对现场讲座来讲显得尤其有用。与HTTP/1.1类似,
RTSP请求也可以交由代理、通道或者缓存来进行处理。
更多推荐
丢失ijl15 dll
发布评论