Intel IJL 简明操作

第一章 准备

一、需要以下的三个库

1. IJL 动态链接库(IJL15.DLL),

2. IJL 引入库(IJL15.LIB),

3. IJL 头文件(IJL.H).

二、建立IJL应用程序的步骤

1. 在每一个将调用IJL函数的模块中包含头文件IJL.H

2. 在项目中增加IJL15.LIB

3. 编译程序。

第二章 结构描述

现在最多的JPEG模式是基本基线模式和扩展基线模式的连续离散余弦变换。IJL1.5完全支持这两种模式的编码及解码,

一、IJL 的I/O数据结构体系

1. 内存中含有一个常规的象素buffer.

2. 一个标准的I/O文件包含JPEG bit stream.

3. 一个内存buffer包含一个JPEG bit stream.

二、支持的数据格式

1、Top-down orbottom-up pixel buffers.

在Windows中, device-independent bitmaps (DIBs) 数据在内存中有两种排列方式 bottom-up and top-down。bottom-up DIB,buffer 是从最底行的最左象素开始, 接着是次底行. 而顶行的数据是在buffer 的最后。GDI 使用的Bottom-upDIB。top-down DIB的排列顺序是颠倒的. 最顶行最左侧的象素是buffer的第一个字节,而最底行的象素在buffer的最后。DirectDraw使用top-down DIBs。RGB DIBs, 图象的排列方式由"http://msdn2.microsoft.com/en-us/library/ms779712.aspx"BITMAPINFOHEADER结构的成员变量 biHeight 来指示。如 biHeight 是正数, 图象是bottom-up. 如果biHeight是负数, 图象是top-down。YUV 格式的DIBs 总是top-down,biHeight 的符号被忽略。

2、象素缓冲区与自定义行尾填充。

3、使用普通象素缓冲之内的一个矩形。

4、从一个大的JPEG图象中指定矩形解码。

5、JPEG文件交换格式(JFIF) 的编码和解码

IJL 提供JFIFfiles 的解码,JFIF 规格版本是1.01 and1.02。编码是JFIF version 1.01.。IJL 也支持解码嵌入式的未压缩的缩略图,使用1 or 3 bytes/pixel 适应JFIF versions 1.01 and1.02. 压缩的缩略图未被支持。

数据精度必须是每颜色通道 8-bits。

 

三、JPEG属性和数据存贮

IJL的 “JPEG 属性” 包括全局的和图象属性的JPEG 信息。控制结构确定I/O 特性的处理选项,象二次抽样和颜色转换需求。

IJL使用 JPEG_CORE_PROPERTIES 结构存放 JPEG 属性数据。这个结构被描述为两个部分,第一部份由一组封包的共用库参数组成,另一部份由低级的嵌入的结构组成。Figure 3-2 与 附件B - Data Structure and TypeDefinitions).

用户必须尊循以下的两个JPEG_CORE_PROPERTIES规则:

1.用户必须提供(allocate) JPEG_CORE_PROPERTIES 数据结构。

2. 同样的JPEG_CORE_PROPERTIES 数据结构可能被一连串的JPEG encodings 和/或decodings 在初始化时和清理时再生。

 

JPEG_PROPERTIES是低级的数据结构且它包含一个在JPEG_CORE_PROPERTIES 中每个高级数据结构的复本及一些附加字段。IJL内部使用JPEG_PROPERTIES, 而不是JPEG_CORE_PROPERTIES, 所以这个结构隔离了内部的变量。

对于高级用户JPEG_PROPERTIES 数据结构可能会使用一些扩充的接口性能。例如:用户可能要自定义的Huffman 表或 量化表(quantization tables) 直接至JPEG_PROPERTIES, 而越过默认表(Chapter 7, AdvancedIJL Features 有更多的信息)。

JPEG_CORE_PROPERTIES andJPEG_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) 成功码。了解详情参看 Appendix B - Data Structure and Type Definitions。 转换错误码至一个文本描述,使用函数 ijlErrorStr()。

函数 ijlGetLibVersion() 返回IJL库的版本及其它相关信息。

注意,ijlErrorStr()和ijlGetLibVersion() 函数返回的是一个指向静态变量的指针,所以应用程序不需要释放这些指针。

The Intel® JPEG LibraryApplication Programming Interface

// 初始化 IJL.

IJLERR ijlInit (JPEG_CORE_PROPERTIES *jcprops);

// Clean up the IJL.

IJLERR ijlFree (JPEG_CORE_PROPERTIES *jcprops);

// Use the IJL to read data from a buffer or a file.

IJLERRijlRead (JPEG_CORE_PROPERTIES *jcprops, IJLIOTYPE iotype);

// Use the IJL to write data into a buffer or a file.

IJLERR ijlWrite (JPEG_CORE_PROPERTIES *jcprops, IJLIOTYPE iotype);

// Return the version number of the IJL.

const IJLibVersion* ijlGetLibVersion( );

// Return a pointer to a string with error description.

const char* ijlErrorStr(IJLERR code);

此段描述设计及执行一些IJL的共用特性,及一些例子。

一、初始化

在使用之前,IJL必须初始化,使用ijlInit( )完成初始化。在每一个分配JPEG_CORE_PROPERTIES 数据结构的时候,只能进行一次初始化。

如果一个程序需要调用多个编、解码函数,应用程序需要在任一调用之前调用ijlInit( )更多的初始化需要在每个编、解码调用之间进行。

使用ijlFree( )释放 JPEG_CORE_PROPERTIES 且必须与初始化一一对应。

二、释放

用ijlFree( )释放内存及相关的系统资源。

三、读数据

使用ijlRead(JPEG_CORE_PROPERTIES *jcprops, IJLIOTYPE iotype)函数访问JPEG的压缩数据。第二个参数用来指定在解码期间的JPEG的数据单元(如:一个文件或一个缓存区),访问模式(mode of access),及缩放比例。

有如下两种约定:XXXX 代表访问模式

1.IJL_JBUFF_XXXX (表示JPEG数据是一个缓存).

2.IJL_JFILE_XXXX(表示JPEG数据是一个标准文件).

读数据时,访问模式必须是: READPARAMS, READHEADER,READENTROPY,READWHOLEIMAGE,,READONEHALF,READONEQUARTER,READONEEIGHTH,READTHUMBNAIL。

 

IJLIOTYPE

描述

IJL_JXXXX_READPARAMS

表示读JPEG 参数 如:高,宽,通道数量,二次抽样等。,

例如如下的分析:

SOI | [tables/misc] like APPn and DQT |

SOF | [tables/misc] like DHT | stops at SOS

Note: bit stream must start with SOI marker.

IJL_JXXXX_READHEADER

 

表示读一些特征数据,如:霍夫曼表,量化表,其它杂项。

例如:

SOI | [tables/misc] | EOI (or stops at SOF or SOS)

Note: bit stream must start with SOI marker.

IJL_JXXXX_READENTROPY

 

表示读压缩图片的格式。与 READWHOLEIMAGE相同,除了位流可能包含的特征表。.

For example:

SOI | [tables/misc] | SOF [tables/misc] like DHT | SOS | EOI

Note: in this case only (READENTROPY), APP0 segments are skipped over.

IJL_JXXXX_READWHOLEIMAGE

表示读压缩图片数据的交换格式,如:整个的JPEG位流。

例如:

SOI | [tables/misc] like APPn and DQT |

SOF [tables/misc] like DHT | SOS | EOI

IJL_JXXXX_READONEHALF

 

图象解码比例是½

(See READENTROPY).

IJL_JXXXX_READONEQUARTER

 

图象解码比例是¼.

 (See READENTROPY).

IJL_JXXXX_READONEEIGHTH

 

图象解码比例是1/8

(See READENTROPY).

IJL_JXXXX_READTHUMBNAIL

试图解码在数据流中嵌入的缩略图

(See READPARAMS).

 

 

READPARAMS被用来确定JPEG 的高和宽,用以分配输出的缓存或显示引擎。然后,读其余的数据使用READWHOLEIMAGE or READENTROPY。

READHEADER被用于分析压缩数据规格表,之后使用READENTROPY 来得到压缩的图象数据。

READHEADER/READENTROPY参数对是一个最优的读取JPEG解码格式的方案。

Whendecoding a JPEG bit streamthe following markers, and their correspondingsegments if applicable, are not processed by the IJL (i.e.,they are skippedover): APPn (except APP0 and APP14), DAC,DHP, DNL, EXP, JPGn, RES, SOFn (exceptSOF0, SOF1, and SOF2), and TEM. Any SOFn markers (except SOF0, SOF1, and SOF2)will cause the IJL_UNSUPPORTED_FRAME error.

四、写数据

ijlWrite(JPEG_CORE_PROPERTIES*, IJLIOTYPE iotype) 是写入数据的接口函数。第二个参数是访问方式,但不能指定图象的比例及嵌入式缩略图。

1.IJL_JBUFF_XXXX (指定 JPEG 压缩数据的内存缓存区).

2.IJL_JFILE_XXXX (指定 JPEG 数据的文件).

写入数据时,访问方式必须是WRITEHEADER, WRITEENTROPY, or WRITEWHOLEIMAGE。

详细描述见下表:

IJLIOTYPE  

描述

IJL_JXXXX_WRITEHEADER

 

指定数据流的压缩格式规格表。

下面的标志将被写入:

SOI | tables DQT and DHT | EOI

IJL_JXXXX_WRITEENTROPY

指定压缩图片数据。

与 WRITEWHOLEIMAGE 相同,只是不包含规格表数据。

下面的标志将被写入:

SOI | SOF | [DRI] | SOS | EOI

IJL_JXXXX_WRITEWHOLEIMAGE

 

指定写入JPEG 文件交换格式(如:JPEG using JFIF).

下面的标志将被写入:

SOI | tables/misc APP0, DQT, DHT | SOF | [DRI] | SOS | EOI

 

WRITEHEADER通常被用于写入压缩格式规格表,它与WRITEENTROPY 一般成对使用于JPEG编码。当编码时,IJL 写入COM 标志片段,如果未指定该片段, 将写入默认的“Intel® JPEG Library, [<version>]”。

五、打开一个 JPEG 图片

普通的解码算法:

1.分配 JPEG_CORE_PROPERTIES

2.初始化 IJL.

3.得到JPEG 图象尺寸及其它

4.设置显示参数,分配输出缓存.

5.得到JPEG数据

6.关闭IJL

下面的代码使用 IJL 解码一个JPEG图象文件。请参照 Appendix B - Data Structure and Type Definitions 以得到IJL数据结构的定义,默认值,数据类型定义和错误码的详细的信息。

//----------------------------------------------------------

// An example using the IntelR JPEGLibrary:

// -- Decode a JPEG image from a JFIFfile to general pixel buffer.

//----------------------------------------------------------

BOOL DecodeJPGFileToGeneralBuffer(

                                                                             LPCSTR lpszPathName,

                                                                             DWORD* width,

                                                                             DWORD* height,

                                                                             DWORD* nchannels,

                                                                             BYTE** buffer)

{

         BOOL bres;   //return Value

         IJLERRjerr;

         DWORD x =0; // pixels in scan line

         DWORD y =0; // number of scan lines

         DWORD c =0; // number of channels

         DWORDwholeimagesize;

         BYTE* pixel_buf= NULL;

         // Allocate the IJL JPEG_CORE_PROPERTIES structure.

         JPEG_CORE_PROPERTIESjcprops;

         bres =TRUE;

         __try

         {

                   // Initialize the IntelR JPEG Library.

                   jerr= ijlInit(&jcprops);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Get information on the JPEG image(i.e., width, height,and channels).

                   jcprops.JPGFile= const_cast<LPSTR>(lpszPathName);

                   jerr= ijlRead(&jcprops, IJL_JFILE_READPARAMS);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Set up local data.

                   x= jcprops.JPGWidth;

                   y= jcprops.JPGHeight;

                   c= 3; // Decode into a 3 channel pixel buffer.

                   // Compute size of desired pixel buffer.

                   wholeimagesize= (x * y * c);

                   // Allocate memory to hold the decompressed image data.

                   pixel_buf= new BYTE [wholeimagesize];

                   if(NULL == pixel_buf)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Set up the info on the desired DIB properties.

                   jcprops.DIBWidth= x;

                   jcprops.DIBHeight= y; // Implies a bottom-up DIB.

                   jcprops.DIBChannels= c;

                   jcprops.DIBColor= IJL_BGR;

                   jcprops.DIBPadBytes= 0;

                   jcprops.DIBBytes= pixel_buf;

                   // 设置JPG 色彩空间… 这总是有一些推策,因为JPEG是个“色盲”

//(也就是说位流中没有告诉你是什么色彩空间)设置JPEG色彩空间,

// 本例中我们假定JFIF图象文件是3个通道YCbCr 色彩空间和1 个通道的Y 色彩空间.

                   switch(jcprops.JPGChannels)

                   {

                   case 1:

                            {

                                     jcprops.JPGColor= IJL_G;

                                     break;

                            }

                   case 3:

                            {

                                     jcprops.JPGColor= IJL_YCBCR;

                                     break;

                            }

                   default:

                            {

                                     // This catches everything else,

                                     //but no color twist will be performed by the IJL.

                                     jcprops.DIBColor= (IJL_COLOR) IJL_OTHER;

                                     jcprops.JPGColor= (IJL_COLOR) IJL_OTHER;

                                     break;

                            }

                   }

                   // Now get the actual JPEG image data into the pixelbuffer.

                   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;

                            }

                   }

                   // Clean up the IntelR JPEG Library.

                   ijlFree(&jcprops);

                   *width= x;

                   *height= y;

                   *nchannels= c;

                   *buffer= pixel_buf;

         } // __finally

         return bres;

} //DecodeJPGFileToGeneralBuffer()

 

注意:这段代码是解码一个JPEG图象到一个“常规的象素缓存”因而这个缓存不是专用的。前面讲过,Chapter 3, Architecture Description, 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 的值能够容易的计算:

jcprops.DIBPadBytes =IJL_DIB_PAD_BYTES (width, nchannels)

其中 width 是图象的象素宽度,nchannels 是通道的数量。

下面的代码举例说明如何从一个图象解码到一个 Windows DIB.

//----------------------------------------------------------

// An example using the IntelR JPEGLibrary:

// -- Decode a JPEG image from a JFIFfile to Windows DIB.

//----------------------------------------------------------

BOOL DecodeJPGFileToDIB(

                                                        LPCSTRlpszPathName,

                                                        BITMAPINFOHEADER**dib)

{

         BOOL bres;

         IJLERRjerr;

         DWORDwidth;

         DWORDheight;

         DWORDnchannels;

         DWORDdib_line_width;

         DWORD dib_pad_bytes;

         DWORDwholeimagesize;

         BYTE*buffer = NULL;

         BITMAPINFOHEADER*bmih = NULL;

         // Allocate the IJL JPEG_CORE_PROPERTIES structure.

         JPEG_CORE_PROPERTIESjcprops;

         bres =TRUE;

         __try

         {

                   // Initialize the IntelR JPEG Library.

                   jerr= ijlInit(&jcprops);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Get information on the JPEG image

                   // (i.e., width, height, and channels).

                   jcprops.JPGFile= const_cast<LPSTR>(lpszPathName);

                   jerr= ijlRead(&jcprops,IJL_JFILE_READPARAMS);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Set up local data.

                   width= jcprops.JPGWidth;

                   height= jcprops.JPGHeight;

                   nchannels= 3; // Decode into a 3 channel pixel buffer.

                   // Compute DIB 填充

                   dib_line_width= width * nchannels;

                   dib_pad_bytes= IJL_DIB_PAD_BYTES(width,nchannels);

                   // Compute size of desired pixel buffer.

                   wholeimagesize= ( dib_line_width + dib_pad_bytes ) * height;

                   // Allocate memory to hold the decompressed image data.

                   buffer= new BYTE [sizeof(BITMAPINFOHEADER)+ wholeimagesize];

                   if(NULL == buffer)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   bmih= reinterpret_cast<BITMAPINFOHEADER*>(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;

                   // Set up the info on the desired DIB properties.

                   jcprops.DIBWidth= width;

                   jcprops.DIBHeight= height; // Implies a bottom-up DIB.

                   jcprops.DIBChannels= nchannels;

                   jcprops.DIBColor= IJL_BGR;

                   jcprops.DIBPadBytes= dib_pad_bytes;

                   jcprops.DIBBytes= reinterpret_cast<BYTE*>(buffer +sizeof(BITMAPINFOHEADER));

                   // Set the JPG color space ... this will always be

                   // somewhat of an educated guess at best because JPEG

                   // is "color blind" (i.e., nothing in the bitstream

                   // tells you what color space the data was encoded from).

                   // However, in this example we assume that we are

                   // reading JFIF files which means that 3 channel images

                   // are in the YCbCr color space and 1 channel images are

                   // in the Y color space.

                   switch(jcprops.JPGChannels)

                   {

                   case 1:

                            {

                                     jcprops.JPGColor= IJL_G;

                                     break;

                            }

                   case 3:

                            {

                                     jcprops.JPGColor= IJL_YCBCR;

                                     break;

                            }

                   default:

                            {

                                     // This catches everything else, but no

                                     // color twist will be performed by the IJL.

                                     jcprops.DIBColor= (IJL_COLOR)IJL_OTHER;

                                     jcprops.JPGColor= (IJL_COLOR)IJL_OTHER;

                                     break;

                            }

                   }

                   // Now get the actual JPEG image data into the pixelbuffer.

                   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;

                            }

                   }

                   // Clean up the IntelR JPEG Library.

                   ijlFree(&jcprops);

                   *dib= bmih;

         } // __finally

         return bres;

} // DecodeJPGFileToDIB()

 

六、建立JPEG图象

此段代码针对普通的JPEG图象:

1.初始化 IJL.

2.设置编码参数(如果与默认值不同).

3.写图象数据给IJL.

4.关闭 IJL.

下面的代码段举例说明如何使用IJL从一个JFIF图象缓存编码。请参照 Appendix B - Data Structure and Type Definitions 查看更多有关数据结构等信息。

 

 

//----------------------------------------------------------

// An example using the IntelR JPEGLibrary:

// -- Encode a JFIF file from WindowsDIB.

//----------------------------------------------------------

BOOL EncodeJPGFileFromDIB(

                                                          LPCSTR lpszPathName,

                                                          BITMAPINFOHEADER* bmih)

{

         BOOL bres;

         IJLERRjerr;

         DWORDdib_pad_bytes;

         // Allocate the IJL JPEG_CORE_PROPERTIES structure.

         JPEG_CORE_PROPERTIESjcprops;

         bres =TRUE;

         __try

         {

                   // Initialize the IntelR JPEG Library.

                   jerr= ijlInit(&jcprops);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   if(bmih->biBitCount != 24)

                   {

                            // not supported palette images

                            bres= FALSE;

                            __leave;

                   }

                   dib_pad_bytes= IJL_DIB_PAD_BYTES(bmih->biWidth,3);

                   // Set up information to write from the pixel buffer.

                   jcprops.DIBWidth= bmih->biWidth;

                   jcprops.DIBHeight= bmih->biHeight; // Implies a bottom-up DIB.

                   jcprops.DIBBytes= reinterpret_cast<BYTE*>(bmih) +

                            sizeof(BITMAPINFOHEADER);

                   jcprops.DIBPadBytes= dib_pad_bytes;

                   // Note: the following are default values and thus

                   // do not need to be set.

                   jcprops.DIBChannels= 3;

                   jcprops.DIBColor= IJL_BGR;

                   jcprops.JPGFile= const_cast<LPSTR>(lpszPathName);

                   // Specify JPEG file creation parameters.

                   jcprops.JPGWidth= bmih->biWidth;

                   jcprops.JPGHeight= bmih->biHeight;

                   // Note: the following are default values and thus

                   // do not need to be set.

                   jcprops.JPGChannels= 3;

                   jcprops.JPGColor= IJL_YCBCR;

                   jcprops.JPGSubsampling= IJL_411; // 4:1:1 subsampling.

                   jcprops.jquality= 75; // Select "good" image quality

                   // Write the actual JPEG image from the pixel buffer.

                   jerr= ijlWrite(&jcprops,IJL_JFILE_WRITEWHOLEIMAGE);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

         } // __try

         __finally

         {

                   // Clean up the IntelR JPEG Library.

                   ijlFree(&jcprops);

         }

         return bres;

} // EncodeJPGFileFromDIB()

 

七、中断编码或解码

IJL可以在编码和解码时中断,它可以被 JPEG_PROPERTIES 中定义的中断标志在任一时间中断。

IJL将在完成当前的最小编码单位(MCU)时返回状态标志IJL_INTERRUPT_OK编解码过程也可以在原位恢复执行,只需使用ijlRead( ) ijlWrite( ) 函数即可恢复。用户可以通过JPEG_PROPERTIES 中的roi IJL_RECT 结构的left top 变量计算出定位。

下面的例子中,程序读一个JPEG数据中的最小片段至指定的缓存区,然后程序返回并重复这个过程,直到整个图象被解码完成。这个函数可以用做定时的中止JPEG的编解码过程。

//----------------------------------------------------------

// An example using the IntelR JPEGLibrary:

// -- Interrupted decoding.

//----------------------------------------------------------

// In this example, we are doing fullscale decoding.

// It could also be any of the scaleddecoding modes.

BOOL DecodeJPGFileInterrupted(LPCSTR lpszPathName)

{

         BOOL bres;

         IJLERRjerr;

         DWORDwidth;

         DWORDheight;

         DWORDnchannels;

         DWORDwholeimagesize;

         BYTE* pixel_buf= NULL;

         // Allocate the IJL JPEG_CORE_PROPERTIES structure.

         JPEG_CORE_PROPERTIESjcprops;

         bres =TRUE;

         __try

         {

                   // Initialize the IntelR JPEG Library.

                   jerr= ijlInit(&jcprops);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   jcprops.JPGFile= const_cast<LPSTR>(lpszPathName);

                   // Get information on the JPEG image

                   // (i.e., width, height, and channels).

                   jerr= ijlRead(&jcprops, IJL_JFILE_READPARAMS);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Set up local data.

                   width= jcprops.JPGWidth;

                   height= jcprops.JPGHeight;

                   nchannels= 3; // Decode into a 3 channel pixel buffer.

                   // Compute size of desired pixel buffer.

                   wholeimagesize= (width * height * nchannels);

                   // Allocate memory to hold the decompressed image data.

                   pixel_buf= new BYTE [wholeimagesize];

                   if(NULL == pixel_buf)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Set up the info on the desired DIB properties.

                   jcprops.DIBWidth= width;

                   jcprops.DIBHeight= height; // Implies a bottom-up DIB.

                   jcprops.DIBChannels= nchannels;

                   jcprops.DIBColor= IJL_BGR;

                   jcprops.DIBPadBytes= 0;

                   jcprops.DIBBytes= pixel_buf;

                   // Set the JPG color space ... this will always be

                   // somewhat of an educated guess at best because JPEG

                   // is "color blind" (i.e., nothing in the bitstream

                   // tells you what color space the data was encoded from).

                   // However, in this example we assume that we are

                   // reading JFIF files which means that 3 channel images

                   // are in the YCbCr color space and 1 channel images are

                   // in the Y color space.

                   switch(jcprops.JPGChannels)

                   {

                   case 1:

                            {

                                     jcprops.JPGColor= IJL_G;

                                     break;

                            }

                   case 3:

                            {

                                     jcprops.JPGColor= IJL_YCBCR;

                                     break;

                            }

                   default:

                            {

                                     // This catches everything else, but no

                                     // color twist will be performed by the IJL.

                                     jcprops.DIBColor= (IJL_COLOR)IJL_OTHER;

                                     jcprops.JPGColor= (IJL_COLOR)IJL_OTHER;

                                     break;

                            }

                   }

                   do

                   {

                            // Since the ROI values are updated following

                            // an interrupt. We need to "reset" the ROI

                            // values so that we continue to process over

                            // the entire image.

                            jcprops.jprops.roi.left= 0;

                            jcprops.jprops.roi.right= 0;

                            jcprops.jprops.roi.top= 0;

                            jcprops.jprops.roi.bottom= 0;

                            jcprops.jprops.interrupt= TRUE;

                            jerr= ijlRead(&jcprops, IJL_JFILE_READENTROPY);

                   }while(IJL_INTERRUPT_OK == jerr);

                   //

                   // ... now you probably want to do something with the

                   // decompressed image like display it ...

                   //

         } // __try

         __finally

         {

                   if(NULL != pixel_buf)

                   {

                            delete [] pixel_buf;

                   }

                   // Clean up the IntelR JPEG Library.

                   ijlFree(&jcprops);

         }

         return bres;

} // DecodeJPGFileInterrupted()

 

 

//----------------------------------------------------------

// An example using the IntelR JPEGLibrary:

// -- Decode image row by row.

//----------------------------------------------------------

BOOL DecodeRowByRow(

                                               LPCSTRlpszJpgName,

                                               LPCSTRlpszBmpName)

{

         int  cnt;

         int  width;

         int  height;

         int  nchannels;

         int  bmp_pad;

         int bmp_row_size;

         int bmp_buf_size;

         int  current_row;

         BOOL  bres;

         IJLERR  jerr;

         FILE*  out_file = NULL;

         BYTE*  bmp_bits = NULL;

         BYTE*  bmp_row = NULL;

         BYTE*  bmp_buf = NULL;

         LPBITMAPFILEHEADER  lpbmfh = NULL;

         LPBITMAPINFOHEADER  lpbmih = NULL;

         IJL_RECT             local_roi;

         JPEG_CORE_PROPERTIESjcprops;

         bres =TRUE;

         __try

         {

                   // Initialize the Intel(R) JPEG Library.

                   jerr= ijlInit(&jcprops);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   jcprops.JPGFile= const_cast<LPSTR>(lpszJpgName);

                   // Get information on the JPEG image (i.e., width, height,and

                   channels).

                            jerr= ijlRead(&jcprops, IJL_JFILE_READPARAMS);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   width= jcprops.JPGWidth;

                   height= jcprops.JPGHeight;

                   nchannels= 3;

                   bmp_pad= IJL_DIB_PAD_BYTES(width,nchannels);

                   bmp_row_size= (width * nchannels) + bmp_pad;

                   // allocate buffer to hold one row DIB data

                   bmp_row= new BYTE [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;

                   // allocate buffer to hold entire DIB

                   bmp_buf= new BYTE [bmp_buf_size];

                   if(NULL == bmp_buf)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   bmp_bits= reinterpret_cast<BYTE*>(bmp_buf +

                            sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));

                   jcprops.DIBWidth= width;

                   jcprops.DIBHeight= height;

                   jcprops.DIBChannels= nchannels;

                   jcprops.DIBColor= IJL_BGR;

                   jcprops.DIBPadBytes= bmp_pad;

                   jcprops.DIBBytes= bmp_row;

                   // Set the JPG color space ... this will always be

                   // somewhat of an educated guess at best because JPEG

                   // is "color blind" (i.e., nothing in the bitstream

                   // tells you what color space the data was encoded from).

                   // However, in this example we assume that we are

                   // reading JFIF files which means that 3 channel images

                   // are in the YCbCr color space and 1 channel images are

                   // in the Y color space.

                   switch(jcprops.JPGChannels)

                   {

                   case 1:

                            {

                                     jcprops.JPGColor= IJL_G;

                                     break;

                            }

                   case 3:

                            {

                                     jcprops.JPGColor= IJL_YCBCR;

                                     break;

                            }

                   default:

                            {

                                     // This catches everything else, but no

                                     // color twist will be performed by the IJL.

                                     jcprops.DIBColor= (IJL_COLOR)IJL_OTHER;

                                     jcprops.JPGColor= (IJL_COLOR)IJL_OTHER;

                                     break;

                            }

                   }

                   //

                   // Below is main code to decode image row by row

                   //

                   current_row= 0;

                   do

                   {

                            // ROI is one row

                            local_roi.left= 0;

                            local_roi.top= current_row;

                            local_roi.right= width;

                            local_roi.bottom= current_row + 1;

                            jcprops.jprops.roi= local_roi;

                            // decode ROI

                            jerr= ijlRead(&jcprops, IJL_JFILE_READENTROPY);

                            if(IJL_ROI_OK != jerr)

                            {

                                     bres= FALSE;

                                     __leave;

                            }

                            // copy row data and reverse row order, to obtainbottom-left

                            DIB.

                                     memcpy(bmp_bits+ (height - 1 - current_row) *

                                     bmp_row_size,bmp_row,bmp_row_size);

                            // advance to next row

                            current_row++;

                   }while(current_row != height);

                   //

                   // Now we have decoded image, and do anything on it.

                   // For example write to file...

                  //

                   lpbmfh= reinterpret_cast<LPBITMAPFILEHEADER>(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<LPBITMAPINFOHEADER>(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);

                   }

                   // Clean up the IntelR JPEG Library.

                   ijlFree(&jcprops);

         }

         return bres;

} // DecodeRowByRow()

 

//----------------------------------------------------------

// An example using the IntelR JPEGLibrary:

// -- Encode image by one MCU at a time.

//----------------------------------------------------------

/*

// get_dib_parameters()

//

// Purpose

// gets image sizes from BMP file

//

// Parameters

// FILE* bmp_file - input BMP file togets data from

// int* width - pointer to variable tostore image width

// int* height - pointer to variable tostore image height

// int* nchannels - pointer to variableto store image number of

channels

//

// Returns

// 0 - if read was successfully, ifbmp_file is valid 24 bits per

pixel bitmap

// -1 - if error has occured

//

*/

static int get_dib_parameters(

                                                                   FILE* bmp_file,

                                                                   int* width,

                                                                   int* height,

                                                                   int*nchannels)

{

         int res;

         int cnt;

         BITMAPFILEHEADERbfh;

         BITMAPINFOHEADERbih;

         cnt = fread(&bfh,sizeof(BYTE),sizeof(BITMAPFILEHEADER),bmp_file);

         if(cnt != sizeof(BITMAPFILEHEADER))

         {

                   res= -1;

                   goto Exit;

         }

         if(bfh.bfType != 'MB')

         {

                   res= -1;

                   goto Exit;

         }

         cnt =fread(&bih,sizeof(BYTE),sizeof(BITMAPINFOHEADER),bmp_file);

         if(cnt != sizeof(BITMAPINFOHEADER))

         {

                   res= -1;

                   goto Exit;

         }

         if(bih.biBitCount != 24 || bih.biCompression !=BI_RGB)

         {

                   res= -1;

                   goto Exit;

         }

         *width =bih.biWidth;

         *height =bih.biHeight;

         *nchannels= 3;

         res = 0;

Exit:

         return res;

} // get_dib_parameters()

/*

// get_dib_chunk_data()

//

// Purpose

// gets chunk of data from BMP file.

//

// Parameters

// FILE* bmp_file - input BMP file togets data from

// int dib_chunk_size - size of chunk ofdata

// BYTE* dib_chunk_ptr - pointer tostore data

//

// Return

// 0 - if read was successfully, even ifhave reached the end of a

file

// -1 - if error has occured

//

// Note

// It is assumed that the file pointerhas a correct position.

// For bottom-up DIBs, it is necessaryto invert the order of scan

lines

// that is read from a file. Here forsimplification we do not make

it.

//

*/

static int get_dib_chunk_data(

                                                                   FILE* bmp_file,

                                                                   intdib_chunk_size,

                                                                   BYTE* dib_chunk_ptr)

{

         int cnt;

         int res;

         res = 0;

         cnt =fread(dib_chunk_ptr,sizeof(BYTE),dib_chunk_size,bmp_file);

         if(cnt < dib_chunk_size)

         {

                   res= ferror(bmp_file);

                   if(0 != res)

                   {

                            res= -1;

                   }

         }

         return res;

} // get_dib_chunk_data()

/*

// ijl_compress_large_dib()

//

// Purpose

// to demonstrate one techniques to compresslarge DIBs

// on mcu line by mcu line basis.

//

// Parameters

// char* bmp_file - ASCIIZ string withinput BMP file name

// char* jpg_file - ASCIIZ string withoutput JPG file name

//

// Returns

// 0 - if success

// -1 - if error has occured

//

*/

static intijl_compress_large_dib(

                                                                             char*bmp_name,

                                                                             char*jpg_name)

{

         int i;

         int j;

         int res;

         int width;

         int height;

         int mcu_width;

         int mcu_height;

         int num_x_mcu;

         int num_y_mcu;

         int dib_line_size;

         int nchannels;

         int dib_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;

                   goto Exit;

         }

         // read source image parameters

         res =get_dib_parameters(bmp_file,&width,&height,&nchannels);

         if(res != 0)

         {

                   goto Exit;

         }

         jerr =ijlInit(&jcprops);

         if(IJL_OK != jerr)

         {

                   res= -1;

                   goto Exit;

         }

         jcprops.DIBChannels= nchannels;

         jcprops.DIBWidth= width;

         jcprops.DIBHeight= height;

         jcprops.DIBPadBytes= IJL_DIB_PAD_BYTES(width,nchannels);

         jcprops.DIBColor= IJL_BGR;

         jcprops.DIBSubsampling= (IJL_DIBSUBSAMPLING)IJL_NONE;

         jcprops.JPGFile= jpg_name;

         jcprops.JPGBytes= NULL;

         jcprops.JPGSizeBytes= 0;

         jcprops.JPGChannels= nchannels;

         jcprops.JPGWidth= width;

         jcprops.JPGHeight= height;

         jcprops.JPGColor= IJL_YCBCR;

         jcprops.JPGSubsampling= IJL_411;

         jcprops.jquality= 75;

         // sizes of mcu depend on subsampling

         switch(jcprops.JPGSubsampling)

         {

         case IJL_NONE:

                   mcu_width= 8;

                   mcu_height= 8;

                   break;

         case IJL_422:

                   mcu_width= 16;

                   mcu_height= 8;

                   break;

         case IJL_411:

                   mcu_width= 16;

                   mcu_height= 16;

                   break;

         default:

                   res= -1;

                   goto Exit;

         }

         // calculate number of mcu in image

         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;

         // allocate memory to hold one mcu line

         dib_chunk_ptr= new BYTE [dib_chunk_size];

         if(NULL == dib_chunk_ptr)

         {

                   res= -1;

                   goto Exit;

         }

         // make illusion to IJL, that it is work with buffer

         jcprops.DIBBytes= dib_chunk_ptr;

         // process num_y_mcu line

         for(j = 0; j < num_y_mcu; j++)

         {

                   // get next mcu line from BMP file

                   res= get_dib_chunk_data(bmp_file,dib_chunk_size,dib_chunk_ptr);

                   if(res != 0)

                   {

                            goto Exit;

                   }

                   // it is actually used pointer

                   jcprops.jprops.state.DIB_ptr= dib_chunk_ptr;

                   // process num_x_mcu in mcu line

                   for(i = 0; i < num_x_mcu; i++)

                   {

                            // interrupt after each mcu

                            jcprops.jprops.interrupt= 1;

                            // compress current mcu (advance pointer to next mcu isinternal

                            job)

                                     jerr= ijlWrite(&jcprops,IJL_JFILE_WRITEWHOLEIMAGE);

                            if(IJL_INTERRUPT_OK == jerr)

                            {

                                     // current mcu was encoded successfully

                                     continue;

                            }

                            if(IJL_OK == jerr)

                            {

                                     // job is complete: all image is processed

                                     res= 0;

                                     break;

                            }

                            if(IJL_OK > jerr)

                            {

                                     // error occured

                                     res= -1;

                                     break;

                            }

                   }

         }

         // if after processing num_y_mcu lines the library returns

         IJL_INTERRUPT_OK,

                   // it is to mean that some data are still keeping ininternal

                   buffers.Need to flush it.

                   if(IJL_INTERRUPT_OK == jerr)

                   {

                            // flush data from internal buffers

                            jcprops.jprops.interrupt= 1;

                            jerr= ijlWrite(&jcprops,IJL_JFILE_WRITEWHOLEIMAGE);

                            if(IJL_OK != jerr)

                            {

                                     res= -1;

                                     goto Exit;

                            }

                   }

                   res= 0;

Exit:

                   if(NULL != bmp_file)

                   {

                            fclose(bmp_file);

                   }

                   if(NULL != dib_chunk_ptr)

                   {

                            delete [] dib_chunk_ptr;

                   }

                   ijlFree(&jcprops);

                   return res;

} // ijl_compress_large_dib()

 

 

八、关注矩形的解码(Rectangle-of-InterestDecoding

经常会有需要解压缩和显示一部分图像的情况。使用这个模式,可以使应用程序变得更有效率,且使用更短的时间。

为了获得这样的效率,在解码图像之前,应用程序需要请求一个被JPEG_PROPERTIES中的IJL_RECT 结构填充的“关注矩形解码(ROI)”。

下面的示例演示了如何使用ROI。

//----------------------------------------------------------

// An example using the IntelR JPEGLibrary:

// -- Decode a JPEG image from a JFIFfile using

// the Rectangle-Of-Interest (ROI)method.

//----------------------------------------------------------

BOOL DecodeJPGFileByROI(LPCSTR lpszPathName)

{

         BOOL bres;

         IJLERR jerr;

         DWORDwidth;

         DWORDheight;

         DWORDnchannels;

         DWORDwholeimagesize;

         BYTE*pixel_buf = NULL;

         IJL_RECTlocal_roi;

         // Allocate the IJL JPEG_CORE_PROPERTIES structure.

         JPEG_CORE_PROPERTIESjcprops;

         bres =TRUE;

         __try

         {

                   // Initialize the IntelR JPEG Library.

                   jerr= ijlInit(&jcprops);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   jcprops.JPGFile= const_cast<LPSTR>(lpszPathName);

                   // Get information on the JPEG image

                   // (i.e., width, height, and channels).

                   jerr= ijlRead(&jcprops, IJL_JFILE_READPARAMS);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Set up local data.

                   width= jcprops.JPGWidth;

                   height= jcprops.JPGHeight;

                   nchannels= 3;

                   // Decode into a 3 channel pixel buffer.

                   // For this example, we will allocate an image buffer half

                   // as big as the input image. Then, we will decode the

                   // top half and bottom half of the image separately.

                   // This could of course be extended to partition the image

                   // into several rectangular tiles which would require asmall

                   // (or fixed size) image buffer. This technique yields

                   // greatly increased memory performance for most

                   // applications!

                   wholeimagesize= width * ((height + 1) >> 1) * nchannels;

                   // Allocate memory to hold the decompressed image data.

                   pixel_buf= new BYTE [wholeimagesize];

                   if(NULL == pixel_buf)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Set up the info on the desired DIB properties.

                   jcprops.DIBWidth= width;

                   // Set a bottom-up DIB of half the original image size.

                   jcprops.DIBHeight= (height + 1) >> 1;

                   jcprops.DIBChannels= nchannels;

                   jcprops.DIBColor= IJL_BGR;

                   jcprops.DIBPadBytes= 0;

                   jcprops.DIBBytes= pixel_buf;

                   // Set the JPG color space ... this will always be

                   // somewhat of an educated guess at best because JPEG

                   // is "color blind" (i.e., nothing in the bitstream

                   // tells you what color space the data was encoded from).

                   // However, in this example we assume that we are

                   // reading JFIF files which means that 3 channel images

                   // are in the YCbCr color space and 1 channel images are

                   // in the Y color space.

                   switch(jcprops.JPGChannels)

                   {

                   case 1:

                            {

                                     jcprops.JPGColor= IJL_G;

                                     break;

                            }

                   case 3:

                            {

                                     jcprops.JPGColor= IJL_YCBCR;

                                     break;

                            }

                   default:

                            {

                                     // This catches everything else, but no

                                     // color twist will be performed by the IJL.

                                     jcprops.DIBColor= (IJL_COLOR)IJL_OTHER;

                                     jcprops.JPGColor= (IJL_COLOR)IJL_OTHER;

                                     break;

                            }

                   }

                   // Get the top half of the image.

                   local_roi.left= 0;

                   local_roi.top= 0;

                   local_roi.right= width;

                   local_roi.bottom= (height + 1) >> 1;

                   jcprops.jprops.roi= local_roi;

                   // Now actually get the top half of the JPEG image data

                   // into the pixel buffer.

                   jerr= ijlRead(&jcprops, IJL_JFILE_READENTROPY);

                   if(IJL_ROI_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // ... now you probably want to do something with the

                   // decompressed top half of the image like display it ...

                   // Next, get the bottom half of the image.

                   local_roi.left= 0;

                   local_roi.top= (height + 1) >> 1; //=(height+1)/2;

                   local_roi.right= width;

                   local_roi.bottom= height;

                   jcprops.jprops.roi= local_roi;

                   // Now actually get the bottom half of the JPEG image data

                   // into the pixel buffer.

                   jerr= ijlRead(&jcprops, IJL_JFILE_READENTROPY);

                   if(IJL_ROI_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // ... now you probably want to do something with the

                   // decompressed bottom half of the image like display it...

                   //

         } // __try

         __finally

         {

                   if(NULL != pixel_buf)

                   {

                            delete [] pixel_buf;

                   }

                   // Clean up the IntelR JPEG Library.

                   ijlFree(&jcprops);

         }

         return bres;

} // DecodeJPGFileByROI()

 

九、比例解码

很多JPEG会被解码为原大小的1/2, 1/4, or 1/8 。这叫做 “scaled decoding”, 这意味着比解码整个图象至少会快两倍以上。IJL 支持并行处理比例解码和关注矩形解码及不断编、解码。

实际应用时,比例解码常用于为那些没有嵌入式缩略图的JPEG图像生成缩略图。

下面的表格列出如何计算比例:

Table 5-1 Scaled Decoding Calculations

Scaled

Decoding Type

Resulting Width’ & Height’

I/O Type Specifier

 

1/2 Size

Width’ = INT((Width + 1) / 2)

Height’ = INT((Height + 1) / 2)

IJL_JXXXX_READONEHALF

 

1/4 Size

Width’ = INT((Width + 3) / 4)

Height’ = INT((Height + 3) / 4)

IJL_JXXXX_READONEQUARTER

 

1/8 Size

Width’ = INT((Width + 7) / 8)

Height’ = INT((Height + 7) / 8)

IJL_JXXXX_READONEEIGHTH

 

计算图像的比例使用下列的宏,该宏位于ijl.h文件中:

IJL_DIB_SCALE_SIZE(jpgsize, scale) = (((jpgsize)+(scale)-1)/(scale))

例如:一个 2407 x 491 象素的图像的1/8 图像是301 x 62 pixels。

 

下面的示例是解码得到一个原始图像的1/8 的JPEG图像。

//----------------------------------------------------------

// An example using the IntelR JPEGLibrary:

// -- Decode a JPEG image from a JFIFfile.

// using the scaled decoding method.

//----------------------------------------------------------

BOOL DecodeJPGFileOneEighth(LPCSTR lpszPathName)

{

         BOOL bres;

         IJLERRjerr;

         DWORD width;

         DWORDheight;

         DWORDnchannels;

         DWORDwholeimagesize;

         BYTE*pixel_buf = NULL;

         // Allocate the IJL JPEG_CORE_PROPERTIES structure.

         JPEG_CORE_PROPERTIESjcprops;

         bres =TRUE;

         __try

         {

                   // Initialize the IntelR JPEG Library.

                   jerr= ijlInit(&jcprops);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   jcprops.JPGFile= const_cast<LPSTR>(lpszPathName);

                   // Get information on the JPEG image

                   // (i.e., width, height, and channels).

                   jerr= ijlRead(&jcprops, IJL_JFILE_READPARAMS);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Set up local data.

                   // Note: In this case, width and height are rounded

                   // to the nearest factor of eight.

                   width= (jcprops.JPGWidth + 7) >> 3;

                   height= (jcprops.JPGHeight + 7) >> 3;

                   nchannels= 3; // Decode into a 3 channel pixel buffer.

                   wholeimagesize= (width * height * nchannels);

                   // Allocate memory to hold the decompressed image data.

                   pixel_buf= new BYTE [wholeimagesize];

                   if(NULL == pixel_buf)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Set up the info on the desired DIB properties.

                   jcprops.DIBWidth= width;

                   jcprops.DIBHeight= height; // Implies a bottom-up DIB.

                   jcprops.DIBChannels= nchannels;

                   jcprops.DIBColor= IJL_BGR;

                   jcprops.DIBPadBytes= 0;

                   jcprops.DIBBytes= pixel_buf;

                   // Set the JPG color space ... this will always be

                   // somewhat of an educated guess at best because JPEG

                   // is "color blind" (i.e., nothing in the bitstream

                   // tells you what color space the data was encoded from).

                   // However, in this example we assume that we are

                   // reading JFIF files which means that 3 channel images

                   // are in the YCbCr color space and 1 channel images are

                   // in the Y color space.

                   switch(jcprops.JPGChannels)

                   {

                   case 1:

                            {

                                     jcprops.JPGColor= IJL_G;

                                     break;

                            }

                   case 3:

                            {

                                     jcprops.JPGColor= IJL_YCBCR;

                                     break;

                            }

                   default:

                            {

                                     // This catches everything else, but no

                                     // color twist will be performed by the IJL.

                                     jcprops.DIBColor= (IJL_COLOR)IJL_OTHER;

                                     jcprops.JPGColor= (IJL_COLOR)IJL_OTHER;

                                     break;

                            }

                   }

                   // Now get the actual JPEG image data into the pixel buffer

                   // and scale the output to 1/8 th the original size.

                   jerr= ijlRead(&jcprops, IJL_JFILE_READONEEIGHTH);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   //

                   // ... now you probably want to do something with the

                   // decompressed scaled image like display it ...

                   //

         }

         __finally

         {

                   if(NULL != pixel_buf)

                   {

                            delete [] pixel_buf;

                   }

                   // Clean up the IntelR JPEG Library.

                   ijlFree(&jcprops);

         }

         return bres;

} // DecodeJPGFileOneEighth()

 

十、嵌入的缩略图解码E

IJL支持嵌入至JFIF图像文件的未压缩的RGB缩略图(1字节/象素或3字节/象素)的解码,并且JFIF的版本是1.01和1.02的。

压缩的缩略图现在不被支持。

在解码之前,用户必须提供一个24bit的DIB,且至少有256x256象素。这是因为,JFIF嵌入缩略图的最大尺寸256x256象素。同样,用户如果需要一个缩略图是24bit RGB,DIBColor段必须被设置为 IJL_RGB。当调用ijlRead( )IJLIOTYPE 参数设为IJL_JXXXX_READTHUMBNAIL

这个IJLIOTYPE 可以与IJL_JXXXX_READPARAMS交替的使用。结果该函数调用之后, JPEG_CORE_PROPERTIES 数据结构的更新如下:

1. 缩略图的宽、高被保存在JPGThumbWidth JPGThumbHeight如果值为 0 则表示没有缩略图或格式不支持。

2.DIBBytes 段取代了表示象素值缓存的指针。

实际上,IJL不支持缩略图的所有者属情。

 

十一、渐进图像支持(Progressive Image Support)

IJL解码支持基于渐进离散余弦变换的JPEG图像。但IJL不支持图像的渐进显示。从 1.5版之后,IJL支持图像的渐进编码。建立一个渐进的JPEG图像,用户将调用 ijlWrite() 函数并使JPEG_PROPERTIES 中的progressive_found 段设为。如下面的代码:

...

JPEG_CORE_PROPERTIES jcprops;

...

ijlInit(&jcprops);

....

// Request to create a progressive image

jcprops.jprops.progressive_found = 1;

ijlWrite(&jcprops,IJL_JXXXX_WRITEWHOLEIMAGE);

使用IJL_JFILE_WRITEWHOLEIMAGEIJL_JBUFF_WRITEWHOLEIMAGE调用ijlWrite() 把图像写入一个文件,或分配至一段缓存。

渐进编码算法,是采用逐渐逼进法或频谱法,扫描次数被固定在库中,并不能被改变。这些参数的设置依靠通道的数量和色彩空间。

这个库支持下列的渐进编码参数:

1-通道的 IJL_G 图像:

scancount is 6, with parameters per each pass as

1 scan; DC component 0; ss = 0, se = 63; ah = 0, al = 1

2 scan; AC component 0; ss = 1, se = 5; ah = 0, al = 2

3 scan; AC component 0; ss = 6, se = 63; ah = 0, al = 2

4 scan; AC component 0; ss = 1, se = 63; ah = 2, al = 1

5 scan; DC component 0; ss = 0, se = 63; ah = 1, al = 0

6 scan; AC component 0; ss = 1, se = 63; ah = 1, al = 0

for 3-channel IJL_YCBCR images:

scan count is 10, with parameters per eachpass as

1 scan; DC components 0,1,2; ss = 0, se = 63;ah = 0, al = 1

2 scan; AC component 0; ss = 1, se = 5; ah =0, al = 2

3 scan; AC component 2; ss = 1, se = 63; ah =0, al = 2

4 scan; AC component 1; ss = 1, se = 63; ah =0, al = 2

5 scan; AC component 0; ss = 6, se = 63; ah =0, al = 2

6 scan; AC component 0; ss = 1, se = 63; ah=2, al = 1

7 scan; DC components 0,1,2; ss = 0, se = 63;ah = 1, al = 0

8 scan; AC component 2; ss = 1, se = 63; ah =1, al = 0

9 scan; AC component 1; ss = 1, se = 63; ah =1, al = 0

10 scan; AC component 0; ss = 1, se = 63; ah= 1, al = 0

for 3-channel IJL_RGB images:

scan count is 8, with parameters per eachpass as

1 scan; DC components 0,1,2; ss = 0, se = 63;ah = 0, al = 1

2 scan; AC component 0; ss = 1, se = 5; ah =0, al = 0

3 scan; AC component 1; ss = 1, se = 5; ah =0, al = 0

4 scan; AC component 2; ss = 1, se = 5; ah =0, al = 0

5 scan; DC component 0,1,2; ss =0, se = 63;ah = 1, al = 0

6 scan; AC component 0; ss = 6, se = 63; ah=0, al = 0

7 scan; AC component 1; ss = 6, se = 63; ah =0, al = 0

8 scan; AC component 2; ss = 6, se = 63; ah =0, al = 0

for 3-channel IJL_OTHER images:

scan count is 8, with parameters per eachpass as

1 scan; DC components 0,1,2; ss = 0, se = 63;ah = 0, al = 1

2 scan; AC component 0; ss = 1, se = 5; ah =0, al = 0

3 scan; AC component 1; ss = 1, se = 5; ah =0, al = 0

4 scan; AC component 2; ss = 1, se = 5; ah =0, al = 0

5 scan; DC component 0,1,2; ss =0, se = 63;ah = 1, al = 0

6 scan; AC component 0; ss = 6, se = 63; ah=0, al = 0

7 scan; AC component 1; ss = 6, se = 63; ah =0, al = 0

8 scan; AC component 2; ss = 6, se = 63; ah =0, al = 0

for 4-channel IJL_RGBA_FPX images:

scan count is 10, with parameters per eachpass as

1 scan; DC components 0,1,2,3; ss =0, se =63; ah = 0, al = 1

2 scan; AC component 0; ss = 1, se = 5; ah =0, al = 0

3 scan; AC component 1; ss = 1, se = 5; ah =0, al = 0

4 scan; AC component 2; ss = 1, se = 5; ah =0, al = 0

5 scan; AC component 3; ss = 1, se = 5; ah =0, al = 0

6 scan; DC component 0,1,2,3; ss =0, se = 63;ah = 1, al = 0

7 scan; AC component 0; ss = 6, se = 63; ah=0, al = 0

8 scan; AC component 1; ss = 6, se = 63; ah =0, al = 0

9 scan; AC component 2; ss = 6, se = 63; ah =0, al = 0

10 scan; AC component 3; ss = 6, se = 63; ah= 0, al = 0

for 4-channel IJL_YCBCRA_FPX images:

scan count is 11, with parameters per eachpass as

1 scan; DC components 0,1,2,3; ss =0, se =63; ah = 0, al = 1

2 scan; AC component 0; ss = 1, se = 5; ah =0, al = 2

3 scan; AC component 2; ss = 1, se = 63; ah =0, al = 1

4 scan; AC component 1; ss = 1, se = 63; ah =0, al = 1

5 scan; AC component 3; ss = 1, se = 63; ah =0, al = 0

6 scan; AC component 0; ss = 6, se = 63; ah =0, al = 2

7 scan; AC component 0; ss = 1, se = 63; ah=2, al = 1

8 scan; DC components 0,1,2,3; ss =0, se =63; ah = 1, al = 0

9 scan; AC component 2; ss = 1, se = 63; ah =1, al = 0

10 scan; AC component 1; ss = 1, se = 63; ah= 1, al = 0

11 scan; AC component 0; ss = 1, se = 63; ah= 1, al = 0

for 4-channel IJL_OTHER images:

scan count is 10, with parameters per eachpass as

1 scan; DC components 0,1,2,3; ss =0, se =63; ah = 0, al = 1

2 scan; AC component 0; ss = 1, se = 5; ah =0, al = 0

3 scan; AC component 1; ss = 1, se = 5; ah =0, al = 0

4 scan; AC component 2; ss = 1, se = 5; ah =0, al = 0

5 scan; AC component 3; ss = 1, se = 5; ah =0, al = 0

6 scan; DC component 0,1,2,3; ss =0, se = 63;ah = 1, al = 0

7 scan; AC component 0; ss = 6, se = 63; ah=0, al = 0

8 scan; AC component 1; ss = 6, se = 63; ah =0, al = 0

9 scan; AC component 2; ss = 6, se = 63; ah =0, al = 0

10 scan; AC component 3; ss = 6, se = 63; ah= 0, al = 0

上面列出的符号意义是:

ss –第一个选择谱带的索引; the first index in thespectral selection band;

se – 最后一个选择谱带的索引;the last index in thespectral selection band;

ah – 逐渐逼近法的最高位;the highest bit in thesuccessive approximation;

al –逐渐逼近法的最低位;the lowest bit in thesuccessive approximation.

 

十二、JPEG 图像的内存操作

JPEG在FlashPix 和 TIFF 6.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的指针取代了。This bug was fixed in the IJLversion 1.5.

从一个 buffer 解码JPEG数据参看下面的步骤:

得到有JPEG 数据的buffer;

设置JPEG_CORE_PROPERTIES 结构的相关字段:

JPGFile = NULL

JPGBytes = buffer的指针

JPGSizeBytes =buffer 的大小(按字节的)

以IJL_BUFF_READEWHOLEIMAGE 做为参数调用 ijlRead() 函数。

下面示例演示如何从buffer读,或写数据。

//----------------------------------------------------------

// An example using the Intel(R) JPEGLibrary:

// -- Decode image from a JFIF buffer.

//----------------------------------------------------------

BOOL DecodeFromJPEGBuffer(

                                                          BYTE* lpJpgBuffer,

                                                          DWORD dwJpgBufferSize,

                                                          BYTE** lppRgbBuffer,

                                                          DWORD* lpdwWidth,

                                                          DWORD* lpdwHeight,

                                                          DWORD* lpdwNumberOfChannels)

{

         BOOL bres;

         IJLERRjerr;

         DWORD dwWholeImageSize;

         BYTE*lpTemp = NULL;

         // Allocate the IJL JPEG_CORE_PROPERTIES structure.

         JPEG_CORE_PROPERTIESjcprops;

         bres =TRUE;

         __try

         {

                   // Initialize the Intel(R) JPEG Library.

                   jerr= ijlInit(&jcprops);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Get information on the JPEG image

                   // (i.e., width, height, and channels).

                   jcprops.JPGFile= NULL;

                   jcprops.JPGBytes= lpJpgBuffer;

                   jcprops.JPGSizeBytes= dwJpgBufferSize;

                   jerr= ijlRead(&jcprops, IJL_JBUFF_READPARAMS);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Set the JPG color space ... this will always be

                   // somewhat of an educated guess at best because JPEG

                   // is "color blind" (i.e., nothing in the bitstream

                   // tells you what color space the data was encoded from).

                   // However, in this example we assume that we are

                   // reading JFIF files which means that 3 channel images

                   // are in the YCbCr color space and 1 channel images are

                   // in the Y color space.

                   switch(jcprops.JPGChannels)

                   {

                   case 1:

                            {

                                     jcprops.JPGColor= IJL_G;

                                     jcprops.DIBColor= IJL_RGB;

                                     jcprops.DIBChannels= 3;

                                     break;

                            }

                   case 3:

                            {

                                     jcprops.JPGColor= IJL_YCBCR;

                                     jcprops.DIBColor= IJL_RGB;

                                     jcprops.DIBChannels= 3;

                                     break;

                            }

                   default:

                            {

                                     // This catches everything else, but no

                                     // color twist will be performed by the IJL.

                                     jcprops.JPGColor= IJL_OTHER;

                                     jcprops.DIBColor= IJL_OTHER;

                                     jcprops.DIBChannels= jcprops.JPGChannels;

                                     break;

                            }

                   }

                   // Compute size of desired pixel buffer.

                   dwWholeImageSize= jcprops.JPGWidth * jcprops.JPGHeight *

                            jcprops.DIBChannels;

                   // Allocate memory to hold the decompressed image data.

                   lpTemp= new BYTE [dwWholeImageSize];

                   if(NULL == lpTemp)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Set up the info on the desired DIB properties.

                   jcprops.DIBWidth= jcprops.JPGWidth;

                   jcprops.DIBHeight= jcprops.JPGHeight;

                   jcprops.DIBPadBytes= 0;

                   jcprops.DIBBytes= lpTemp;

                   // Now get the actual JPEG image data into the pixelbuffer.

                   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;

                            }

                   }

                   // Clean up the Intel(R) JPEG Library.

                   ijlFree(&jcprops);

                   *lpdwWidth= jcprops.DIBWidth;

                   *lpdwHeight= jcprops.DIBHeight;

                   *lpdwNumberOfChannels= jcprops.DIBChannels;

                   *lppRgbBuffer= lpTemp;

         } // __finally

         return bres;

} // DecodeFromJPEGBuffer()

//----------------------------------------------------------

// An example using the Intel(R) JPEGLibrary:

// -- Encode Windows DIB to JPEG buffer.

//----------------------------------------------------------

BOOL EncodeToJPEGBuffer(

                                                        BYTE*lpRgbBuffer,

                                                        DWORDdwWidth,

                                                        DWORDdwHeight,

                                                        BYTE**lppJpgBuffer,

                                                        DWORD*lpdwJpgBufferSize)

{

         BOOL bres;

         IJLERRjerr;

         DWORDdwRgbBufferSize;

         BYTE*lpTemp;

         // Allocate the IJL JPEG_CORE_PROPERTIES structure.

         JPEG_CORE_PROPERTIESjcprops;

         bres = TRUE;

         __try

         {

                   // Initialize the Intel(R) JPEG Library.

                   jerr= ijlInit(&jcprops);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   dwRgbBufferSize= dwWidth * dwHeight * 3;

                   lpTemp= new BYTE [dwRgbBufferSize];

                   if(NULL == lpTemp)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Set up information to write from the pixel buffer.

                   jcprops.DIBWidth= dwWidth;

                   jcprops.DIBHeight= dwHeight; // Implies a bottom-up DIB.

                   jcprops.DIBBytes= lpRgbBuffer;

                   jcprops.DIBPadBytes= 0;

                   jcprops.DIBChannels= 3;

                   jcprops.DIBColor= IJL_RGB;

                   jcprops.JPGWidth= dwWidth;

                   jcprops.JPGHeight= dwHeight;

                   jcprops.JPGFile= NULL;

                   jcprops.JPGBytes= lpTemp;

                   jcprops.JPGSizeBytes= dwRgbBufferSize;

                   jcprops.JPGChannels= 3;

                   jcprops.JPGColor= IJL_YCBCR;

                   jcprops.JPGSubsampling= IJL_411; // 4:1:1 subsampling.

                   jcprops.jquality= 75; // Select "good" image quality

                   // Write the actual JPEG image from the pixel buffer.

                   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= jcprops.JPGSizeBytes;

                   // Clean up the Intel(R) JPEG Library.

                   ijlFree(&jcprops);

         }

         return bres;

} // EncodeToJPEGBuffer()

十三、Odd Data Formats

Most of today’s JPEG files are stored in the JPEG FileInterchange Format (JFIF), and the IJL supports JFIF version 1.02. JFIF is aminimal file format that enables JPEG bit streams to be exchanged between awide variety of platforms and applications. One feature of JFIF is that it specifiesa standard color space. JFIF files are stored using either the 3-channelluminance/chrominance color space (YCbCr as defined by CCIR 601 (256 levels)),or the 1-channel grayscale color space (only the Y component of YCbCr).

However, the JPEG interchange format (not JFIF) definescompressed data storage formats that allow a great deal of flexibility to therepresentation of a set of data. A JPEG bit stream may have many meanings otherthan the common JFIF 3-channel, 2-D interleaved plane image data.

A JPEG image does not necessarily contain anyinformation that specifies the color space of the image data. Any JPEG decoderis thus forced to make assumptions about the color format of some JPEG images.Modern file formats like TIFF 6.0 and FlashPix contain enough color space informationto avoid this ambiguity.

JPEGis often called “color blind”. This is because nothing within a JPEG bit streamindicates what color format was used to encode the image data. When the colorformat of a JPEG image is unknown, or not supported by the IJL (i.e., Adobe’s*CMYK), it is suggested that the user specify the IJL_OTHER color space format for both the JPGColor and DIBColor fields in the JPEG_CORE_PROPERTIES data structure. This technique prevents theIJL from applying a color space conversion. Then, it becomes the user’s responsibilityto perform their own color space manipulation (if so desired) outside of theIJL.

Ifa JPEG bit stream indicates that data will be stored in separate planes, theIJL will present the data in a pixel-interleaved format. This may causeunexpected results, especially for data represented using multiple scans (i.e.,one scan per block-row).

 

第四章 预处理及后处理

一、DIBs

设备无关位图(DIB)图像数据存贮为一个字节型的交叉存取格式,每通道的一个字节(8位)。Windows 24-bit DIB, 存贮形式如下图:

IJL可以从一个buffer得到数据,也可以解码一个JPEG数据至一个buffer。用户需要关心色彩通道的数量,色彩空间的解释,和行末的填充。

IJL 支持输入数据:

隔行扫描的色彩平面,Interleaved color planes.

非二次抽样Non-subsampled)数据 (除了 IJL_YCBCR 色彩空间以外, 这个空间仅支持4:2:2二次抽样象素的隔行扫描)。

颜色值是 1 to 255。

图像宽度是 1 to 65,535。

图像高度是 -65,535 to 65,535 (值 > 0 表示 bottom-up DIB).

行尾填充,或填充字节,必须 >= 0.

缩略图的输出DIBs, 宽和高的绝对值不能超过255,色彩空间必须是3 通道的 IJL_RGBor IJL_BGR

二、IJL Color Spaces

下列表格举例说明IJL支持的不同的DIB and JPEG色彩空间。

Table 6-1 IJL Supported Color Spaces

IJL Color Space

Valid IJL DIB Color Space?

Valid IJL JPEG Color Space?

Description

 

IJL_G

Yes

Yes

灰度图像,只有一个亮度通道.

IJL_RGB

Yes

Yes

RGB (red-green-blue) 3 or 4 channel color  space

IJL_BGR

Yes

No

RGB 3 channel color space,但顺序是 BGR.

IJL_RGBA_FPX

Yes

Yes

FlashPix  RGB 4 channel color space with pre-multiplied opacity.

IJL_YCBCR

 

Yes

Yes

CCIR 601 YCbCr (luminance-chrominance)

3 channel color space. Starting fromversion 1.5, the IJL supports the specific 4:2:2 subsampled pixel interleaved format used both as input data format for encoding, and output data format for decoding. In this case

the data sequence is set to be Y0-Cb0-Y1- Cr0-Y2-Cb1-Y3-Cr1-... .

IJL_YCBCRA_FPX

 

No

Yes

FlashPix YCbCr 4 channel color space with

pre-multiplied opacity and the YCbCr values

are stored "flipped" (i.e., X' = 255 - X).

IJL_OTHER

 

Yes

Yes

Unknown color space where the user

specifies the number of channels.

IJL_G 色彩空间指定DIB存贮为一个只有亮度的每通道8位的格式。这个空间被定义为只有亮度或YCbCr 色彩空间的Y分量,且亮度级是256级。

IJL_RGB 色彩空间是每通道8位的,被sRGB定义的,数据存贮是按每像素由低到高 Red, Green, Blue存放的。.

IJL_BGR IJL_RGB 类似,只是排列顺序按照 Blue, Green, Red。 IJL_BGR 支持从Windows DIBs and Bitmaps (使用BGR顺序的)快速的输入输出。

IJL_RGBA_FPX IJL_YCBCRA_FPX 颜色是 FlashPix 4通道色彩空间和自左乘不透明的,并提供FlashPixJPEG压缩文件很大的兼容性。

IJL_YCBCR 色彩空间是一个标准的 YCbCr 色彩空间,被 CCIR 601 定义为256 级 (8-bit)每通道。这是在JPEG图像中使用最多的并且被JFIF,EXIF, TIFF, FlashPix, and SPIFF 文件格式支持。它被推荐用来处理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”。

备注:

RGB1   2色,每个像素用1位表示,需要调色板

RGB4   16色,每个像素用4位表示,需要调色板

RGB8   256色,每个像素用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通道值)

YUY2   YUY2格式,以4:2:2方式打包

YUYV   YUYV格式(实际格式与YUY2相同)

YVYU   YVYU格式,以4:2:2方式打包

UYVY   UYVY格式,以4:2:2方式打包

AYUV   带Alpha通道的4:4:4 YUV格式

Y41P   Y41P格式,以4:1:1方式打包

Y411   Y411格式(实际格式与Y41P相同)

Y211   Y211格式

IF09   IF09格式

IYUV   IYUV格式

YV12   YV12格式

YVU9   YVU9格式

下面分别介绍各种RGB格式。

¨RGB1、RGB4、RGB8都是调色板类型的RGB格式,在描述这些媒体类型的格式细节时,通常会在BITMAPINFOHEADER数据结构后面跟着

一个调色板(定义一系列颜色)。它们的图像数据并不是真正的颜色值,而是当前像素颜色值在调色板中的索引。以RGB1(2色位图

)为例,比如它的调色板中定义的两种颜色值依次为0x000000(黑色)和0xFFFFFF(白色),那么图像数据001101010111…(每个像

素用1位表示)表示对应各像素的颜色为:黑黑白白黑白黑白黑白白白…。

¨RGB565使用16位表示一个像素,这16位中的5位用于R,6位用于G,5位用于B。程序中通常使用一个字(WORD,一个字等于两个字

节)来操作一个像素。当读出一个像素后,这个字的各个位意义如下:

    高字节             低字节

RR R R R G G G     G G G B B B B B

可以组合使用屏蔽字和移位操作来得到RGB各分量的值:

#defineRGB565_MASK_RED    0xF800

#defineRGB565_MASK_GREEN  0x07E0

#defineRGB565_MASK_BLUE   0x001F

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位不用)。使用一个字读出一个像素后,这个字的各个位意义如下:

    高字节            低字节

XR R R R G G       G G G B B B BB       (X表示不用,可以忽略)

可以组合使用屏蔽字和移位操作来得到RGB各分量的值:

#defineRGB555_MASK_RED    0x7C00

#defineRGB555_MASK_GREEN  0x03E0

#defineRGB555_MASK_BLUE   0x001F

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各分量的排列顺序为:BGR BGR BGR

…。通常可以使用RGBTRIPLE数据结构来操作一个像素,它的定义为:

typedefstruct tagRGBTRIPLE {

 BYTE rgbtBlue;    // 蓝色分量

 BYTE rgbtGreen;   // 绿色分量

 BYTE rgbtRed;     // 红色分量

}RGBTRIPLE;

¨RGB32使用32位来表示一个像素,RGB分量各用去8位,剩下的8位用作Alpha通道或者不用。(ARGB32就是带Alpha通道的RGB32。)

注意在内存中RGB各分量的排列顺序为:BGRA BGRA BGRA…。通常可以使用RGBQUAD数据结构来操作一个像素,它的定义为:

typedef struct tagRGBQUAD {

BYTE    rgbBlue;     // 蓝色分量

BYTE   rgbGreen;     // 绿色分量

BYTE   rgbRed;       // 红色分量

BYTE   rgbReserved;  // 保留字节(用作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分量排列顺序如下:

Y0U0 Y1 V0    Y2 U2 Y3 V2 …

¨YVYU格式跟YUY2类似,只是图像数据中YUV分量的排列顺序有所不同:

Y0V0 Y1 U0    Y2 V2 Y3 U2 …

¨UYVY格式跟YUY2类似,只是图像数据中YUV分量的排列顺序有所不同:

U0Y0 V0 Y1    U2 Y2 V2 Y3 …

¨AYUV格式带有一个Alpha通道,并且为每个像素都提取YUV分量,图像数据格式如下:

A0Y0 U0 V0    A1 Y1 U1 V1 …

¨Y41P(和Y411)格式为每个像素保留Y分量,而UV分量在水平方向上每4个像素采样一次。一个宏像素为12个字节,实际表示8个像

素。图像数据中YUV分量排列顺序如下:

U0Y0 V0 Y1    U4 Y2 V4 Y3    Y4 Y5 Y6 Y8 …

¨Y211格式在水平方向上Y分量每2个像素采样一次,而UV分量每4个像素采样一次。一个宏像素为4个字节,实际表示4个像素。图像

数据中YUV分量排列顺序如下:

Y0U0 Y2 V0    Y4 U4 Y6 V4 …

¨YVU9格式为每个像素都提取Y分量,而在UV分量的提取时,首先将图像分成若干个4 x 4的宏块,然后每个宏块提取一个U分量和一

个V分量。图像数据存储时,首先是整幅图像的Y分量数组,然后就跟着U分量数组,以及V分量数组。IF09格式与YVU9类似。

¨IYUV格式为每个像素都提取Y分量,而在UV分量的提取时,首先将图像分成若干个2 x 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_G

1

 IJL_G

1

Y,Y,…

 CC No & US No  

 IJL_G

1

 IJL_RGB

3

YYY,YYY,…

 CC No & US No  

 IJL_G

1

 IJL_BGR

3

YYY,YYY,…

(see note1 below)

 CC No & US No  

 IJL_G

1

 IJL_RGBA_ FPX

4

YYYO,YYYO,…

 CC No & US No 

 IJL_RGB

3

 IJL_RGB

3

RGB,RGB,…

 1:1:1 CC No & US No

 4:1:1 CC No & US Yes 

 4:2:2 CC No & US Yes 

 IJL_RGB

3

 IJL_BGR

3

BGR,BGR,…

 1:1:1 CC No & US No 

 4:1:1 CC No & US Yes 

 4:2:2 CC No & US Yes 

IJL_RGB

3

IJL_RGBA_FPX

4

RGBO,RGBO,…

1:1:1 CC No & US No

4:1:1 CC No & US Yes

4:2:2 CC No & US Yes

IJL_RGBA_ FPX

4

IJL_RGBA_ FPX

4

RGBA, RGBA, …

(see note 2 below)

1:1:1:1 CC No & US No

4:1:1:4 CC No & US Yes

4:2:2:4 CC No & US Yes

IJL_YCBCR

3

IJL_G

1

Y,Y,…

1:1:1 CCNo & US No

4:1:1 CC No & US Yes

4:2:2 CC No & US Yes

IJL_YCBCR

3

IJL_YCBCR

3

Y0-Cb0-Y1-Cr0-

Y2-Cb1-...

(see note 4 below)

4:2:2 CC No & US No

IJL_YCBCR

3

IJL_RGB

3

RGB, RGB, …

1:1:1 CC Yes & US No

4:1:1 CC Yes & US Yes

4:2:2 CC Yes & US Yes

IJL_YCBCR

3

IJL_BGR

3

BGR, BGR, …

1:1:1 CC Yes & US No

4:1:1 CC Yes & US Yes

4:2:2 CC Yes & US Yes

IJL_YCBCR

3

IJL_RGBA_ FPX

 

4

RGBO, RGBO, …

1:1:1 CC Yes & US No

4:1:1 CC Yes & US Yes

4:2:2 CC Yes & US Yes

IJL_YCBCRA_ FPX

 

4

IJL_RGBA_ FPX

 

4

RGBA, RGBA, …

(see note 3 below)

1:1:1:1 CC Yes & US No

4:1:1:4 C Yes & US Yes

4:2:2:4 C Yes & US Yes

IJL_OTHER

n

IJL_OTHER

1<=m<n

X0..X(m-1),

X0..X(m-1),

CC No & US if needed

IJL_OTHER

n

IJL_OTHER

m = n

X0..X(n-1),

X0..X(n-1),

CC No & US if needed

IJL_OTHER

n

IJL_OTHER

m>n

X0..X(n-1)En..E(m-1),

X0..X(n-1)En..E(m-1),

CC No & US if needed

 

符号说明:

符号

描述

Y

亮度通道

Cb

Cr 色度通道 (遮盖红色至兰绿域covering the red to blue-green range)

Cr

Cb 色度通道 (遮盖兰色至黄域(covering the blue to yellow range)

R

红通道

G

绿通道

B

兰通道

E

空值(i.e., the existing memory contents are not over written)

O

不透明值 (i.e., for 8-bit samples, it equals 255)

X

通道任意值

CC

色彩空间转换

US

不采样

SS

二次采样

注解:

1. 注意, 这个描述是正确的,就象IJL_G IJL_RGB

2. Pursuant to the FlashPix specification,the pre-multiplied opacity is preserved.

3. Pursuant to the FlashPix specification, an"inverse flip" (that is,X = 255 – X') is performed and the pre-multiplied opacity is preserved.

4. Starting fromversion 1.5, the IJL supportsIJL_YCBCR DIB color space (currently for DIBSubsampling = IJL_422 only).Decoding is implemented only for JPGSubsampling= IJL_422.

 

五、编码及预处理矩阵

下表列出IJL中色彩空间编码集合及预处理选项。

DIB 色彩空间

DIB 通道

JPEG  色彩空间

JPEG 通道

编码数据格式

预处理

IJL_G

1

IJL_G

1

Y,Y,…

CC No &SSNo

IJL_G

1

IJL_YCBCR

3

Y00, Y00, …

(see note 1 below)

1:1:1 CC No & SS No

4:1:1 CC No & SS Yes

4:2:2 CC No & SS Yes

IJL_RGB

3

IJL_G

1

Y,Y,…

CC Yes&SS No

IJL_RGB

3

IJL_RGB

3

RGB, RGB, …

1:1:1 CC No & SS No

4:1:1 CC No & SS Yes

4:2:2 CC No & SS Yes

IJL_RGB

3

IJL_YCBCR

3

YCbCr, YCbCr, …

1:1:1 CC Yes & SS No

4:1:1 CC Yes & SS Yes

4:2:2 CC Yes & SS Yes

IJL_RGB

4

IJL_YCBCR

3

YCbCr, YCbCr, …

(see note 2 below)

1:1:1 CC Yes & SS No

4:1:1 CC Yes & SS Yes

4:2:2 CC Yes & SS Yes

IJL_BGR

3

IJL_G

1

Y,Y,…

CC Yes&SS No

IJL_BGR

3

IJL_RGB

3

RGB, RGB, …

1:1:1 CC No & SS No

4:1:1 CC No & SS Yes

4:2:2 CC No & SS Yes

IJL_BGR

3

IJL_YCBCR

3

YCbCr, YCbCr, …

1:1:1 CC Yes & SS No

4:1:1 CC Yes & SS Yes

4:2:2 CC Yes & SS Yes

IJL_YCBCR

3

IJL_YCBCR

3

YCbCr, YCbCr, …

(see note 5 below)

4:2:2 CC No & SS Yes

IJL_RGBA_FPX

4

IJL_RGBA_FPX

4

RGBA, RGBA, …

(see note 3 below)

1:1:1:1 CC No & SS No

4:1:1:4 CC No & SS Yes

4:2:2:4 CC No & SS Yes

IJL_RGBA_FPX

4

IJL_YCBCRA_FPX

4

YCbCrA, YCbCrA, …

(see note 4 below)

1:1:1:1 CC Yes & SS No

4:1:1:4 CC Yes & SS Yes

4:2:2:4 CC Yes & SS Yes

IJL_OTHER

n

IJL_OTHER

1<=m<n

X0..X(m-1),

X0..X(m-1),

CC No & SS if needed

IJL_OTHER

n

IJL_OTHER

m = n

X0..X(n-1),

X0..X(n-1),

CC No & SS if needed

注释,:

1. 亮度值被保留,色度值被清零。

2. 假定没有左乘不透明度。

3. Pursuant to the FlashPix specification,the pre-multiplied opacity is preserved.

4. Pursuant to the FlashPix specification, a"flip" (i.e., X' = 255 - X) is performed and the pre-multipliedopacity is preserved.

5. The data encoding from DIBColor =IJL_YCBCR to JPGColor = IJL_YCBCR is currently supported only for DIBSubsampling= IJL_422.

 

第五章 IJL高级特性

一、使用CPU代码

IJL 检测处理器的类型并自动选择是好的CPU特定的代码(这是默认选项)。例如:如果你使用IJL在一个Intel® Pentium® 4 处理器的系统中,库将利用专门针对此CPU优化的代码。

通过设置系统注册表的USECPU 键值,你可以指引库使用需要的代码:

0 – 混合代码 (选项针对所有以前的CPU)

4 - PentiumII 优化代码;

5 - PentiumIII 优化代码;

6 - Pentium 4优化代码;

USECPU 是DWORD 类型,位置在:HKEY_LOCAL_MACHINE\Software\IntelCorporation\PLSuite\IJLib。

 

二、设置 DCT 算法

IJL支持两种不同的DCT算法。一个是设置IJL_AAN字段的值,这是基于Arai et al工作的。see [Arai]. 这个算法相当快,但有一些精度的限制。另一个算法提供足够的速度及高精度,源自Intel Integrated Performance Primitives 并针对 Intel体系结构。 默认的选项设置后调用ijlInit().

使用前一个算法,必须设置JPEG_CORE_PROPERTIES结构的jcprops.jprops.dcttype 字段为IJL_AAN。并且需在调用ijlInit()之后,在调用jlRead() 或 ijlWrite() 这前。

 

三、写和读JPEG 注释块

这里介绍两个新的JPEG_CORE_PROPERTIES结构中的字段:

jpeg_comment是指向注释字符串的指针

jpeg_comment_size是注释字符串的长度,包括尾部的zero.

当IJL初始化是,这两个设置被调为“0”,这意味着下面的注释字符串将被插入到编码数据中: “Intel® JPEG Library, [<version>]”. 如果你需要插入自己的注释,设置这两个值。同样提取注释字符串你需要设置指针指向一个缓存区并指明长度。当注释成功的读取并放置到这个缓存区,jpeg_comment_size的值是写入字串的长度。万一缓存的长度不足,IJL将写数据直至缓存区满,并返回错误码IJL_ERR_COM_BUFFER。如果没有注释字段,IJL将不改变缓存的内容及大小。

应用程序必须负责分配和释放缓存所占的内存。

四、自定义JPEG表

IJL允许规定霍夫曼(Huffman)和量化表以实现一些特殊的用途。通过JPEG_PROPERTIES 结构设定。

 

 

五、自定义量化表

IJL 可以接受4个自定义的量化表。IJL通过一个8bit unsigned char 型的行为主或不专弯的形式的8X8的数组来设定量化表。默认是,标准的量化表。在JPEG编码程序中默认使用标准的量化表,就象下面的描述:

static unsigned char DefaultLuminanceQuantTbl[]=

{

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

};

static unsigned charDefaultChrominanceQuantTbl[] =

{

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内部质量水平乘法器调节,并且用于除以输入的数据以减少精度(减小存贮空间)。在图像内部的某一个频率The entries in the quantization arrays correspond to multipliersapplied to certain spatial frequencies within the image.

The lowest-order (DC) component is located in theupper-left hand corner. The following code illustrates adding customquantization tables prior to authoring a JPEG image.

//----------------------------------------------------------

// An example using the IntelR JPEGLibrary:

// -- Author a JPEG image using customquantization tables.

//----------------------------------------------------------

// Your special quantization table goeshere!

static BYTE HQLumQuantTable[] =

{

         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

};

// Your special quantization table goeshere!

static BYTE HQChromQuantTable[] =

{

         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

};

BOOL EncodeJPGFileWithCustomQuantization(

         LPCSTRlpszPathName,

         DWORDwidth,

         DWORDheight,

         DWORDnchannels,

         BYTE*pixel_buf)

{

         BOOL bres;

         IJLERRjerr;

         // Allocate the IJL JPEG_CORE_PROPERTIES structure.

         JPEG_CORE_PROPERTIESjcprops;

         bres = TRUE;

         __try

         {

                   // Initialize the IntelR JPEG Library.

                   jerr= ijlInit(&jcprops);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Set the custom quantization tables. For this example we

                   // assign two custom tables, although up to four arepossible.

                   // Here we also assume the tables specify luminance and

                   // chrominance quantization factors (as in a YCbCr image).

                   jcprops.jprops.maxquantindex= 2;

                   jcprops.jprops.nqtables= 2;

                   jcprops.jprops.rawquanttables[0].quantizer = HQLumQuantTable;

                   jcprops.jprops.rawquanttables[0].ident = 0;

                   jcprops.jprops.rawquanttables[1].quantizer = HQChromQuantTable;

                   jcprops.jprops.rawquanttables[1].ident = 1;

                   // Now that we have assigned the tables, we need to decidewhich

                   // color channels of the authored image will use whichtables.

                   // The ident member of raw quanttables specifies a unique

                   // identifier for each table; we reference the quant_selmember of

                   // each frame (image) component to this identifier.

                   jcprops.jprops.jframe.comps[0].quant_sel = 0;

                   jcprops.jprops.jframe.comps[1].quant_sel = 1;

                   jcprops.jprops.jframe.comps[2].quant_sel = 1;

                   jcprops.jprops.jframe.comps[3].quant_sel = 1;

                   jcprops.DIBWidth= width;

                   jcprops.DIBHeight= height;

                   jcprops.DIBChannels= nchannels; // nchannels MUST BE 3!

                   jcprops.DIBColor= IJL_BGR;

                   jcprops.DIBBytes= pixel_buf;

                   jcprops.JPGFile= const_cast<LPSTR>(lpszPathName);

                   // Specify JPEG file creation parameters.

                   jcprops.JPGWidth= width;

                   jcprops.JPGHeight= height;

                   // Note: the following are default values and thus

                   // do not need to be set.

                   // jcprops.JPGChannels = 3;

                   // jcprops.JPGColor = IJL_YCBCR;

                   // jcprops.JPGSubsampling = IJL_411; // 4:1:1 subsampling.

                   // jcprops.jquality = 75; // Select "good" imagequality

                  // Write theactual JPEG image from the pixel buffer.

                   jerr= ijlWrite(&jcprops, IJL_JFILE_WRITEWHOLEIMAGE);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

         } // __try

         __finally

         {

                   // Clean up the IntelR JPEG Library.

                   ijlFree(&jcprops);

         }

         return bres;

} //EncodeJPGFileWithCustomQuantization()

IJL格式内部的量化表在使用任何数据之前被使用。因此这个表只需在第一次调用ijlWrite( ) 之前传递至IJL。

 

六、自定义霍夫曼表

IJL 允许每幅图有4个霍夫曼表。霍夫曼表用来测定JPEG编码过程运行周期的熵代码。

霍夫曼表被成对的指定:一个表用于一个图像通道的每个直流和交流的频率成份。每个表需要两个结构,一个表示每个符号必须的的位,一个表示实际符号的值。这些结构中的数据格式是与每个JPEG规格中嵌入的霍夫曼表同样的。

下面的代码示例是使用自定义霍夫曼表的

//----------------------------------------------------------

// An example using the IntelR JPEGLibrary:

// -- Author a JPEG image using customHuffman tables.

//----------------------------------------------------------

// Your special Huffman DC Symbol Lengthtable goes here!

static BYTE CustomLuminanceDCBits[] =

{

         0x00, 0x01,0x05, 0x01, 0x01, 0x01, 0x01, 0x01,

         0x01, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00

};

// Your special Huffman DC Symbol tablegoes here!

static BYTE CustomLuminanceDCValues[] =

{

         0x00, 0x01,0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,

         0x0b

};

// Your special Huffman DC Symbol Lengthtable goes here!

static BYTE CustomChrominanceDCBits[] =

{

         0x00, 0x03,0x01, 0x01, 0x01, 0x01, 0x01, 0x01,

         0x01, 0x01,0x01, 0x00, 0x00, 0x00, 0x00, 0x00

};

// Your special Huffman DC Symbol tablegoes here!

static BYTE CustomChrominanceDCValues[] =

{

         0x00, 0x01,0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,

         0x0b

};

// Your special Huffman AC Symbol Lengthtable goes here!

static BYTE CustomLuminanceACBits[] =

{

         0x00, 0x02,0x01, 0x03, 0x03, 0x02, 0x04, 0x03,

         0x05, 0x05,0x04, 0x04, 0x00, 0x00, 0x01, 0x7d

};

// Your special Huffman AC Symbol tablegoes here!

static BYTE CustomLuminanceACValues[] =

{

         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

};

// Your special Huffman AC Symbol Lengthtable goes here!

static unsigned char CustomChrominanceACBits[] =

{

         0x00, 0x02,0x01, 0x02, 0x04, 0x04, 0x03, 0x04,

         0x07, 0x05,0x04, 0x04, 0x00, 0x01, 0x02, 0x77

};

// Your special Huffman AC Symbol tablegoes here!

static unsigned char CustomChrominanceACValues[] =

{

         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

};

BOOL EncodeJPGFileWithCustomHuffman(

                                                                                    LPCSTRlpszPathName,

                                                                                    DWORDwidth,

                                                                                    DWORDheight,

                                                                                    DWORDnchannels,

                                                                                    BYTE*pixel_buf)

{

         BOOL bres;

         IJLERRjerr;

         // Allocate the IJL JPEG_CORE_PROPERTIES structure.

         JPEG_CORE_PROPERTIESjcprops;

         bres =TRUE;

         __try

         {

                   // Initialize the IntelR JPEG Library.

                   jerr= ijlInit(&jcprops);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

                   // Set the custom Huffman tables. For this example, we

                   // assign two sets of custom tables, though up to four are

                   // possible. We also assume the tables specify luminanceand

                   // chrominance Huffman factors (as in a YCbCr image).

                   jcprops.jprops.nhuffActables= 2;

                   jcprops.jprops.nhuffDctables= 2;

                   jcprops.jprops.maxhuffindex= 2;

                   jcprops.jprops.rawhufftables[0].bits = CustomLuminanceDCBits;

                   jcprops.jprops.rawhufftables[0].vals = CustomLuminanceDCValues;

                   jcprops.jprops.rawhufftables[0].hclass = 0;

                   jcprops.jprops.rawhufftables[0].ident = 0;

                   jcprops.jprops.rawhufftables[1].bits = CustomLuminanceACBits;

                   jcprops.jprops.rawhufftables[1].vals = CustomLuminanceACValues;

                   jcprops.jprops.rawhufftables[1].hclass = 1;

                   jcprops.jprops.rawhufftables[1].ident = 0;

                   jcprops.jprops.rawhufftables[2].bits = CustomChrominanceDCBits;

                   jcprops.jprops.rawhufftables[2].vals = CustomChrominanceDCValues;

                   jcprops.jprops.rawhufftables[2].hclass = 0;

                   jcprops.jprops.rawhufftables[2].ident = 1;

                   jcprops.jprops.rawhufftables[3].bits = CustomChrominanceACBits;

                   jcprops.jprops.rawhufftables[3].vals = CustomChrominanceACValues;

                   jcprops.jprops.rawhufftables[3].hclass = 1;

                   jcprops.jprops.rawhufftables[3].ident = 1;

                   // Now that we have assigned the tables, we need to decidewhich

                   // channels of the authored image will use which tables.

                   // The ident member of rawhufftables specifies a unique

                   // identifier for each table; we reference theHuffIdentifier

                   // member of each image (which applies to each component in

                   // increasing order) to this identifier.

                   jcprops.jprops.HuffIdentifierAC[0] = 0;

                   jcprops.jprops.HuffIdentifierDC[0] = 0;

                   jcprops.jprops.HuffIdentifierAC[1] = 1;

                   jcprops.jprops.HuffIdentifierDC[1] = 1;

                   jcprops.jprops.HuffIdentifierAC[2] = 1;

                   jcprops.jprops.HuffIdentifierDC[2] = 1;

                   jcprops.jprops.HuffIdentifierAC[3] = 1;

                   jcprops.jprops.HuffIdentifierDC[3] = 1;

                   jcprops.DIBWidth= width;

                   jcprops.DIBHeight= height;

                   jcprops.DIBChannels= nchannels; // only 3 is valid

                   jcprops.DIBColor= IJL_BGR;

                   jcprops.DIBBytes= pixel_buf;

                   // Specify JPEG file creation parameters.

                   jcprops.JPGWidth= width;

                   jcprops.JPGHeight= height;

                   jcprops.JPGFile= const_cast<LPSTR>(lpszPathName);

                   // Note: the following are default values and thus

                   // do not need to be set.

                   // jcprops.JPGChannels = 3;

                   // jcprops.JPGColor = IJL_YCBCR;

                   // jcprops.JPGSubsampling = IJL_411; // 4:1:1 subsampling.

                   // jcprops.jquality = 75; // Select "good" imagequality

                   // Write the actual JPEG image from the pixel buffer.

                   jerr= ijlWrite(&jcprops, IJL_JFILE_WRITEWHOLEIMAGE);

                   if(IJL_OK != jerr)

                   {

                            bres= FALSE;

                            __leave;

                   }

         } // __try

         __finally

         {

                   // Clean up the IntelR JPEG Library.

                   ijlFree(&jcprops);

         }

         return bres;

} //EncodeJPGFileWithCustomHuffman()

IJL在任何写数据之前格式化霍夫曼表。所以,需要在第一次调用ijlWrite( )的时候传递表至IJL。

七、扩展基线解码

这段描述的技术是格式表信息交叉多IJL使用最小表处理和内存开销。

多数图像格式分开了头,表,和熵信息。一些“瓷片”格式的图像,就象FlashPix, 可以把图像分成很多“瓷片”,每个一个参照JPEG表存贮在文件的另外的地方。优化编码需要这些表信息,以不处理每个“瓷片”,而应保持译码器格式表。之后,霍夫曼或量化表被解码和格式化,这些格式表示要求存贮在IJL的外部。在图象解码之前,格式化表再被复制回JPEG_PROPERTIES结构的适当的位置。

更多的信息请参考白皮书“Using the IJLwith JPEG Compressed FlashPix Files”.

HUFFMAN_TABLE and QUANT_TABLE 结构包含进行适当的解码器格式的霍夫曼和量化表。这些表在JPEG_PROPERTIES 定位象下面的片段: //

// ... a code fragment from the JPEG_PROPERTIES datastructure ...

//

// Tables

DWORD nqtables;

DWORD maxquantindex;

DWORD nhuffActables;

DWORD nhuffDctables;

DWORD maxhuffindex;

QUANT_TABLE jFmtQuant[4];

HUFFMAN_TABLE jFmtAcHuffman[4];

HUFFMAN_TABLE jFmtDcHuffman[4];

short* jEncFmtQuant[4];

HUFFMAN_TABLE *jEncFmtAcHuffman[4];

HUFFMAN_TABLE *jEncFmtDcHuffman[4];

// Allow user-defined tables.

DWORD use_default_htables;

DWORD use_default_qtables;

JPEGQuantTable rawquanttables[4];

JPEGHuffTable rawhufftables[8];

BYTE HuffIdentifierAC[4];

BYTE HuffIdentifierDC[4];

重要的成员是jFmtQuant, jFmtAcHuffman,和jFmtDcHuffman 解码之后,这些表使用IJL_JXXXX_READHEADER, 复制它们到你的持久化存储器。

接下来,解码一个JPEG比特流(即至少假定为简短格式压缩的图像数据), 用户复制格式化表回到 JPEG_PROPERTIES成员并调用ijlRead( )使用 IJL_JXXXX_READWHOLEIMAGE

复制保留表到JPEG_PROPERTIES,要快于在每次调用解码器的时候强制处理和格式化和附加一个表到每个JPEG数据流的前面。

八、参考

[Arai] Arai, Agui, and Nakajima, Trans. IEICE, vol. E 71(11), pp.1095-1097, Nov. 1988.

 

附录 A 词汇表

简短格式 Abbreviated Format (针对压缩图像数据) – 这个格式等于互换格式,只是它可能或不可能包括解码所需的所有表。这个格式在用户应用中提供一种备选(交错)的机制,用于解码需要的部分或全部的表规范数据。

简短格式 Abbreviated Format (针对表规格化数据) – 这个格式只包含表规范数据。意味着解码器中应用的表需要在随后重建一个或更多的图像。

基线模式 Baseline Mode – (又名基于连续离散余弦变换模式)-被JPEG定义的四种图像压缩算法中的一种。这个模式是最简单的DCT-based JPEG 编、解码处理,是在所有的DCT-based JPEG中必须具有的最小能力。图象压缩使用单独扫描,基本的信息如下:

· DCT-based process

· 源图像:每层8-bit抽样

·连续的

· Huffman coding: 2 AC and 2 DC tables

· Decoders 将处理扫描用1, 2, 3, and 4分量

· 隔行和逐行扫描

Bit Stream – 位流。

位流 Channel –图像中颜色的单一分量;

已压缩数据 Compressed Data – 任何已压缩的图像图据和表规范数据。

Compressed Image Data – A coded representation of an image as specified by theJPEG specification.

连续色调图象Continuous-tone Image – 图像分量大小1位的抽样。

离散余弦变换DCT

DIB - (设备无关位图)

Entropy Coding – A lossless procedure that converts a sequence of input symbolsinto a sequence of bits such that the average number of bits per symbolapproaches the entropy of the input symbols.

Extended Baseline Mode - A sequential DCT-based encoding and decoding process inwhich additional capabilities are added beyond the Baseline mode. This modeextends the Baseline mode to a broader range of applications. Here is a summaryof its essential characteristics:

DCT-based process

Source image: 8-bit or 12-bit samples

Sequential or progressive

Huffman or arithmetic coding: 4 AC and 4 DC tables

Decoders shall process scans with 1, 2, 3, and 4components

Interleaved and non-interleaved scans

Grayscale Image – A continuous-tone image that has only one component.

Horizontal Sampling Factor – The relative number of horizontal data units of aparticular component with respect to the number of horizontal data units in theother components.

Huffman Table – The set of variable length codes required in theHuffman coding process.

Huffman Coding – An entropy coding procedure that assigns a variable lengthcode to each input symbol.

IJL -(Intel® JPEG Library)The IJL is a software library for application developers that provides highperformance JPEG encoding and decoding of full color, and grayscale, stillimages. The IJL was developed to take advantage of MMX™ technology if present.

Interchange Format – (a.k.a. JPEG Interchange Format or JIF) A JPEG compressedimage data bit stream that includes all tables that are required by the decoder(i.e., Huffman and quantization tables).

Interleaved – Thedescriptive term applied to the repetitive multiplexing of small groups of dataunits from each component in a scan in a specific order.

JFIF -(JPEG File Interchange Format) A minimal file format which enables JPEG bitstreams to be exchanged between a wide variety of platforms and applications.The JFIF is entirely compatible with the standard JPEG Interchange Format.

JPEG -(Joint Photographic Experts Group) Usually refers to ISO DIS 10918-1 and10918-2, “Digital compression and coding of continuous-tone still images",the compression standard this group created.

Lossless – Adescriptive term for encoding and decoding processes and procedures in whichthe output of the decoding procedure(s) is identical to the input to theencoding procedure(s).

Lossy – Adescriptive term for encoding and decoding processes which are not lossless.

MCU -(Minimum Coded Unit) The minimal set of data written to a compressed JPEGstream. The MCU is, for DCT-based JPEG coding processes, a set of rectangularregions over several channels representing the same pixel-based region. It isalways a multiple of 8 pixels wide and high. Subsampling various colorcomponents of an image generates MCUs with dimensions greater than 8 x 8pixels. For example, common 4:1:1 subsampled JPEG images have a 16 x 16 pixelMCU.

Non-Interleaved – The descriptive term applied to the data unitprocessing sequence when the scan has only one component.

Pixel Buffer – A rectangular array of pixels with each pixel havingthe same number of component values  (colorchannels). The number of components and the color space interpretation of thecomponents are also required.

Pre-Processing – The act of applying various operations to an imageprior to sending it to the JPEG encoder. These operations typically includecolor space conversion and subsampling.

Post-Processing – The act of applying various operations to an imageafter receiving it from the JPEG decoder. These operations typically include upsamplingand inverse color space conversion.

Progressive Mode – One of the four main categories of image compressionprocesses defined by JPEG. This mode is a DCT-based coding process that isachieved by a sequence of scans, each of which codes part of the quantized DCTcoefficient information.

Quantization - A lossy procedure in which the DCT coefficients are linearlyscaled in order to achieve compression.

Quantization Table – The set of 64 integer values used to quantize the DCTcoefficients.

Restart Interval – The integer number of MCUs processed as an independentsequence within a scan.

ROI -(Rectangle-of-Interest) A particular rectangular region of the image which canbe specified by (top, left) and (bottom, right) pixel coordinates. The ROI mustbe contained within the image, but may encompass the total image.

Scan – Asingle pass through the data for one or more of the components in an image.

Subsampling –(a.k.a. Downsampling) A procedure by which the spatial resolution of an imageis reduced.

Table Specification Data – The coded representation from which the tables used inthe encoder and decoder are generated.

Upsampling – Aprocedure by which the spatial resolution of an image is increased.

Vertical Sampling Factor – The relative number of vertical data units of a particularcomponent with respect to the number of vertical data units in the othercomponents.

Zig-Zag Sequence – A specific sequential ordering of the DCT coefficientsfrom (approximately) lowest spatial frequency to highest.

 

 

 
实时流媒体编程(RTP,RTCP,RTSP)

 

流媒体指的是在网络中使用流技术传输的连续时基媒体,其特点是在播放前不需要下载整个文件,而是采用边下载边播放的方式,它是视频会议、IP电话等应用场合的技术基础。RTP是进行实时流媒体传输的标准协议和关键技术,本文介绍如何在Linux下利用JRTPLIB进行实时流媒体编程。

一、流媒体简介

随着Internet的日益普及,在网络上传输的数据已经不再局限于文字和图形,而是逐渐向声音和视频等多媒体格式过渡。目前在网络上传输音频/视频(Audio/Video,简称A/V)等多媒体文件时,基本上只有下载和流式传输两种选择。通常说来,A/V文件占据的存储空间都比较大,在带宽受限的网络环境中下载可能要耗费数分钟甚至数小时,所以这种处理方法的延迟很大。如果换用流式传输的话,声音、影像、动画等多媒体文件将由专门的流媒体服务器负责向用户连续、实时地发送,这样用户可以不必等到整个文件全部下载完毕,而只需要经过几秒钟的启动延时就可以了,当这些多媒体数据在客户机上播放时,文件的剩余部分将继续从流媒体服务器下载。

     流(Streaming)是近年在Internet上出现的新概念,其定义非常广泛,主要是指通过网络传输多媒体数据的技术总称。流媒体包含广义和狭义两种内涵:广义上的流媒体指的是使音频和视频形成稳定和连续的传输流和回放流的一系列技术、方法和协议的总称,即流媒体技术;狭义上的流媒体是相对于传统的下载-回放方式而言的,指的是一种从Internet上获取音频和视频等多媒体数据的新方法,它能够支持多媒体数据流的实时传输和实时播放。通过运用流媒体技术,服务器能够向客户机发送稳定和连续的多媒体数据流,客户机在接收数据的同时以一个稳定的速率回放,而不用等数据全部下载完之后再进行回放。由于受网络带宽、计算机处理能力和协议规范等方面的限制,要想从Internet上下载大量的音频和视频数据,无论从下载时间和存储空间上来讲都是不太现实的,而流媒体技术的出现则很好地解决了这一难题。目前实现流媒体传输主要有两种方法:顺序流(progressive streaming)传输和实时流(realtimestreaming)传输,它们分别适合于不同的应用场合。

顺序流传输

     顺序流传输采用顺序下载的方式进行传输,在下载的同时用户可以在线回放多媒体数据,但给定时刻只能观看已经下载的部分,不能跳到尚未下载的部分,也不能在传输期间根据网络状况对下载速度进行调整。由于标准的HTTP服务器就可以发送这种形式的流媒体,而不需要其他特殊协议的支持,因此也常常被称作HTTP流式传输。顺序流式传输比较适合于高质量的多媒体片段,如片头、片尾或者广告等。

实时流传输 

     实时流式传输保证媒体信号带宽能够与当前网络状况相匹配,从而使得流媒体数据总是被实时地传送,因此特别适合于现场事件。实时流传输支持随机访问,即用户可以通过快进或者后退操作来观看前面或者后面的内容。从理论上讲,实时流媒体一经播放就不会停顿,但事实上仍有可能发生周期性的暂停现象,尤其是在网络状况恶化时更是如此。与顺序流传输不同的是,实时流传输需要用到特定的流媒体服务器,而且还需要特定网络协议的支持。

二、流媒体协议

     实时传输协议(Real-time Transport Protocol,PRT)是在Internet上处理多媒体数据流的一种网络协议,利用它能够在一对一(unicast,单播)或者一对多(multicast,多播)的网络环境中实现传流媒体数据的实时传输。RTP通常使用UDP来进行多媒体数据的传输,但如果需要的话可以使用TCP或者ATM等其它协议,整个RTP协议由两个密切相关的部分组成:RTP数据协议和RTP控制协议。实时流协议(Real Time Streaming Protocol,RTSP)最早由Real Networks和Netscape公司共同提出,它位于RTP和RTCP之上,其目的是希望通过IP网络有效地传输多媒体数据。

2.1 RTP数据协议

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.2 RTCP控制协议

     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.3 RTSP实时流协议

作为一个应用层协议,RTSP提供了一个可供扩展的框架,它的意义在于使得实时流媒体数据的受控和点播变得可能。总的说来,RTSP是一个流媒体表示协议,主要用来控制具有实时特性的数据发送,但它本身并不传输数据,而是必须依赖于下层传输协议所提供的某些服务。RTSP可以对流媒体提供诸如播放、暂停、快进等操作,它负责定义具体的控制消息、操作方法、状态码等,此外还描述了与RTP间的交互操作。

RTSP在制定时较多地参考了HTTP/1.1协议,甚至许多描述与HTTP/1.1完全相同。RTSP之所以特意使用与HTTP/1.1类似的语法和操作,在很大程度上是为了兼容现有的Web基础结构,正因如此,HTTP/1.1的扩展机制大都可以直接引入到RTSP中。

由RTSP控制的媒体流集合可以用表示描述(Presentation Description)来定义,所谓表示是指流媒体服务器提供给客户机的一个或者多个媒体流的集合,而表示描述则包含了一个表示中各个媒体流的相关信息,如数据编码/解码算法、网络地址、媒体流的内容等。

虽然RTSP服务器同样也使用标识符来区别每一流连接会话(Session),但RTSP连接并没有被绑定到传输层连接(如TCP等),也就是说在整个RTSP连接期间,RTSP用户可打开或者关闭多个对RTSP服务器的可靠传输连接以发出RTSP 请求。此外,RTSP连接也可以基于面向无连接的传输协议(如UDP等)。

RTSP协议目前支持以下操作:

检索媒体  允许用户通过HTTP或者其它方法向媒体服务器提交一个表示描述。如表示是组播的,则表示描述就包含用于该媒体流的组播地址和端口号;如果表示是单播的,为了安全在表示描述中应该只提供目的地址。

邀请加入  媒体服务器可以被邀请参加正在进行的会议,或者在表示中回放媒体,或者在表示中录制全部媒体或其子集,非常适合于分布式教学。

添加媒体  通知用户新加入的可利用媒体流,这对现场讲座来讲显得尤其有用。与HTTP/1.1类似,RTSP请求也可以交由代理、通道或者缓存来进行处理。


转自:http://wenku.baidu.com/view/fea8518683d049649b6658b9.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
由于ID3决策树是一种基于信息熵的算法,因此我们需要计算每个属性的信息熵和整个数据集的信息熵。具体步骤如下: 1. 计算整个数据集的信息熵 首先,我们需要计算整个数据集的信息熵。假设有m个类别,每个类别的概率为$p_i$,则整个数据集的信息熵为: $H=-\sum_{i=1}^mp_i\log_2p_i$ 2. 计算每个属性的信息熵 接下来,我们需要计算每个属性的信息熵。假设有n个属性,第i个属性有k个取值,第i个属性的第j个取值有m个样本,其中有$p_{ij}$个样本属于第j个类别,则第i个属性的信息熵为: $H_i=-\sum_{j=1}^k\frac{m_j}{m}\sum_{l=1}^mp_{ijl}\log_2p_{ijl}$ 3. 计算信息增益 在计算每个属性的信息熵后,我们可以通过计算信息增益来确定选择哪个属性作为当前节点的分裂属性。信息增益的计算公式为: $Gain(S,A)=H(S)-\sum_{v\in Val(A)}\frac{|S_v|}{|S|}H(S_v)$ 其中,$S$表示当前节点的样本集合,$A$表示当前节点可以选择的属性集合,$Val(A)$表示属性$A$的取值集合,$S_v$表示属性$A$等于$v$的样本集合。 4. 递归构建决策树 接下来,我们可以按照信息增益的大小选择当前节点的分裂属性,并根据分裂属性的取值将当前节点的样本集合分裂成多个子节点。我们可以递归地对每个子节点进行上述操作,直到所有样本都属于同一个类别或者没有可以分裂的属性为止。 5. 预测新样本的类别 当构建好决策树后,我们可以使用它来预测新样本的类别。具体步骤如下: (1)从根节点开始,根据当前节点的分裂属性,将新样本分裂到相应的子节点。 (2)如果当前节点是叶节点,则返回该节点的类别作为预测结果。 (3)否则,继续递归地对子节点进行上述操作,直到找到叶节点为止。 以上就是ID3决策树模型的matlab实现步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值