15年做那些网站致富wordpress自动alt

news/2025/9/24 5:37:04/文章来源:
15年做那些网站致富,wordpress自动alt,汽车制作公司排名,centos 6.8 wordpressavi文件格式详解 AVI是音频视频交错(Audio Video Interleaved)的英文缩写#xff0c;它是Microsoft公司开发的一种符合RIFF文件规范的数字音频与视频文件格式#xff0c;原先用于Microsoft Video for Windows (简称VFW)环境#xff0c;现在已被Windows 95/98、OS/2等多数操…avi文件格式详解 AVI是音频视频交错(Audio Video Interleaved)的英文缩写它是Microsoft公司开发的一种符合RIFF文件规范的数字音频与视频文件格式原先用于Microsoft Video for Windows (简称VFW)环境现在已被Windows 95/98、OS/2等多数操作系统直接支持。AVI格式允许视频和音频交错在一起同步播放支持256色和RLE压缩但AVI文件并未限定压缩标准因此AVI文件格式只是作为控制界面上的标准不具有兼容性用不同压缩算法生成的AVI文件必须使用相应的解压缩算法才能播放出来。常用的AVI播放驱动程序主要是Microsoft Video for Windows或Windows 95/98中的Video 1以及Intel公司的Indeo Video。   在介绍AVI文件前我们要先来看看RIFF文件结构。AVI文件采用的是RIFF文件结构方式RIFFResource Interchange File Format资源互换文件格式是微软公司定义的一种用于管理windows环境中多媒体数据的文件格式波形音频waveMIDI和数字视频AVI都采用这种格式存储。构造RIFF文件的基本单元叫做数据块Chunk每个数据块包含3个部分   1、4字节的数据块标记或者叫做数据块的ID   2、数据块的大小   3、数据   整个RIFF文件可以看成一个数据块其数据块ID为RIFF称为RIFF块。一个RIFF文件中只允许存在一个RIFF块。RIFF块中包含一系列的子块其中有一种字块的ID为LIST称为LISTLIST块中可以再包含一系列的子块但除了LIST块外的其他所有的子块都不能再包含子块。   RIFF和LIST块分别比普通的数据块多一个被称为形式类型Form Type和列表类型List Type的数据域其组成如下   1、4字节的数据块标记Chunk ID   2、数据块的大小   3、4字节的形式类型或者列表类型   4、数据   下面我们看看AVI文件的结构。AVI文件是目前使用的最复杂的RIFF文件它能同时存储同步表现的音频视频数据。AVI的RIFF块的形式类型是AVI它包含3个子块如下所述   1、信息块一个ID为hdrl的LIST块定义AVI文件的数据格式。   2、数据块一个ID为 movi的LIST块包含AVI的音视频序列数据。   3、索引块ID为 idxl的子块定义 moviLIST块的索引数据是可选块。   AVI文件的结构如下图所示下面将具体介绍AVI文件的各子块构造。   1、信息块信息块包含两个子块即一个ID为 avih 的子块和一个ID 为 strl 的LIST块。 avih子块的内容可由如下的结构定义 typedef struct {  DWORD dwMicroSecPerFrame ; //显示每桢所需的时间ns定义avi的显示速率  DWORD dwMaxBytesPerSec; // 最大的数据传输率  DWORD dwPaddingGranularity; //记录块的长度需为此值的倍数通常是2048  DWORD dwFlages; //AVI文件的特殊属性如是否包含索引块音视频数据是否交叉存储  DWORD dwTotalFrame; //文件中的总桢数  DWORD dwInitialFrames; //说明在开始播放前需要多少桢  DWORD dwStreams; //文件中包含的数据流种类  DWORD dwSuggestedBufferSize; //建议使用的缓冲区的大小  //通常为存储一桢图像以及同步声音所需要的数据之和  DWORD dwWidth; //图像宽  DWORD dwHeight; //图像高  DWORD dwReserved[4]; //保留值 }MainAVIHeader; strl LIST块用于记录AVI数据流每一种数据流都在该LIST块中占有3个子块他们的ID分别是strh,strf, strd strh子块由如下结构定义。 typedef struct {  FOURCC fccType; //4字节表示数据流的种类 vids 表示视频数据流  //auds 音频数据流  FOURCC fccHandler;//4字节 表示数据流解压缩的驱动程序代号  DWORD dwFlags; //数据流属性  WORD wPriority; //此数据流的播放优先级  WORD wLanguage; //音频的语言代号  DWORD dwInitalFrames;//说明在开始播放前需要多少桢  DWORD dwScale; //数据量视频每桢的大小或者音频的采样大小  DWORD dwRate; //dwScale /dwRate 每秒的采样数  DWORD dwStart; //数据流开始播放的位置以dwScale为单位  DWORD dwLength; //数据流的数据量以dwScale为单位  DWORD dwSuggestedBufferSize; //建议缓冲区的大小  DWORD dwQuality; //解压缩质量参数值越大质量越好  DWORD dwSampleSize; //音频的采样大小  RECT rcFrame; //视频图像所占的矩形 }AVIStreamHeader; strf子块紧跟在strh子块之后其结构视strh子块的类型而定如下所述如果 strh子块是视频数据流则 strf子块的内容是一个与windows设备无关位图的BIMAPINFO结构如下 typedef struct tagBITMAPINFO {  BITMAPINFOHEADER bmiHeader;  RGBQUAD bmiColors[1]; //颜色表 }BITMAPINFO; typedef struct tagBITMAPINFOHEADER {  DWORD biSize;  LONG biWidth;  LONG biHeight;  WORD biPlanes;  WORD biBitCount;  DWORD biCompression;  DWORD biSizeImage;  LONG biXPelsPerMeter;  LONG biYPelsPerMeter;  DWORD biClrUsed;  DWORD biClrImportant; }BITMAPINFOHEADER; 如果 strh子块是音频数据流则strf子块的内容是一个WAVEFORMAT结构如下 typedef struct {  WORD wFormatTag;  WORD nChannels; //声道数  DWORD nSamplesPerSec; //采样率  DWORD nAvgBytesPerSec; //WAVE声音中每秒的数据量  WORD nBlockAlign; //数据块的对齐标志  WORD biSize; //此结构的大小 }WAVEFORMAT strd子块紧跟在strf子块后存储供压缩驱动程序使用的参数不一定存在也没有固定的结构。   strl LIST块定义的AVI数据流依次将 hdrl LIST 块中的数据流头结构与movi LIST块中的数据联系在一起第一个数据流头结构用于数据流0第二个用于数据流1依次类推。   数据块中存储视频和音频数据流数据可直接存于 movi LIST块中。数据块中音视频数据按不同的字块存放其结构如下所述   音频字块     ##wb     Wave 数据流   视频子块中存储DIB数据又分为压缩或者未压缩DIB     ##db     RGB数据流     ##dc   压缩的图像数据流   看到了吧avi文件的图像数据可以是压缩的和非压缩格式的。对于压缩格式来说也可采用不同的编码也许你曾经遇到有些avi没法识别就是因为编码方式不一样如果没有相应的解码你就没法识别视频数据。AVI的编码方式有很多种比较常见的有 mpeg2mpeg4divx等。 索引块索引快包含数据块在文件中的位置索引能提高avi文件的读写速度其中存放着一组AVIINDEXENTRY结构数据。如下这个块并不是必需的也许不存在。 typedef struct {DWORD ckid; //记录数据块中子块的标记DWORD dwFlags; //表示chid所指子块的属性DWORD dwChunkOffset; //子块的相对位置DWORD dwChunkLength; //子块长度}; 视频捕捉全教程 前 言           视频捕获是指由专用的视频采集卡捕获声频和视频信息然后将其进行数据化处理再经过软件的压缩进行处理这时就可对这些数据进行保存、回放、传输等各种操作。          Windows专门提供了Video for Windows来对视频处理进行支持提供的接口可以被大多数的视频采集卡支持并有多种视频压缩驱动供选择当然视频压缩可以自己开发采集卡支持摄像头等多种输入。 一. 视频捕获快速入门           视频捕捉将一个视频流和音频流数字化, 然后存储在硬盘或其他存储介质上.           一个AVICap视窗口句柄描述了声频与视频流的细节, 这样就使你的应用程序从AVI文件格式, 声频视频缓冲管理, 低层声频视频驱动访问等等解脱出来, AVICap为应用程序提供了一个灵活的介面, 你可以仅仅使用如下几行代码就可以将视频捕捉加入你的程序: hWndC capCreateCaptureWindow ( My Own Capture Window, WS_CHILD | WS_VISIBLE , 0, 0, 160, 120, hwndParent, nID); SendMessage (hWndC, WM_CAP_DRIVER_CONNECT, 0 /* wIndex */, 0L); SendMessage (hWndC, WM_CAP_SEQUENCE, 0, 0L);            一个宏其实也是使用SendMessage, 只不过提供给程序一个更易读的代码而已, 下面的这些示例就是使用宏的方法将视频捕捉加入程序: hWndC capCreateCaptureWindow ( My Own Capture Window, WS_CHILD | WS_VISIBLE , 0, 0, 160, 120, hwndParent, nID); capDriverConnect (hWndC, 0); capCaptureSequence (hWndC);           当你创建了一个AVICap类的捕捉窗口并将它连接到一个视频驱动时, 此捕捉窗口即可以开始捕捉数据, 你的程序可以简单的发送WM_CAP_SEQUENCE消息(或者使用capCaptureSequence宏)来开始捕捉.           如果是缺省的设置, WM_CAP_SEQUENCE会开始捕捉视频音频流到CAPTURE.AVI文件中, 直到下面的某一事件发生为止: 用户按下了ESC键或者一个鼠标键 你的应用程序终止或异常中断捕捉操作 磁盘已满               在一个应用程序里, 你可以发送WM_CAP_STOP消息来终止捕捉数据(或者使用capCaptureStop宏), 你也可以发送WM_CAP_ABORT消息(或者使用capCaptureAbort宏)来终止. 二.基本的捕获设置           基本的捕获设置包括设置捕获速度每秒捕获多少帧是否同时捕获声频捕获缓冲允许最大丢失多少帧是否使用内存以及用键盘的哪个键或鼠标 的哪个键来终止捕获等等。这些基本的设置都可以使用结构来描述你可以使用capCaptureGetSetup宏来得到当前 的设置然后改变此结构的成员变量再使用capCaptureSetSetup宏设置新的设置。 例如 设置捕获速度            捕捉速度是指捕捉任务每秒钟捕获的帧数, 你可以发送WM_CAP_GET_SEQUENCE_SETUP消息(或者使用capCaptureGetSetup宏)来得到当前的捕捉速度, 当前的捕捉速度保存在CAPTUREPARAMS结构的dwRequestMicroSecPerFrame成员变量中, 你可以通过设置此变量来改变当前设置, 单位是每毫秒连续的帧数, 你可以发送WM_CAP_SET_SEQUENCE_SETUP消息(或者使用capCaptureSetSetup宏), dwRequestMicroSecPerFrame的值是66667, 相当于每秒15帧. 设置终止捕获            你可以允许用户按下某键或某组合键或者鼠标的左右键来终止一个捕获任务, 如果是实时的捕获, 则捕获的文件将会被丢弃; 如果是单步捕获, 在终止之前所捕获的内容将会被保存.           你可以通过发送WM_CAP_GETQUENCE_SETUP消息(或者使用capCaptureGetSetup宏)来得到当前的设置, 当前的按键设置保存在CAPTUREPARAMS的vKeyAbort成员中, 当前的鼠标设置保存在fAbortLeftMouse和fAbortRightMouse成员中. 你可以设置新的按键或按键组合, 或者鼠标左右键, 当你修改的CAPTUREPARAMS后,应该发送WM_CAP_SET_SEQUENCE_SETUP消息来进行更新(或者使用 capCaptureSetSetup宏). 缺省的按键是VK_ESCAPE. 你必须在指定按键之前使用RegisterHotKey函数, 鼠标缺省的值是fAbortLeftMouse和fAbortRightMouse都为TRUE. 捕获的时间限制            CAPTUREPARAMS结构中的fLimitEnabled指示是否有时间限度, wTimeLimit指示最大的持续时间, 单位为秒.           得到fLimitEnabled和wTimeLimit的值可以发送WM_CAP_GET_SEQUENCE_SETUP消息(或使用 capCatureGetSetup宏), 当设置了这些成员变量后, 应该发送消息WM_CAP_SET_SEQUENCE_SETUP消息(或capCaptureSetSetup宏)来更新CAPTUREPARAMS结 构. 三.关于捕获窗口         在捕获之前必须创建一个捕获窗口capture window在发送消息或使用宏的过程中都需要使用此窗口。 .创建一个AVICap捕获窗口         你可以使用capCreateCaptureWindow函数来创建一个AVICap捕获窗口, 此函数将会返回一个句柄, 此句柄以后在发送消息时要用.         你可以在一个程序里创建一个或多个捕获窗口, 然后给每一个窗口连接不同的捕获设置. 将一个捕获窗口连接至捕获设备            你可以动态的在一个捕获窗口与一个捕获设备之前连接或断接, 你可以发送WM_CAP_DRIVER_CONNECT消息来使一个捕获窗口与一个捕获设备连接或关联. 当连接上以后, 你就可以通过捕获窗口向捕获设备发送各种消息.         如果你的系统里装有多个捕获设备, 你可以在发送WM_CAP_DRIVER_CONNECT消息时用wParam参数指定使用哪一个, 此参数是登记在SYSTEM.INI文件的[drivers]一节里的列表中的某一项, 0为第一个.           你可以使用capGetDriverDescription函数来得到已安装的捕获设备的名称及版本, 这样你的程序就可以列举所有已安装的捕获设备和驱动, 这样用户就可以选择其中的一个来与你的捕获窗口连接.          你可以发送WM_CAP_DRIVER_GET_NAME消息(或capDriverGetName宏)来得到连接到捕获窗口的捕获设备的名称, 得到版本发送WM_CAP_DRIVER_GET_VERSION消息(或capDriverGetVersion宏)          你可以发送WM_CAP_DRIVER_DISCONNECT消息(或capDriverDisconnect宏)来断接. 父窗口与子窗口的交互            一些象WM_PALETTECHANGED和WM_QUERYNEWPALETTE的系统级消息只能发送到顶级窗口或OVERLAPPED窗口, 如果一个捕获窗口是子窗口,就必须通过父窗口转送.          同样的, 如果父窗口的尺寸改变了, 它就需要通知捕获窗口, 相反地, 如果捕获窗口的尺寸改变了, 捕获窗口就需要发送消息给父窗口, 一个简单的方法就是始终保持捕获窗口的尺寸与视频流的尺寸一致, 并随时将尺寸的改变通知父窗口. 捕获窗口的状态           你可以发送WM_CAP_GET_STATUS消息(或capGetStatus宏)来得到当前捕获窗口的状态, 得到的是一个CAPSTATUS结构的拷贝, 它包含图片的尺寸, 卷轴的当前位置, overlay和preview是否已设置.         因为CAPSTATUS信息是动态的, 你的程序应该只要捕获的视频流的尺寸或格式可能发生了改变就应该进行刷新(例如: 显示了捕获设备的视频格式以后).         改变捕获窗口的尺寸并不影响实际的捕获的视频流的尺寸, 视频捕获设备的格式对话框捕获频流的尺寸. 四.视频捕获驱动和音频驱动 视频捕获驱动的性能:           你可以通过发送WM_CAP_DRIVER_GET_CAPS消息(或者capDriverGetCaps宏)来得到当前连接的视频驱动的硬件性能. 得到的信息保存在CAPDRIVERCAPS结构中. 视频对话框:           每一个视频驱动能够提供四个对话框来控制视频捕获和数字化处理, 定义压缩品质等, 这些对话框都定义在视频捕获驱动中.           Video Source对话框用于控制选择视频来源, 此对话框列举了此视频捕获卡连接的所有视频源(典型的例如:SVHS和合成输入), 并提供了改变色调, 对比度, 饱和度. 如果视频驱动支持此对话框, 你就可以显示并更新它, 使用WM_CAP_DLG_VIDEOSOURCE消息(或capDlgVideoSource宏).            Video Format对话框定义视频帧的尺寸以及精度, 视频捕获卡的压缩设置. 如果卡支持的话, 可以发送消息WM_CAP_DLG_VIDEOFORMAT消息或(capDlgVideoFormat宏).            Video Display对话框控制在视频捕获期间在显示器上的显示, 此控制不会影响视频数字数据, 但是他们可能会影响数字信号的表现形式, 例如: 如果捕获设备支持overlay, 可能允许改变色调和饱和度, 关键色彩 或者overlay队列. 如果卡支持, 你可以发送WM_CAP_DLG_VIDEODISPLAY消息(或者使用capDlgVideoDisplay宏).            Video Compression对话框控制压缩品质, 如果卡支持, 发送消息WM_CAP_DLG_VIDEOCOMPRESSION(或capDlgVideoCompression宏). Preview 和 Overlay模式:                  一个视频捕获驱动对进入的视频流有两种工作模式: Preview模式和overlay模式, 如果一个捕获驱动能够执行两种方法, 用户可以在其中选择一种.                Preview模式把从捕获硬件传来的数据送入系统内存并使用图形设备介面(GDI)将数字化帧显示在捕获窗口内. 应用程序可以在父窗口失去焦点时减缓显示速度, 当重新又得到焦点后加快显示速度, 此种模式要占用大量CPU时间. 有三种消息控制Preview操作: WM_CAP_SET_PREIVEW消息(capPreview宏)允许或禁止preview模式 WM_CAP_SET_PREVIEWRATE(capPreviewRate宏)当帧在preview模式显示时设置速度. WM_CAP_SET_SCALE(capPreviewScale宏)允许或禁止preview视频的缩放比例.           当preview和scaling同时使用, 捕获的视频帧将会根据捕获窗口的尺寸自动缩放, 允许preview模式会自动关闭overlay模式.                       overlay模式是一个硬件函数它将数据送入捕获缓冲区中因而不占用CPU资源. 你可以发送消息WM_CAP_SET_OVERLAY(或capOverlay宏)给捕获窗口来启用或终止overlay模式, 允许overlay模式会自动禁止preview模式.                你同时也可以在preview模式或overlay模式里发送WM_CAP_SET_SCROLL消息(或capSetScrollPos宏)来设置视频帧的客户区卷轴位置. 视频格式             你可以通过发送WM_CAP_GET_VIDEOFORMAT消息(或capGetVideoFormat和capGetVideoFormatSize 宏)来得到视频格式的结构或结构的尺寸. 你可以通过发送CAP_SET_VIDEOFORMAT消息(或capSetVideoFormat宏)来设置视频格式. 视频捕获设置            CAPTUREPARMS结构包含了对视频捕获流的控制参数, 你可以完成以下这些任务: 指定帧数 指定分配多少视频缓冲 允许或禁止声频捕获 指定捕获的时间间隔 指定在捕获的过程中是否使用MCI设置(VCR或者videodisc) 指定终止流的键盘或鼠标 specify the type of video averaging applied during capture. 得到:WM_CAP_GET_SEQUENCE_SETUP消息(或capCaptureGetSetup宏) 设置:WM_CAP_SET_SEQUENCE_SETUP消息(或capCaptureSetSetup宏) 声频格式                你可以通过发送WMCAPGETAUDIOFORMAT消息或capGetAudioFormat宏和 capGetAudioFormatSize宏来得到当前捕获音频数据的格式或尺寸格式。缺省的声频格式是单声道、8位、11kHz PCM。 当你使用WMCAPGETAUDIOFORMAT时总是使用WAVEFORMATEX结构。              设置发送消息WMCAPSETAUDIOFORMAT消息或capSetAudioFormat宏可以传送WAVEFORMATWAVEFORMATEXPCMWAVEFORMAT结构指针。 五使用视频捕获 1.创建捕获窗口(Creating a Capture Window) hWndC capCreateCaptureWindow ( (LPSTR) My Capture Window, // window name if pop-up WS_CHILD | WS_VISIBLE, // window style 0, 0, 160, 120, // window position and dimensions (HWND) hwndParent, (int) nID /* child ID */); 2.连接到捕获驱动(Connecting to a Capture Driver)            下面的例子是将MSVIDEO驱动连接到句柄为hWndC的捕获窗口, 然后调用capDriverDisconnect宏来断接. fOK SendMessage (hWndC, WM_CAP_DRIVER_CONNECT, 0, 0L); // // Or, use the macro to connect to the MSVIDEO driver: // fOK capDriverConnect(hWndC, 0); // // Place code to set up and capture video here. // capDriverDisconnect (hWndC); 3.列举所有已安装的捕获驱动(Enumerating Installed Capture Drivers)            下面的例子使用capGetDriverDescription函数得到已安装的捕获驱动的名称及版本: char szDeviceName[80]; char szDeviceVersion[80]; for (wIndex 0; wIndex 10; wIndex) { if (capGetDriverDescription (wIndex, szDeviceName, sizeof (szDeviceName), szDeviceVersion, sizeof (szDeviceVersion)) { // Append name to list of installed capture drivers // and then let the user select a driver to use. } } 4.得到捕获驱动的性能(Obtaining the Capabilities of a Capture Driver)               发送WM_CAP_DRIVER_GET_CAPS消息可以得到捕获驱动的性能,并保存入一个CAPDRIVERCAPS结构.每当程序连接一个新的捕获 驱动到一个捕获窗口时, 就应该更新CAPDRIVERCAPS结构. 下面的程序举例说明了如何使用capDriverGetCaps宏来得到捕获驱动的性能: CAPDRIVERCAPS CapDrvCaps; SendMessage (hWndC, WM_CAP_DRIVER_GET_CAPS, sizeof (CAPDRIVERCAPS), (LONG) (LPVOID) CapDrvCaps); // Or, use the macro to retrieve the driver capabilities. // capDriverGetCaps(hWndC, CapDrvCaps, sizeof (CAPDRIVERCAPS)); 5.得到捕获窗口的状态(Obtaining the Status of a Capture Window)                  下面的例子使用SetWindowPos函数使捕获窗口与进来的视频流尺寸保持一致, 视频流的基本信息是使用capGetStatus宏得到的, 保存在CAPSTATUS结构中. CAPSTATUS CapStatus; capGetStatus(hWndC, CapStatus, sizeof (CAPSTATUS)); SetWindowPos(hWndC, NULL, 0, 0, CapStatus.uiImageWidth, CapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE); 6.显示对话框设置视频特征(Displaying Dialog Boxes to Set Video Characteristics)               每个视频捕获卡一般能提供三个不同的对话框用于控制视频捕获及数字化处理. 下面的例子说明如何显示这些对话框, 在显示这些对话框之前,使用了capDriverGetCaps宏来检查CAPDRIVERCAPS结构, 以检测该卡是否有显示这些对话框: CAPDRIVERCAPS CapDrvCaps; capDriverGetCaps(hWndC, CapDrvCaps, sizeof (CAPDRIVERCAPS)); // Video source dialog box. if (CapDriverCaps.fHasDlgVideoSource) capDlgVideoSource(hWndC); // Video format dialog box. if (CapDriverCaps.fHasDlgVideoFormat) { capDlgVideoFormat(hWndC); // Are there new image dimensions? capGetStatus(hWndC, CapStatus, sizeof (CAPSTATUS)); // If so, notify the parent of a size change. } // Video display dialog box. if (CapDriverCaps.fHasDlgVideoDisplay) capDlgVideoDisplay(hWndC); 7.得到和设置视频格式(Obtaining and Setting the Video Format)                    BITMAPINFO结构的长度既适应于标准的也适应于压缩的数据格式, 所有程序必须总是询问此结构的尺寸以便在得到当前的视频格式之前分配内存. 下面的例子就是使用capGetVideoFormatSize宏来得到缓冲区尺寸并调用capGetVideoFormat宏来得到当前的视频格式. LPBITMAPINFO lpbi; DWORD dwSize; dwSize capGetVideoFormatSize(hWndC); lpbi GlobalAllocPtr (GHND, dwSize); capGetVideoFormat(hWndC, lpbi, dwSize); // Access the video format and then free the allocated memory.               程序可以使用capSetVideoFormat宏(或WM_CAP_SET_VIDEOFORMAT消息)发送一个BITMAPINFO头结构给捕获窗口, 因为视频格式是设备细节, 你的程序应该检查返回值以便确定此格式是否已被接受. 8. 预览视频(Previewing Video)              下面的例子使用capPreviewRate宏来设置每66毫秒显示一帧, 并使用capPreview宏将它放置在捕获窗口里. capPreviewRate(hWndC, 66); // rate, in milliseconds capPreview(hWndC, TRUE); // starts preview // Preview capPreview(hWnd, FALSE); // disables preview 9.将视频设置为overlay模式(Enabling Video Overlay)             下面的例子: capDriverGetCaps宏确定此捕获卡是否有overlay功能, 如果有就使用宏来设置它 CAPDRIVERCAPS CapDrvCaps; capDriverGetCaps(hWndC, CapDrvCaps, sizeof (CAPDRIVERCAPS)); if (CapDrvCaps.fHasOverlay) capOverlay(hWndC, TRUE); 10.命名捕获文件(Naming the Capture File)              下面的例子: 使用capFileSetCaptureFile宏来指定预备文件名为:MYCAP.AVI, capFileAlloc宏预先指定它的大小为5M. char szCaptureFile[] MYCAP.AVI; capFileSetCaptureFile( hWndC, szCaptureFile); capFileAlloc( hWndC, (1024L * 1024L * 5)); 11.格式化声频捕获(Formatting Audio Capture)              下面的例子使用capSetAudioFormat来设置声频格式为:11kHz, PCM 8位, 立体声 WAVEFORMATEX wfex; wfex.wFormatTag WAVE_FORMAT_PCM; wfex.nChannels 2; // Use stereo wfex.nSamplesPerSec 11025; wfex.nAvgBytesPerSec 22050; wfex.nBlockAlign 2; wfex.wBitsPerSample 8; wfex.cbSize 0; capSetAudioFormat(hWndC, wfex, sizeof(WAVEFORMATEX)); 12.改变视频捕获设置(Changing a Video Capture Setting)                下面的例子使用capCaptureGetSetup和capCaptureSetSetup宏得将捕获帧数从缺省的15帧改成每秒10帧. CAPTUREPARMS CaptureParms; float FramesPerSec 10.0; capCaptureGetSetup(hWndC, CaptureParms, sizeof(CAPTUREPARMS)); CaptureParms.dwRequestMicroSecPerFrame (DWORD) (1.0e6 /FramesPerSec); capCaptureSetSetup(hWndC, CaptureParms, sizeof (CAPTUREPARMS)); 13.捕获数据(Capturing Data)                 下面的例子使用capCaptureSequence宏来开始捕获视频并使用capFileSaveAs宏来将捕获的数据拷贝至NEWFILE.AVI文件中. char szNewName[] NEWFILE.AVI; // Set up the capture operation. capCaptureSequence(hWndC); // Capture. capFileSaveAs(hWndC, szNewName); 14.增加一个信息块(Adding an Information Chunk)                如果你需要在你的程序捕获的声频和视频数据中加入你的其他信息, 你可以创建一个信息块并将它们插入捕获文件中, 信息块可以包含一些典型的信息, 例如:版权信息,视频来源, 外部定位信息等. 下面的例子使用capFileSetInfoChunk宏来插入一个信息块, 里面包含了一个SMPTE的时间代码. // This example assumes the application controls // the video source for preroll and postroll. CAPINFOCHUNK cic; // . // . // . cic.fccInfoID infotypeSMPTE_TIME; cic.lpData 00:20:30:12; cic.cbData strlen (cic.lpData) 1; capFileSetInfoChunk (hwndC, cic); 15.在程序中加入一个回调函数(Adding Callback Functions to an Application)                一个程序可以为捕获窗口登记一个回调函数以便在以下的这些情况下通知程序. 状态改变 错误发生 视频框架和声频缓冲区变得可用 程序应用在捕获视频流的过程中接收            下面的例子创建一个捕获窗口并登记状态,错误,视频流和框架回调函数在消息处理对列中, 也包括了一个终止回调函数的说明. case WM_CREATE: { char achDeviceName[80] char achDeviceVersion[100] char achBuffer[100] WORD wDriverCount 0 WORD wIndex WORD wError HMENU hMenu // Create a capture window using the capCreateCaptureWindow macro. ghWndCap capCreateCaptureWindow((LPSTR)Capture Window, WS_CHILD | WS_VISIBLE, 0, 0, 160, 120, (HWND) hWnd, (int) 0); // Register the error callback function using the // capSetCallbackOnError macro. capSetCallbackOnError(ghWndCap, fpErrorCallback); // Register the status callback function using the // capSetCallbackOnStatus macro. capSetCallbackOnStatus(ghWndCap, fpStatusCallback); // Register the video-stream callback function using the // capSetCallbackOnVideoStream macro. capSetCallbackOnVideoStream(ghWndCap, fpVideoCallback); // Register the frame callback function using the // capSetCallbackOnFrame macro. capSetCallbackOnFrame(ghWndCap, fpFrameCallback); // Connect to a capture driver break; } case WM_CLOSE: { // Use the capSetCallbackOnFrame macro to // disable the frame callback. Similar calls exist for the other // callback functions. capSetCallbackOnFrame(hWndC, NULL); break; } 16.创建一个状态回调函数(Creating a Status Callback Function)             下面的例子是创建一个简单的状态回调函数,登记此回调函数使用capSetCallbackOnStatus宏. // StatusCallbackProc: status callback function // hWnd: capture window handle // nID: status code for the current status // lpStatusText: status text string for the current status // LRESULT PASCAL StatusCallbackProc(HWND hWnd, int nID, LPSTR lpStatusText) { if (!ghWndMain) return FALSE; if (nID 0) { // Clear old status messages. SetWindowText(ghWndMain, (LPSTR) gachAppName); return (LRESULT) TRUE; } // Show the status ID and status text... wsprintf(gachBuffer, Status# %d: %s, nID, lpStatusText); SetWindowText(ghWndMain, (LPSTR)gachBuffer); return (LRESULT) TRUE; } 17.创建一个错误回调函数( Creating an Error Callback Function)              下面的例子是创建一个简单的错误回调函数,登记此回调函数使用capsetCallbackOnError宏: // ErrorCallbackProc: error callback function // hWnd: capture window handle // nErrID: error code for the encountered error // lpErrorText: error text string for the encountered error // LRESULT PASCAL ErrorCallbackProc(HWND hWnd, int nErrID, LPSTR lpErrorText) { if (!ghWndMain) return FALSE; if (nErrID 0) // Starting a new major function. return TRUE; // Clear out old errors. // Show the error identifier and text. wsprintf(gachBuffer, Error# %d, nErrID); MessageBox(hWnd, lpErrorText, gachBuffer, MB_OK | MB_ICONEXCLAMATION); return (LRESULT) TRUE; } 18.创建一个框架回调函数(Creating a Frame Callback Function)               登记此回调函数使用capSetCallbackOnFrame宏: // FrameCallbackProc: frame callback function // hWnd: capture window handle // lpVHdr: pointer to struct containing captured // frame information // LRESULT PASCAL FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr) { if (!ghWndMain) return FALSE; wsprintf(gachBuffer, Preview frame# %ld , gdwFrameNum); SetWindowText(ghWndMain, (LPSTR)gachBuffer); return (LRESULT) TRUE }   六将四个标准对话框改成函数调用形式               系统提供了四个标准的对话框AudioFormat, VideoFormat, VideoSource, Video Compression但有时程序希望通过函数控制它们而不是使用系统提供的那个单一的对话框此时就应该使用函数调用的方法 AudioFormat对话框             可以通过使用capSetAudioFormat来实现此时要使用WAVEFORMATEX结构。 例如改成格式立体声声道12.05kHz则 WAVEFORMATEX audioFormat; // 确定宽度 acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT,dwSize); dwSize max (dwSize, capGetAudioFormatSize (m_hwCapCapturing)); // 设置参数 audioFormat.wFormatTag WAVE_FORMAT_PCM; audioFormat.nChannels 2; audioFormat.nSamplesPerSec 120500; audioFormat.wBitsPerSample 16; audioFormat.nBlockAlign nBitsPerSample * nChannels / 8; audioFormat.nAvgBytesPerSec audioFormat.nBlockAlign * nSamplesPerSec; // 更新 capSetAudioFormat(ghCapWnd,audioFormat,dwSize); VideoFormat对话框                   可以通过使用capSetVideoFormat来实现此时要使用BITMAPINFOHEADER结构。 例如设置图片大小为位岁大小为 BITMAPINFOHEADER bi; DWORD dwSize,dw; bi.biSize sizeof(BITMAPINFOHEADER); bi.biWidth 320; // 起作用 bi.biHeight 160; // 起作用 bi.biPlanes 1; bi.biBitCount 24; bi.biCompression BI_RGB; bi.biSizeImage 0; bi.biXPelsPerMeter 176; bi.biYPelsPerMeter 144; bi.biClrUsed 0; bi.biClrImportant 0; dwSize bi.biSize ((bi.biBitCount 8 || bi.biClrUsed) ? (bi.biClrUsed * sizeof(PALETTEENTRY)) : (2 ^ bi.biBitCount * sizeof(PALETTEENTRY))); dw capSetVideoFormat(m_hwCapCapturing, bi, dwSize); VideoSource对话框                 没有找到现成的方法但视频捕获卡提供的里面有一个动态链接库可以实现。 Video Compression对话框              可以通过使用ICOpen,ICInfo等函数联合起来得到当前系统里面的视频压缩驱动的列表并可选择其一里面有一个程序示范了此用户程序名叫ICWalk。 WINCE声音驱动模型概述(1) 1.1 WINCE的声音模型 标准的WINDOWS CE下的声音处理模型。 1  声音应用在使用WAVE接口函数的时候被COREDLL模块分了类如果是简单的PCM数据则直接进入ADM模块进行SoftWare Mixer或者连Mixer也省了直接调用Driver放音如果是压缩模式的数据则进入ACM模块进行解压处理后比如GSM/G7XX等等…再次进入ADM模块。 此外如果DRIVER支持硬件的Mixer,则应用层直接Bypass掉ACM和ADM直接进入到驱动进行软件或者硬件进行混音和放音。 2  ACM、Software Mixer都是可选配单元可以通过注册表或者CE内核配置参数添加或者删除。 1.2 WINCE的声音驱动模型 l         分层模型 这是一个标准的分层 MDD-PDD 流式接口模型。 应用层的WAVEAPI都使用WaveAPI Manager(WaveApi.DLL)通过DeviceIOControl映射成为WAV_IOControl函数进行处理。 MDD层是微软的标准实现通过DDSI device driver service-provider interface 和PDD层实现进行连接。MDD通过消息来通知PDD层PDD_WaveProc处理 MDD层接口函数 ·                 WAV_Close ·                 WAV_Deinit ·                 WAV_Init ·                 WAV_IOControl ·                 WAV_Open ·                 WAV_PowerDown ·                 WAV_PowerUp ·                 WAV_Read ·                 WAV_Seek ·                 WAV_Write DDSI接口函数 ·                 PDD_AudioDeinitialize ·                 PDD_AudioGetInterruptType ·                 PDD_AudioInitialize ·                 PDD_AudioMessage ·                 PDD_AudioPowerHandler ·                 PDD_WaveProc 但是分层模型也有一定的限制 ·                 只支持一个设备 ·                 不支持多个流 ·                 对循环支持的不好 ·                 对多个流数据支持的不是很好 l         单片模型 对于单片模型WINCE是希望过渡到这个方案上的。该模型下驱动的移植 还是很简单的。同时该模型也客服了以前只能通过内核的MIXER来支持多个流的局限在驱动层面即支持输入和输出多个流的混音操作。 l         分层模型的基本运转 分层模型支持同时放音和录音操作。MDD层管理着一个中断处理程序和多个 DMA BUFFERS一般放音和录音都使用双DMA 缓冲。 比如放音的时候应用通过WAVEAPI传递过来一些数据MDD层通过 PDD_WaveProc 函数发送 WPDM_START消息给PDDPDD层将数据拷贝到DMA缓冲并启动硬件放音。当DMA完成一个BUFFER的数据传送后会产生一个硬件中断PDD层会设定一个 AUDIO_STATE_OUT_PLAYING标志 。如果MDD发现有更多的数据要传送就会通过WPDM_CONTINUE.消息让PDD层继续负责填充DMA缓冲否则就发送一个WPDM_ENDOFDATA.消息让PDD层停止DMA。 WINCE声音驱动模型概述(2)--WINCE WAVE接口模型详解 WINCE WAVE接口模型详解 1、标准的WAVE流式驱动程序接口 WAVE的驱动程序提供标准的流式接口给高层但真正产生关键作用的是 WAV_IOControl这个函数。该函数的以下两个参数最重要 dwCode 具体的IO控制命令包括 IOCTL_WAV_MESSAGE  处理放音和录音相关的所有操作 IOCTL_DSDVR_MESSAGE DirectSound 动作处理 IOCTL_MIX_MESSAGE.   MIXER的操作 pBufIn 指向了MMDRV_MESSAGE_PARAMS结构该结构如下       Struct {              UINT uDeviceId;        UINT uMsg;        DWORD dwUser;        DWORD dwParam1;        DWORD dwParam2; }MMDRV_MESSAGE_PARAMS;                                           uDeviceId 012 。。。 如果是0代表全局或者缺省的设备                      uMsg 用作(WIDM_*),(WODM_*), (MXDM_*)三种消息                      dwUser实例的具体标识           通过这个函数传递的高层命令最终导致驱动的具体动作放音、录音或者混音。   2、关键的数据结构         WAVE OPEN时候使用的数据结构               WAVEFORMATEX{                      WORD  wFormatTag;                      WORD  wChannels;                      DWORD       nSamplesPerSec;                      DWORD  nAvgBytesPerSec;                      WORD  nBlockAlign;                      WORD  nBitsPerSample;                      WORD  cbSize; } 该数据结构定义了一个Audio Stream所需要的大部分信息当做WAVE OPEN的时候可能应用可能会首先尝试打开这个时候WAVE_IO_CONTROL 就会传递一个WAVE_FORMAT_QUERY 给驱动而驱动只是简单的检查是否真正的支持请求的格式而不真正打开设备。   每次应用添加声音数据的时候会使用如下数据结构 Struct { LPSTR lpData; DWORD dwBufferLength; DWORD dwBytesRecorded; DWORD dwUser; DWORD dwFlags; DWORD dwLoops; Struct wavehdr_tag *lpNext; DWORD Reserved; } 其中dwFlags定义了几个标志               WHDR_BEGINLOOP 指明这个BUFFER是否要求被自动重放 (APP设)               WHDR_DONE          指明这个BUFFER已经处理完毕驱动设               WHDR_ENDLOOP 指明这个BUFFER是否结束重放APP设               WHDR_INQUEUE 指明这个BUFFER入队列驱动设               WHDR_PREPARED指明这个BUFFER的确准备好APP或驱动设 这几个标志是应用和驱动通信的关键也是对队列操作的关键。应用和驱动通过设定这些标志位让数据不断在驱动和应用之间流动从而完成录放的各种操作。当然这个过程还要配合一些WAVE 消息。 WINCE声音驱动模型概述(3)--放音的消息解析 放音的消息解析 WINCE的声音驱动模型在放音的工作中定义了21个消息懒了不再列举了但在具体实现中并不是每个消息都必须实现。 消息很多特别是在具体实现中需要和DMA操作模型配合使用因此理解消息的用途和推敲它们之间的关系就显得格外重要了 通过仔细推敲它们之间的关系我们可以将放音的整个过程规划成如下一些状态并用状态迁移图来理解消息的使用整个过程的操作就非常简单了。 WINCE声音驱动模型概述(4) 混音的处理 如果要WINDOWS CE的声音驱动模型支持混音则要考虑如下问题 1  声音设备是否支持硬件混音 2  声音设备需要工作在同一种采样频率下 3  声音设备要能够同时支持录音和放音操作 而声音的驱动要负责完成声音采集的混音和声音放音的混音。其基本原理如下 1  将声音设备设定在一个频率下比如44.1KHZ,16BIT 2  驱动允许打开多个音频流每个音频流可以允许不同的采样率比如: (A8KHZ,8BIT    B: 44.1KHZ,16BIT) 3  放音的混音在最后的数据准备阶段即放入到DMA前用合成算法将所有的流进行数学运算得出声音设备采样频率下44.1KHZ,16BIT的数据。数据通过DMA发送到CODEC中。 4  录音的混音操作都是从声音设备采样频率下44.1KHZ16BIT下得到采样的基本数据然后通过数学运算分配到不同的频率下的音频流上。 5  要注意的就是合成的时候要注意数据不溢出分开的时候要注意数据速率的匹配和数据宽度的匹配。 中断和DMA驱动模型 声音系统一般都使用DMA作为数据传输的基本手段因此DMA的操作模型对于 声音子系统的处理有着特别关键的作用。DMA的声音操作一般都是用双BUFFER作为 数据缓冲录和放都如此一个BUFFER在被DMA占用的时候另一个BUFFER 就可以被CPU占用从而提高效率。显而易见声音子系统的硬件操作是一个典型的 生产者消费者模式因此对共享资源的控制就特别重要。 DMA的硬件实现不同的CPU略有不同。有的嵌入式芯片做的简单不支持DMA地址的链式连接有的则支持但不影响具体实现。他们相同的点是 l         一般一个DMA有N个子CHANNEL l         每一个CHANNEL都可以互不干扰的独立运转或者停机自有一个状态机 l         DMA使用一个总的DMA 中断通知CPU然后由软件负责查找具体某个CHANNEL。 如果一个系统中很多驱动都需要用到DMA那么就需要一个DMA ENGINE来总 协调DMA的运作否则就会出现驱动争用DMA的问题。如果只有一个驱动使用DMA系统则实现起来的障碍会小不少。 双声道系统中的声音驱动DMA运作都是采用两个通道独立完成录、放的操作并且每个通道都采用双BUFFER的策略来保证DMA和CPU可以近乎同时的工作互不影响。而且一个在高层支持多个流的声音驱动也要注意对DMA这个硬件设备的操作要保持互斥。 在实际驱动的实现过程中这种双通道、双BUFFER的驱动有很多细节要注意要注意处理好几大类关系 1  硬件 DMA和硬件CODEC之间的关系 在整个放音声音数据传输系统中有 APP buffer ßà DMA buffer ßà I2S(AC97) FIFO ßà CODEC APP负责提供数据DMA负责数据传输其实就是要把数据搬运到类似I2S或者AC97间的FIFO中I2S负责成帧传递数据最后由CODEC还原。录音则反之。 一般来讲I2S和CODEC要在DMA启动前准备好而启动DMA和I2S的顺序往往会导致一些数据的丢失这是关注的一点。 2  DMA与APP  buffer之间的关系 还原处理时 APP 往往提供很大的数据包比如16K,而DMA由于设计的需要一般取到4K就比较大了。 启动DMA开始工作的条件是 ---填充完毕两个DMA BUFFER ---I2S准备好 当DMA完成搬运后会产生DMA的中断而在中断处理中要注意一下问题 ---启动第二个BUFFER,继续让DMA工作如果不能启动就要DMA停机了。 ---CPU负责检查是否还有足够的数据给DMA如果有够填充几个DMA BUFFER DMA停机的条件是 ---没有更多的BUFFER可供搬运 ---强制停机 在实践过程中要拿捏好DMA启动和停机的条件因为驱动一般都是多线程运转的一定要注意对DMA操作时的互斥防止出现异常或者死锁。 另外DMA BUFFER的大小直接关系到采样的频率对于一些实时应用很重要。比如VOIP中需要20ms 的打包周期就需要限制DMA BUFFER的大小从而控制中断时间及时为VOIP提供周期打包数据。 3  DMA多CHANNEL之间的关系 如果同时启动录音和放音CHANNEL那么在DMA的中断处理中要注意区分是谁的数据并且要及时启动各自CHANNEL的第二个BUFFER防止采集数据丢失或者放音停顿。 视频与图像RGB/YUV格式详解 计算机彩色显示器显示色彩的原理与彩色电视机一样都是采用RRed、GGreen、BBlue相加混色的原理通过发射出三种不同强度的电子束使屏幕内侧覆盖的红、绿、蓝磷光材料发光而产生色彩。这种色彩的表示方法称为RGB色彩空间表示它也是多媒体计算机技术中用得最多的一种色彩空间表示方法。   根据三基色原理任意一种色光F都可以用不同分量的R、G、B三色相加混合而成。 F r [ R ] g [ G ] b [ B ]   其中r、g、b分别为三基色参与混合的系数。当三基色分量都为0最弱时混合为黑色光而当三基色分量都为k最强时混合为白色光。调整r、g、b三个系数的值可以混合出介于黑色光和白色光之间的各种各样的色光。   那么YUV又从何而来呢在现代彩色电视系统中通常采用三管彩色摄像机或彩色CCD摄像机进行摄像然后把摄得的彩色图像信号经分色、分别放大校正后得到RGB再经过矩阵变换电路得到亮度信号Y和两个色差信号RY即U、BY即V最后发送端将亮度和色差三个信号分别进行编码用同一信道发送出去。这种色彩的表示方法就是所谓的YUV色彩空间表示。   采用YUV色彩空间的重要性是它的亮度信号Y和色度信号U、V是分离的。如果只有Y信号分量而没有U、V分量那么这样表示的图像就是黑白灰度图像。彩色电视采用YUV空间正是为了用亮度信号Y解决彩色电视机与黑白电视机的兼容问题使黑白电视机也能接收彩色电视信号。   YUV与RGB相互转换的公式如下RGB取值范围均为0-255 Y 0.299R 0.587G 0.114B U -0.147R - 0.289G 0.436B V 0.615R - 0.515G - 0.100B R Y 1.14V G Y - 0.39U - 0.58V B Y 2.03U   在DirectShow中常见的RGB格式有RGB1、RGB4、RGB8、RGB565、RGB555、RGB24、RGB32、ARGB32等常见的YUV格式有YUY2、YUYV、YVYU、UYVY、AYUV、Y41P、Y411、Y211、IF09、IYUV、YV12、YVU9、YUV411、YUV420等。作为视频媒体类型的辅助说明类型Subtype它们对应的GUID见表2.3。 表2.3 常见的RGB和YUV格式       GUID                                         格式描述 MEDIASUBTYPE_RGB1    2色每个像素用1位表示需要调色板 MEDIASUBTYPE_RGB4    16色每个像素用4位表示需要调色板 MEDIASUBTYPE_RGB8    256色每个像素用8位表示需要调色板 MEDIASUBTYPE_RGB565    每个像素用16位表示RGB分量分别使用5位、6位、5位 MEDIASUBTYPE_RGB555    每个像素用16位表示RGB分量都使用5位剩下的1位不用 MEDIASUBTYPE_RGB24    每个像素用24位表示RGB分量各使用8位 MEDIASUBTYPE_RGB32    每个像素用32位表示RGB分量各使用8位剩下的8位不用 MEDIASUBTYPE_ARGB32    每个像素用32位表示RGB分量各使用8位剩下的8位用于表示Alpha通道值 MEDIASUBTYPE_YUY2    YUY2格式以4:2:2方式打包 MEDIASUBTYPE_YUYV    YUYV格式实际格式与YUY2相同 MEDIASUBTYPE_YVYU    YVYU格式以4:2:2方式打包 MEDIASUBTYPE_UYVY    UYVY格式以4:2:2方式打包 MEDIASUBTYPE_AYUV    带Alpha通道的4:4:4 YUV格式 MEDIASUBTYPE_Y41P    Y41P格式以4:1:1方式打包 MEDIASUBTYPE_Y411    Y411格式实际格式与Y41P相同 MEDIASUBTYPE_Y211    Y211格式 MEDIASUBTYPE_IF09    IF09格式 MEDIASUBTYPE_IYUV    IYUV格式 MEDIASUBTYPE_YV12    YV12格式 MEDIASUBTYPE_YVU9    YVU9格式 下面分别介绍各种RGB格式。 ¨ RGB1、RGB4、RGB8都是调色板类型的RGB格式在描述这些媒体类型的格式细节时通常会在BITMAPINFOHEADER数据结构后面跟着一个调色板定义一系列颜色。它们的图像数据并不是真正的颜色值而是当前像素颜色值在调色板中的索引。以RGB12色位图为例比如它的调色板中定义的两种颜色值依次为0x000000黑色和0xFFFFFF白色那么图像数据001101010111…每个像素用1位表示表示对应各像素的颜色为黑黑白白黑白黑白黑白白白…。 ¨ RGB565使用16位表示一个像素这16位中的5位用于R6位用于G5位用于B。程序中通常使用一个字WORD一个字等于两个字节来操作一个像素。当读出一个像素后这个字的各个位意义如下      高字节              低字节 R R R R R G G G     G G G B B B B B 可以组合使用屏蔽字和移位操作来得到RGB各分量的值 #define RGB565_MASK_RED    0xF800 #define RGB565_MASK_GREEN  0x07E0 #define RGB565_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位不用。使用一个字读出一个像素后这个字的各个位意义如下      高字节             低字节 X R R R R G G       G G G B B B B B       X表示不用可以忽略 可以组合使用屏蔽字和移位操作来得到RGB各分量的值 #define RGB555_MASK_RED    0x7C00 #define RGB555_MASK_GREEN  0x03E0 #define RGB555_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数据结构来操作一个像素它的定义为 typedef struct 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分量排列顺序如下 Y0 U0 Y1 V0    Y2 U2 Y3 V2 … ¨ YVYU格式跟YUY2类似只是图像数据中YUV分量的排列顺序有所不同 Y0 V0 Y1 U0    Y2 V2 Y3 U2 … ¨ UYVY格式跟YUY2类似只是图像数据中YUV分量的排列顺序有所不同 U0 Y0 V0 Y1    U2 Y2 V2 Y3 … ¨ AYUV格式带有一个Alpha通道并且为每个像素都提取YUV分量图像数据格式如下 A0 Y0 U0 V0    A1 Y1 U1 V1 … ¨ Y41P和Y411格式为每个像素保留Y分量而UV分量在水平方向上每4个像素采样一次。一个宏像素为12个字节实际表示8个像素。图像数据中YUV分量排列顺序如下 U0 Y0 V0 Y1    U4 Y2 V4 Y3    Y4 Y5 Y6 Y8 … ¨ Y211格式在水平方向上Y分量每2个像素采样一次而UV分量每4个像素采样一次。一个宏像素为4个字节实际表示4个像素。图像数据中YUV分量排列顺序如下 Y0 U0 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间隔的方式减小一半色差采样

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/914976.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

上海网站推广模板汉中公司网站建设

NextQRCode ZXing开源库的精简版 **基于ZXing Android实现生成二维码图片和相机扫描二维码图片即时解码的功能原文博客 附源码下载地址** 与原ZXingMini项目对比 NextQRCode做了重大架构修改,原ZXingMini项目与当前NextQRCode不兼容 dependencies {compile com.gith…

网站建设成品常州企业家坠楼公司发讣告后删除

c qt–页面布局(第五部分) 一.页面布局 在设计页面的左侧一栏的组件中我们可以看到进行页面布局的一些组件 布局组件的使用 1.水平布局 使用:将别的组件拖到水平布局的组件中即可,可以选择是在哪个位置 2.垂直布局 使用&…

洛阳便宜网站建设漫画网站建设教程

文章目录 准备安装安装宝塔面板开启ssh和修改ssh的密码导出镜像问题解决宝塔面板无法开启防火墙无法启动ssh设置密码nginx安装失败设置开机启动相关服务准备 演示的系统环境:Ubuntu 22.04.3 LTS更新安装/升级docker到最新版本升级docker相关命令如下# 更新软件包列表并自动升级…

网站开发专业课程oa软件有哪些公司

在一个比较大的C项目中,我们有很多包,每个包都有一个自己的src、include、CMakeLists.txt和其它文件,比如以下文件结构: project- pkg1- datas- data.json- src- xxx1.cpp- include- xxx1.h - CMakeLists.txt- pkg2- src- xxx2.…

网站建设英文如何表达广州搜索seo网站优化

Dart 中的多态教程 一、多态的概念 多态是面向对象编程中的一个重要概念。它允许将子类类型的指针赋值给父类类型的指针,同一个函数调用会有不同的执行效果。换句话说,子类的实例可以赋值给父类的引用。多态的核心在于父类定义一个方法不去实现&#x…

可信赖的响应式网站最好的看vr影片的设备是哪个

在学习Linux的时候,今天遇到了$-,什么意思呢?网上搜索了一些帖子: 帖子1: linux命令 $- 是什么意思 $- 是什么意思?有什么用?可以判断什么交互式shell? $-记录着当前设置的shell…

黄岩区建设局网站如何建一个公司的网站

轿车产业链股9日盘中走势活跃,截至发稿,恒勃股份、博俊科技“20cm”涨停,德迈仕涨超17%,上声电子涨超14%,川环科技涨超10%,圣龙股份、科华控股、沪光股份、上海沿浦、日盈电子、赛力斯等均涨停。 工作方面…

郑州网站建设zzjisu三字型布局的网站

在前面学会了如何开通OSS,对OSS的一些基本操作,接下来记录一下如何通过Java代码通过SDK对OSS存储引擎里面的Bucket存储空间进行创建。 目录 1、先看看OSS: 2、代码编写: 3、运行效果: 1、先看看OSS: 此…

自己开网站需要什么全国医院的网站建设

开源发展20年,.NET Core开源 4年时间,.NET开源实现Mono也有18年的时间,特别近年国内.NET Core社区的蓬勃发展,.NET Core中国社区作为中国开源社区的重要参与者,获得官方的优惠票. 活动主办方开源社,为.NET …

上海企业公示绍兴seo排名收费

实际上任何Linux发行版(Centos/RedHat....),其系统内核都是Linux。我们的应用都需要通过Linux内核与硬件交互。为了避免用户应用导致冲突甚至内核崩溃,用户应用与内核是分离的: 进程的寻址空间会划分为两部分:内核空间、用户空间。…

怎样做网站结构优化网站不被收录的原因

一、物联网在智慧社区中的应用与挑战 随着科技的飞速发展,物联网技术已经深入到我们生活的方方面面,尤其在智慧社区的建设中发挥着举足轻重的作用。物联网通过连接各种设备和系统,为社区居民提供了更便捷、高效的生活方式,同时也…

怎么自己做彩票网站吗商城类网站和o2o网站

第二章线性表 综合 一、在什么情况下用顺序表比用链表好 表长度确定,很少进行插入删除操作且经常访问元素 二、2-4 顺序表的插入和删除要求仍然保持各个元素原来的次序。设在等概率情形下, 对有 127 个元素的顺序表进行插入, 平均需要移动多少个元素? 删除一个元素…

张家港网站制作网络推广网站建设费用模板

字符串转换整数 描述 : 请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C 中的 atoi 函数)。 函数 myAtoi(string s) 的算法如下: 读入字符串并丢弃无用的前导空格检查下一个字符&am…

石家庄哪里能制作网站网站一年维护费用

matlab阻尼振动模拟matlab阻尼振动模拟班级 应数0801 姓名 翟伟西 学号 u座机电话号码5实验目的通过这个实验能更好的了解学习matlab程序语言,了解matlab在仿真方面的应用实验原理通过把做阻尼振动的小球的运动作投影,更好的观察在阻尼振动过程中&#x…

ipa文件自己网站怎么做下载网站备案邮寄资料

电脑会储存大量的重要数据,而为了避免数据泄露,必须要使用专业的方式进行保护。那么,要如何保护电脑数据呢?下面我们就来了解一下。 文件夹加密超级大师 文件夹加密超级大师是一款专业的电脑数据加密软件,拥有强大的文…

深圳做门户网站的网络公司有网站源码去哪里做

一、前言 workstations想必很多童鞋都在用,经常会用来在本机创建不同的虚拟机来做各种测试,那么对于它支持的网络模式,在不同的测试场景下应该用哪种网络模式,你需要做下了解,以便可以愉快的继续测(搬&…

可信网站认证必须做吧商城网站建设都有哪些类型

岁末年终,回顾2023年,这一年你都做了什么呢? 记不清楚没关系,互联网都帮你记录好了。2023年,B站的年轻人当“所见所闻”刷新自身认知时,往往会发送弹幕“啊?”来抒发惊叹。这一年,支付宝“小荷包”的用户中00后占了4成,近一半更开启了“自动攒”计划“无痛攒钱”!携程上,每7…

海东高端网站建设wordpress 个人信息编辑

原创 哪吒 哪吒编程 2023-09-07 08:03 发表于辽宁 收录于合集#Redis11个 (给哪吒编程加星标,提高Java技能) 大家好,我是哪吒。 在前几篇文章中,提到了Redis实现排行榜、Redis数据缓存策略,让我们对Redis…

没有网站可以做百度直通车吗密码管理

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲解供…