winrar注册-360安全卫士下载 软件

丢失ijl15 dll
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(lpszPathName);

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(lpszPathName);

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(buffer);

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(buffer+sizeof(BITMAPINFOHEADER));

//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(bmih)+

sizeof(BITMAPINFOHEADER);

Bytes=dib_pad_bytes;

//Note:thefollowingaredefaultvaluesandthus

//donotneedtobeset.

nnels=3;

or=IJL_BGR;

e=const_cast(lpszPathName);

//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(lpszPathName);

//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(lpszJpgName);

//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(bmp_buf+

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(bmp_buf);

lpbmfh->bfType='MB';

lpbmfh->bfSize=bmp_buf_size;

lpbmfh->bfReserved1=0;

lpbmfh->bfReserved2=0;

lpbmfh->bfOffBits=sizeof(BITMAPFILEHEADER)+

sizeof(BITMAPINFOHEADER);

lpbmih=reinterpret_cast(bmp_buf+

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(lpszPathName);

//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(lpszPathName);

//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(lpszPathName);

//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(lpszPathName);

//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