Tuesday, October 09, 2007

Audio: 如何播放一段 WAV 檔

Example:
PlaySound("camera.wav",NULL,SND_APPLICATION);

The PlaySound function plays a sound specified by the given filename, resource, or system event.
(A system event may be associated with a sound in the registry or in the WIN.INI file.)

BOOL PlaySound(
LPCSTR pszSound,
HMODULE hmod,
DWORD fdwSound
);

Parameters

pszSound

A string that specifies the sound to play. If this parameter is NULL, any currently playing waveform sound is stopped. To stop a non-waveform sound, specify SND_PURGE in the fdwSound parameter.

Three flags in fdwSound (SND_ALIAS, SND_FILENAME, and SND_RESOURCE) determine whether the name is interpreted as an alias for a system event, a filename, or a resource identifier. If none of these flags are specified, PlaySound searches the registry or the WIN.INI file for an association with the specified sound name. If an association is found, the sound event is played. If no association is found in the registry, the name is interpreted as a filename.

hmod

Handle of the executable file that contains the resource to be loaded. This parameter must be NULL unless SND_RESOURCE is specified in
fdwSound.

fdwSound

Flags for playing the sound. The following values are defined:

SND_APPLICATION

The sound is played using an application-specific association.

SND_ALIAS

The pszSound parameter is a system-event alias in the registry or the WIN.INI file. Do not use with either SND_FILENAME or SND_RESOURCE.

SND_ALIAS_ID

The pszSound parameter is a predefined sound identifier.

SND_ASYNC

The sound is played asynchronously and PlaySound returns immediately after beginning the sound. To terminate an asynchronously played waveform sound, call PlaySound with pszSound set to NULL.

SND_FILENAME

The pszSound parameter is a filename.

SND_LOOP

The sound plays repeatedly until PlaySound is called again with the pszSound parameter set to NULL. You must also specify the SND_ASYNC flag to indicate an asynchronous sound event.

SND_MEMORY

A sound event's file is loaded in RAM. The parameter specified by pszSound must point to an image of a sound in memory.

SND_NODEFAULT

No default sound event is used. If the sound cannot be found, PlaySound returns silently without playing the default sound.

SND_NOSTOP

The specified sound event will yield to another sound event that is already playing. If a sound cannot be played because the resource needed to generate that sound is busy playing another sound, the function immediately returns FALSE without playing the requested sound.
If this flag is not specified, PlaySound attempts to stop the currently playing sound so that the device can be used to play the new sound.

SND_NOWAIT

If the driver is busy, return immediately without playing the sound.

SND_PURGE

Sounds are to be stopped for the calling task. If pszSound is not NULL, all instances of the specified sound are stopped. If pszSound is NULL, all sounds that are playing on behalf of the calling task are stopped.
You must also specify the instance handle to stop SND_RESOURCE events.

SND_RESOURCE

The pszSound parameter is a resource identifier; hmod must identify the instance that contains the resource.

SND_SYNC

Synchronous playback of a sound event. PlaySound returns after the sound event completes.

Return Values

Returns TRUE if successful or FALSE otherwise.

Remarks

The sound specified by pszSound must fit into available physical memory and be playable by an installed waveform-audio device driver. PlaySound searches the following directories for sound files: the current directory; the Windows directory; the Windows system directory; directories listed in the PATH environment variable; and the list of directories mapped in a network. For more information about the directory search order, see the documentation for the OpenFile function.

If it cannot find the specified sound, PlaySound uses the default system event sound entry instead. If the function can find neither the system default entry nor the default sound, it makes no sound and returns FALSE.
 

Wednesday, November 22, 2006

文章總覽

VFW:

VFW.H ( 28 Sep, 2006 )
取得視訊裝置驅動程式的資訊 ( 29 Sep, 2006 )
如何建立一個視訊擷取視窗 ( 13 Oct, 2006 )
連結視訊擷取視窗與視訊裝置 ( 13 Oct, 2006 )
取得視訊裝置驅動程式的效能 ( 15 Oct, 2006 )
設定顯示模式 ( 15 Oct, 2006 )
設定視訊畫面顯示速率 ( 15 Oct, 2006 )
調整視訊畫面大小 ( 15 Oct, 2006 )
靜態影像擷取 ( 1 Nov, 2006 )
錄影參數設定 ( 4 Nov, 2006 )

Bitmap:

RGB macro ( 12 Oct, 2006 )
位元塊傳輸 BitBlt ( 18 Nov, 2006 )

Data Tpyes & Classes:

TColor type ( 6 Oct, 2006 )
TCanvas ( 6 Oct, 2006 )
TRect type ( 21 Oct, 2006 )
tagPOINT type ( 28, May, 2006 )

Objects & Methods:

TImage ( 25 Sep, 2006 )
TPicture ( 25 Sep, 2006 )
Objects ( 26 Sep, 2006 )
TCanvas::CopyRect method ( 21 Oct, 2006 )

Basic:

開啟 BMP 影像 ( 11 Sep, 2006 )
開啟 JPEG 影像 ( 11 Sep, 2006 )
動態宣告二維陣列 ( 13 Sep, 2006 )
Visual Component Library (VCL) ( 24 Sep, 2006 )
Component Palette ( 25 Sep, 2006 )
如何讓 Label 顯示實數值 ( 13 Nov, 2006)
將布林值轉成字串 BoolToStr ( 4 Nov, 2006 )

 

Saturday, November 18, 2006

Bitmap: 位元塊傳輸 BitBlt

當我們想將圖像從視訊顯示的某個區域複製到另外一個區域時, 可以考慮使用 Windows 圖形裝置介面 (Graphics Device Interface, GDI) 所提供的位元塊傳輸 ( bit-block transfer ) 函式 BitBlt。BitBlt 讀作 bit blit, 有關 Bit Blit 這個指令的來源, 在 維基百科有相當詳細的描述; 除此, 維基百科還用小精靈為例子, 介紹關於背景圖片與 BitBlt 的使用方法, 值得一看...
The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels from the specified source device context into a destination device context.

BOOL BitBlt(
 HDC hdcDest,
  // handle to destination device context
 int nXDest,
  // x-coordinate of destination rectangle's upper-left corner
 int nYDest,
  // y-coordinate of destination rectangle's upper-left corner
 int nWidth,
  // width of destination rectangle
 int nHeight,
  // height of destination rectangle
 HDC hdcSrc,
  // handle to source device context
 int nXSrc,
  // x-coordinate of source rectangle's upper-left corner
 int nYSrc,
  // y-coordinate of source rectangle's upper-left corner
 DWORD dwRop
  // raster operation code
);

Parameters
hdcDest Identifies the destination device context.

nXDest
 Specifies the logical x-coordinate of the upper-left corner of the destination rectangle.

nYDest
 Specifies the logical y-coordinate of the upper-left corner of the destination rectangle.

nWidth
 Specifies the logical width of the source and destination rectangles.

nHeight
 Specifies the logical height of the source and the destination rectangles.

hdcSrc
 Identifies the source device context.

nXSrc
 Specifies the logical x-coordinate of the upper-left corner of the source rectangle.

nYSrc
 Specifies the logical y-coordinate of the upper-left corner of the source rectangle.

dwRop
 Specifies a raster-operation code. These codes define how the color data for the source rectangle is to be combined with the color data for the destination rectangle to achieve the final color.

The following list shows some common raster operation codes:

Value Description

BLACKNESS  Fills the destination rectangle using the color associated with index 0 in the physical palette. (This color is black for the default physical palette.)

DSTINVERT  Inverts the destination rectangle.

MERGECOPY Merges the colors of the source rectangle with the specified pattern by using the Boolean AND operator.

MERGEPAINT  Merges the colors of the inverted source rectangle with the colors of the destination rectangle by using the Boolean OR operator.

NOTSRCCOPY Copies the inverted source rectangle to the destination.

NOTSRCERASE 
Combines the colors of the source and destination rectangles by using the Boolean OR operator and then inverts the resultant color.

PATCOPY
 Copies the specified pattern into the destination bitmap.

PATINVERT
 Combines the colors of the specified pattern with the colors of the destination rectangle by using the Boolean XOR operator.

PATPAINT
 Combines the colors of the pattern with the colors of the inverted source rectangle by using the Boolean OR operator. The result of this operation is combined with the colors of the destination rectangle by using the Boolean OR operator.

SRCAND
 Combines the colors of the source and destination rectangles by using the Boolean AND operator.

SRCCOPY  Copies the source rectangle directly to the destination rectangle.

SRCERASE  Combines the inverted colors of the destination rectangle with the colors of the source rectangle by using the Boolean AND operator.

SRCINVERT  Combines the colors of the source and destination rectangles by using the Boolean XOR operator.

SRCPAINT  Combines the colors of the source and destination rectangles by using the Boolean OR operator.

WHITENESS Fills the destination rectangle using the color associated with index 1 in the physical palette. (This color is white for the default physical palette.)

Return Values
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.

Remarks
If a rotation or shear transformation is in effect in the source device context, BitBlt returns an error. If other transformations exist in the source device context (and a matching transformation is not in effect in the destination device context), the rectangle in the destination device context is stretched, compressed, or rotated as necessary.

If the color formats of the source and destination device contexts do not match, the BitBlt function converts the source color format to match the destination format.

When an enhanced metafile is being recorded, an error occurs if the source device context identifies an enhanced-metafile device context.

Not all devices support the BitBlt function. For more information, see the RC_BITBLT raster capability entry in GetDeviceCaps.

BitBlt returns an error if the source and destination device contexts represent different devices.

針對 BitBlt 這個指令, 我做了一項有趣的實驗, 利用 WebCam 攝影機拍攝了連續兩張影像, 這兩張影像人眼看起來雖然相同, 但是, 由於光影的影響, 還是存在一些像素的色彩值有些許的差異。



我使用 BitBlt 這個指令, 並設定運算模式為 SRCINVERT, 將一張影像從 Device Context (DC), 傳送到另外一張影像的 DC 中, 得到下列這張影像...



很有趣的實驗, 你知道為什麼這張影像會出現紅、綠、藍這些顏色嗎?
 

Monday, November 13, 2006

如何讓 Label 顯示實數值

在程式中, 我們常會遭遇到要顯示實數(real number)的問題, 早期我會直接寫一個小程式把實數中每一個 digit 都算出來, 然後轉換成 AnsiString, 再把字串接起來, 再顯示到 Label 上。

後來, 我的作法就簡單多了, 直接用 sprintf 的方式, 將實數輸出到某一個字串中, 然後再顯示到某個 Label 上。例如:

//宣告部份
char Message[10];

//程式部份
RMS = sqrt(SquareErrorSum/(MH*MW*3));
sprintf(Message,"%6.3f",RMS);
lblRMS->Caption = "RMS="+AnsiString(Message);
 

Saturday, November 04, 2006

VFW: 取得與設定錄影參數

攝影機錄影期間, 必須針對需求設定相關攝影參數, 這些參數在 vfw.h 之中, 宣告一個資料型態來儲存這些參數。
typedef struct tagCaptureParms {
 DWORD dwRequestMicroSecPerFrame;
           // Requested capture rate
 BOOL fMakeUserHitOKToCapture; // Show "Hit OK to cap" dlg?
 UINT wPercentDropForError; // Give error msg if > (10%)
 BOOL fYield; // Capture via background task?
 DWORD dwIndexSize; // Max index size in frames (32K)
 UINT wChunkGranularity; // Junk chunk granularity (2K)
 BOOL fUsingDOSMemory; // Use DOS buffers?
 UINT wNumVideoRequested; // # video buffers, If 0, autocalc
 BOOL fCaptureAudio; // Capture audio?
 UINT wNumAudioRequested; // # audio buffers, If 0, autocalc
 UINT vKeyAbort; // Virtual key causing abort
 BOOL fAbortLeftMouse; // Abort on left mouse?
 BOOL fAbortRightMouse; // Abort on right mouse?
 BOOL fLimitEnabled; // Use wTimeLimit?
 UINT wTimeLimit; // Seconds to capture
 BOOL fMCIControl; // Use MCI video source?
 BOOL fStepMCIDevice; // Step MCI device?
 DWORD dwMCIStartTime; // Time to start in MS
 DWORD dwMCIStopTime; // Time to stop in MS
 BOOL fStepCaptureAt2x; // Perform spatial averaging 2x
 UINT wStepCaptureAverageFrames;
          // Temporal average n Frames
 DWORD dwAudioBufferSize; // Size of audio bufs (0 = default)
 BOOL fDisableWriteCache; // Attempt to disable write cache
 UINT AVStreamMaster; // Which stream controls length?
} CAPTUREPARMS, *PCAPTUREPARMS, FAR *LPCAPTUREPARMS;

因此, 我們在程式中可以如下宣告一個變數 s,
tagCaptureParms s;
然後, 我們就可以透過 &s 當作為呼叫 VFW SDK 相關函數的參數, 了解目前視訊系統的攝影參數設定為何? 一般來說, 一些我們比較常用到的攝影參數為:
  • 指定視訊畫面的擷取速率
  • 指定分派影像緩衝區數目
  • 選擇是否'擷取聲音
  • 指定視訊串流擷取時間長短
  • 指定擷取時間是否使用 MCI 裝置
  • 指定鍵盤或滑鼠控制來終止擷取
在 VFW SDK 中, 透過 capCaptureGetSetup 可以知道目前的錄影參數的設定為何?
The capCaptureGetSetup macro retrieves the current settings of the streaming capture parameters.

BOOL capCaptureGetSetup(
 hwnd,
 s,
 wSize
 );

Parameters
hwnd Handle of a capture window.
s Address of a CAPTUREPARMS structure.
wSize Size, in bytes, of the structure referenced by s.

Return Values
Returns TRUE if successful or FALSE otherwise.

Remarks
For information about the parameters used to control streaming capture, see the CAPTUREPARMS structure.
知道了錄影參數的設定情形後, 我們也可以透過 capCaptureSetSetup 來改變錄影參數的設定:
The capCaptureSetSetup macro sets the configuration parameters used with streaming capture.

BOOL capCaptureSetSetup(
 hwnd,
 s,
 wSize
 );

Parameters
hwnd Handle of a capture window.
s Address of a CAPTUREPARMS structure.
wSize Size, in bytes, of the structure referenced by s.

Return Values
Returns TRUE if successful or FALSE otherwise.

Remarks
For information about the parameters used to control streaming capture, see the CAPTUREPARMS structure.
延伸閱讀: C++ Builder's Help 中的 CAPTUREPARMS structure

將布林值轉成字串 BoolToStr

運用在邏輯運算的 Boolean 型態值有 true or false 兩個。因此, 這兩個字在 C++ 屬於 specific keywords。換句話說, 你不可以用這兩個字當變數名稱, 它們是有特定意義的。

我們再深入一點探討, 電腦是怎麼儲存這個形態的變數呢? 我們看看 BCB 中的 Help 是怎麼說的:
bool, true, false

Category

C++-Specific Keywords

Syntax
bool ;

Description
Use bool and the literals false and true to perform Boolean logic tests.

The bool keyword represents a type that can take only the value false or true. The keywords false and true are Boolean literals with predefined values. false is numericallly zero and true is numerically one. These Boolean literals are rvalues; you cannot make an assignment to them.

You can convert an rvalue that is of type bool to an rvalue that is int type. The numerical conversion sets false to zero and true becomes one.

You can convert arithmetic, enumeration, pointer, or pointer to member rvalue types to an rvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false. Any other value is converted to true.

很顯然地, 這些 Boolean 值在電腦中, 也是用電腦基本的 0, 1 數值來儲存。"The keywords false and true are Boolean literals with predefined values. false is numericallly zero and true is numerically one." 此外, 我們也可以把一些其他型態的值轉換成布林值, 像 0, null pointer value, null member pointer value 會被轉換成 false, 其餘則是通通轉換成 true

在 BCB 中, 還提供了一個 BoolToStr 將布林值轉換成字串。
BoolToStr(bool B, bool UseBoolStrs)
Converts a Boolean value to an AnsiString.

Unit
SysUtils

Category
type conversion routines

extern PACKAGE AnsiString __fastcall BoolToStr(bool B, bool UseBoolStrs = false);

Description
BoolToStr converts the given Boolean value to a string as follows:

B UseBoolStrs  Returned string
true  false    "-1"
true  true    The first string in TrueBoolStrs (default, "TRUE");
false  false    "0"
false  true    The first string in FalseBoolStrs (default, "FALSE");

 

Wednesday, November 01, 2006

VFW: 靜態影像擷取

VFW SDK 所提供的擷取靜態影像方式是先抓取單一視訊畫面 ( frame ), 將其存入記憶體緩衝區中, 接下來你可以選擇要將存到剪貼簿中, 或是直接存成一張點陣圖檔 ( .BMP )。

抓取單一視訊畫面時, 依照不同需求, 可以使用 capGrabFrame 選擇讓原先動態的視訊畫面靜止, 或是用 capGrabFrameNoStop 不讓畫面靜止。靜止的影像可以讓我們清楚地看清抓取的視訊畫面為何, 如果要讓原先的擷取視窗恢復動態顯示, 則是必須重新 設定顯示模式 才行。

The capGrabFrame macro retrieves and displays a single frame from the capture driver. After capture, overlay and preview are disabled.

BOOL capGrabFrame(
 hwnd
 );

Parameters
hwnd Handle of a capture window.

Return Values
Returns TRUE if successful or FALSE otherwise.

Remarks
For information about installing callback functions, see the capSetCallbackOnError and capSetCallbackOnFrame macros.
因為必須告知要抓取哪一個視訊視窗, 所以函數的傳入值 ( parameter ) 就是該視窗的代碼 ( handle)。而傳回值 ( return value ) 就是告知我們是否成功捉取畫面。至於抓取畫面後的後續動作, 還可以使用回呼函數 ( callback function ) 來執行。
The capGrabFrameNoStop macro fills the frame buffer with a single uncompressed frame from the capture device and displays it. Unlike with the capGrabFrame macro, the state of overlay or preview is not altered by this message.

BOOL capGrabFrameNoStop(
 hwnd
 );

Parameters
hwnd Handle of a capture window.

Return Values
Returns TRUE if successful or FALSE otherwise.

Remarks
For information about installing callback functions, see the capSetCallbackOnError and capSetCallbackOnFrame macros.
以點陣圖格式 ( device independent bitmap, DIB ) 放入緩衝區的視訊畫面, 可以透過放到剪貼簿的方式 (capEditCopy) 讓別的應用程式使用。
The capEditCopy macro copies the contents of the video frame buffer and associated palette to the clipboard.

BOOL capEditCopy(
 hwnd
 );

Parameters
hwnd Handle of a capture window.

Return Values
Returns TRUE if successful or FALSE otherwise.
我們也可以使用 capFileSaveDIB 直接將緩衝區中畫面存成點陣圖檔 ( .BMP )。
The capFileSaveDIB macro copies the current frame to a DIB file.

BOOL capFileSaveDIB(
 hwnd,
 szName
);

Parameters
hwnd Handle of a capture window.
szName Address of the null-terminated string that contains the name of the destination DIB file.

Return Values
Returns TRUE if successful or FALSE otherwise. If an error occurs and an error callback function is set using the capSetCallbackOnError macro, the error callback function is called.

Remarks
If the capture driver supplies frames in a compressed format, this call attempts to decompress the frame before writing the file.
注意: 輸入參數 szName 變數名稱前置的 sz 告訴我們這是一個 null-terminated string。而要傳入的正是該 string 的記憶體位址 ( address )。因此, 若是我們在 BCB 中, 要用一個 TSavePictureDialog 類別的物件要讓使用者輸入檔名, 我們在程式中則是要將該物件的檔名屬性 ( TSavePictureDialog::FileName ) 中的檔名位址指定給 capFileSaveDIB 函數。假設該物件的名稱為 SavePictureDialog1, 而檔名的位址為: &SavePictureDialog1->FileName[1]。

範例程式:
 if ( SavePictureDialog1->Execute() )
  {
  capFileSaveDIB(hwndVideo,&(SavePictureDialog1->FileName[1]));
  }
 

Saturday, October 21, 2006

TRect type

TRect defines a rectangle.
Unit
Types

struct TRect
 {
 TRect() {}
 TRect(const TPoint& TL, const TPoint& BR)
  { left=TL.x; top=TL.y; right=BR.x; bottom=BR.y; }
 TRect(int l, int t, int r, int b)
  { left=l; top=t; right=r; bottom=b; }
 TRect(RECT& r)
  {
  left = r.left;
  top = r.top;
  right = r.right;
  bottom = r.bottom;
  }

int Width() const { return right - left; }
int Height() const { return bottom - top ; }
bool operator ==(const TRect& rc) const
 {
 return left == rc.left && top==rc.top &&
 right == rc.right && bottom==rc.bottom;
 }
bool operator !=(const TRect& rc) const
 { return !(rc==*this); }
 __property LONG Left = { read=left, write=left };
 __property LONG Top = { read=top, write=top };
 __property LONG Right = { read=right, write=right };
 __property LONG Bottom = { read=bottom, write=bottom };
 };

Description
TRect represents the dimensions of a rectangle. The coordinates are specified as either four separate integers representing the left, top, right, and bottom sides, or as two points representing the locations of the top left and bottom right corners.

Typically, TRect values represent pixel locations, where the origin of the pixel coordinate system is in the top left corner of the screen (screen coordinates) or the top left corner of a control client area (client coordinates). When a TRect value represents a rectangle on the screen, by convention the top and left edges are considered inside the rectangle and the bottom and right edges are considered outside the rectangle. This convention allows the width of the rectangle to be Right - Left and the height to be Bottom - Top.
要特別注意的一點是 TRect 這個長方塊中所指明的區域並不包含 the bottom and right edges, 這是為了讓 rectangle 的長寬值剛好符合座標相減的緣故。
 

TCanvas::CopyRect method

Copies part of an image from another canvas into the canvas.
void __fastcall CopyRect(const TRect &Dest, TCanvas* Canvas, const TRect &Source);

Description
Use CopyRect to transfer part of the image on another canvas to the image of the TCanvas object. Dest specifies the rectangle on the canvas where the source image will be copied. The Canvas parameter specifies the canvas with the source image. Source specifies a rectangle bounding the portion of the source canvas that will be copied.

The portion of the source canvas is copied using the mode specified by CopyMode.
TCanvas::CopyRect method 可以將另外一個 Canvas ( 第二個輸入參數 ) 中的特定長方塊 (rectangle) ( 第三個輸入參數 ) 中的影像 copy 到自己這個 Canvas 的特定長方塊( 第一個輸入參數 ) 中。
 

Sunday, October 15, 2006

VFW: 調整視訊畫面大小

調整視訊畫面大小主要有兩個步驟:
1. 使用VFW SDK 所提供的 capPreviewScale 函數設定畫面大小是否隨著視窗大小變化。
2. 使用 Win32 API 的 MoveWindow 函數來調整視訊擷取視窗的大小。

在 Preview 的顯示模式下, VFW SDK 提供 capPreviewScale 函數來允許視訊畫面大小隨著視窗大小變化而調整。
The capPreviewScale macro enables or disables scaling of the preview video images. If scaling is enabled, the captured video frame is stretched to the dimensions of the capture window.

BOOL capPreviewScale(
 hwnd,
 f
 );

Parameters
hwnd Handle of a capture window.
f Preview scaling flag.
Specify TRUE for this parameter to stretch preview frames to the size of the
capture window or FALSE to display them at their natural size.

Return Values
Returns TRUE if successful or FALSE otherwise.

Remarks
Scaling preview images controls the immediate presentation of captured frames within the capture window. It has no effect on the size of the frames saved to file. Scaling has no effect when using overlay to display video in the frame buffer.
設定擷取畫面隨著擷取視窗的位置, 大小而調整後, 我們就可以使用 Win32 API 所提供的 MoveWindow 函數來調整視窗, 達到調整視訊擷取畫面的目的
The MoveWindow function changes the position and dimensions of the specified window. For a top-level window, the position and dimensions are relative to the upper-left corner of the screen. For a child window, they are relative to the upper-left corner of the parent window's client area.

BOOL MoveWindow(
 HWND hWnd,  // handle of window
 int X,     // horizontal position
 int Y,     // vertical position
 int nWidth,  // width
 int nHeight,   // height
 BOOL bRepaint // repaint flag
 );

Parameters
hWnd Identifies the window.
X Specifies the new position of the left side of the window.
Y Specifies the new position of the top of the window.
nWidth Specifies the new width of the window.
nHeight Specifies the new height of the window.
bRepaint Specifies whether the window is to be repainted. If this parameter is TRUE, the window receives a WM_PAINT message. If the parameter is FALSE, no repainting of any kind occurs. This applies to the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent window uncovered as a result of moving a child window. If this parameter is FALSE, the application must explicitly invalidate or redraw any parts of the window and parent window that need redrawing.

Return Values
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero.

Remarks
If the bRepaint parameter is TRUE, Windows sends the WM_PAINT message to the window procedure immediately after moving the window (that is, the MoveWindow function calls the UpdateWindow function). If bRepaint is FALSE, Windows places the WM_PAINT message in the message queue associated with the window. The message loop dispatches the WM_PAINT message only after dispatching all other messages in the queue.

VFW: 設定視訊畫面顯示速率

在Preview 顯示模式下, VFW SKD 提供 capPreviewRate 函數來設定視訊畫面的顯示速率。
The capPreviewRate macro sets the frame display rate in preview mode.

BOOL capPreviewRate(
 hwnd,
 wMS
 );

Parameters
hwnd Handle of a capture window.
wMS Rate, in milliseconds, at which new frames are captured and displayed.

Return Values
Returns TRUE if successful or FALSE if the capture window is not connected to a capture driver.

Remarks
The preview mode uses substantial CPU resources. Applications can disable preview or lower the preview rate when another application has the focus. During streaming video capture, the previewing task is lower priority than writing frames to disk, and preview frames are displayed only if no other buffers are available for writing.
注意: 這邊的 wMS 指的就是一個畫面 ( frame ) 要顯示多少毫秒 ( msec ), 單位是 msec/frame, 若要轉換成我們一般習慣的每秒顯示多少個畫面, 單位是 frame/sec, 則是 1sec. = 1000 msec. 例如: 每個畫面顯示 20 毫秒, 代表每秒種可以顯示 1000/20 = 50 個畫面。
 

VFW: 設定顯示模式

視訊顯示模式分成兩種:
一、Preview 顯示模式:
從視訊裝置取得的影像資料會先放在系統記憶體中, 然後再顯示於螢幕上。這些處理過程全都要仰賴 CPU 處理, 因此效率較差。在 Preview 模式下, 可以透過 capPreviewRate 函數設定視訊畫面的顯示速率與透過 capPreviewScale 調整顯示畫面尺寸。VFW SDK 提供了 capPreview 函數來啟動 Preview 顯示模式。
The capPreview macro enables or disables preview mode. In preview mode, frames are transferred from the capture hardware to system memory and then displayed in the capture window using GDI functions.

BOOL capPreview(
 hwnd,
 f
 );

Parameters
hwnd Handle of a capture window.
f Preview flag. Specify TRUE for this parameter to enable preview mode or FALSE to disable it.

Return Values
Returns TRUE if successful or FALSE otherwise.

Remarks
The preview mode uses substantial CPU resources. Applications can disable preview or lower the preview rate when another application has the focus. The fLiveWindow member of the CAPSTATUS structure indicates if preview mode is currently enabled. Enabling preview mode automatically disables overlay mode.
二、Overlay 顯示模式:
視訊裝置會直接將影像資料覆疊到螢幕上, 因此, 並不會佔用系統的 CPU 與記憶體資源, 所以顯示效率較好。不過, 並不是所有的視訊裝置都支援 Overlay 模式, 像 USB 攝影機就不支援 Overlay 顯示模式。 VFW SDK 提供 capOverlay 函數來啟動 Overlay 顯示模式。
The capOverlay macro enables or disables overlay mode. In overlay mode, video is displayed using hardware overlay.

BOOL capOverlay(
 hwnd,
 f
 );

Parameters
hwnd Handle of a capture window.
f Overlay flag. Specify TRUE for this parameter to enable overlay mode or FALSE to disable it.

Return Values
Returns TRUE if successful or FALSE otherwise.

Remarks
Using an overlay does not require CPU resources. The fHasOverlay member of the CAPDRIVERCAPS structure indicates whether the device is capable of overlay. The fOverlayWindow member of the CAPSTATUS structure indicates whether overlay mode is currently enabled. Enabling overlay mode automatically disables preview mode.
註: USB 攝影機將類比影像訊號轉成數位資料, 透過 USB 傳輸介面傳送到系統記憶體中, 然後 CPU 再將影像資料顯示於螢幕上。至於影像擷取卡, 透過 A/D 轉換模組, 將類比影像訊號轉成數位資料, 並儲存於影像擷取卡的記憶體中。某些較高階的影像擷取卡還包含了影像處理晶片, 提供一些基本的影像處理功能。
 

VFW: 取得視訊裝置驅動程式的效能

由於各家視訊裝置所提供的驅動程式功能並不完全相同, 因此, 我們開發的應用程式有必要了解自己所安裝的驅動程式到底提供了什麼功能。VFW SDK 提供了 capDriverGetCaps 函數來讓你了解自己的視訊系統。
The capDriverGetCaps macro returns the hardware capabilities of the capture driver currently connected to a capture window.

capDriverGetCaps(
 hwnd,
 psCaps,
 wSize
 );

Parameters
hwnd Handle of a capture window.
psCaps Address of the CAPDRIVERCAPS structure to contain the hardware capabilities.
wSize Size, in bytes, of the structure referenced by s.

Return Values
Returns TRUE if successful or FALSE if the capture window is not connected to a capture driver.

Remarks
The capabilities returned in CAPDRIVERCAPS are constant for a given capture driver. Applications need to retrieve this information once when the capture driver is first connected to a capture window.
呼叫了這個函數後, 我們的應用程式就會得知你的電腦中代表該視訊驅動程式的索引值, 你的視訊裝置有沒有提供影像 Overlay 模式, 提供了哪些對話盒供你呼叫使用...等等。

既然這個函數要告訴我們這麼多資料, 顯然呼叫時, 就要設定很多個輸入或輸出的參數。為了方便我們使用, VFW 所採用的作法就是在 vfw.h, line 3493 起, 宣告了 tagCapDriverCaps 結構資料型態供我們使用:
typedef struct tagCapDriverCaps {
 UINT wDeviceIndex; // Driver index in system.ini
 BOOL fHasOverlay; // Can device overlay?
 BOOL fHasDlgVideoSource; // Has Video source dlg?
 BOOL fHasDlgVideoFormat; // Has Format dlg?
 BOOL fHasDlgVideoDisplay; // Has External out dlg?
 BOOL fCaptureInitialized; // Driver ready to capture?
 BOOL fDriverSuppliesPalettes; // Can driver make palettes?
 // following always NULL on Win32.
 HANDLE hVideoIn; // Driver In channel
 HANDLE hVideoOut; // Driver Out channel
 HANDLE hVideoExtIn; // Driver Ext In channel
 HANDLE hVideoExtOut; // Driver Ext Out channel
 } CAPDRIVERCAPS, *PCAPDRIVERCAPS, FAR *LPCAPDRIVERCAPS;
因此, 我們只要在程式中宣告一個變數 s 屬於 tagCapDriverCaps 資料型態, 我們就可以將 s 的位址 &s 放到 capDriverGetCaps 的參數之中來用了。

範例程式:
// 宣告部份:
tagCapDriverCaps s;

// 呼叫與傳回值使用部份
if (capDriverGetCaps(hwndVideo,&s,sizeof(s)))
 {
 if ( s.fHasOverlay )
  lblOverlay->Caption = AnsiString("Overlay: Yes");
 else
  lblOverlay->Caption = AnsiString("Overlay: No");
 }
 

Friday, October 13, 2006

VFW: 連結視訊擷取視窗與視訊裝置

The capDriverConnect macro connects a capture window to a capture driver.
BOOL capDriverConnect(
 hwnd,
 iIndex
 );

Parameters
hwnd Handle of a capture window.
iIndex Index of the capture driver. The index can range from 0 through 9.

Return Values
Returns TRUE if successful or FALSE if the specified capture driver cannot be connected to the capture window.

Remarks
Connecting a capture driver to a capture window automatically disconnects any previously connected capture driver.
當我們的應用程式建立一個視訊擷取視窗時, 視窗的畫面仍然會黑壓壓的一片, 這是由於視訊裝置所拍攝的資料並沒有餵進所建立之視訊擷取視窗的緣故。我們可以用 capDriverConnect 這個函數將兩者連結起來。很自然而然地, 輸入參數一個是之前建立視窗時傳回的 handle 值, 另一個是視訊裝置驅動程式的編號 iIndex。不過, 要中斷兩者的連結 capDriverDisconnect , 只要指出哪個視訊擷取視窗要中斷連結即可, 並不需要指出兩邊的參數。


The capDriverDisconnect macro disconnects a capture driver from a capture window.

BOOL capDriverDisconnect(
 hwnd
 );

Return Values
Returns TRUE if successful or FALSE if the capture window is not connected to a capture driver.
注意: 連結成功後, 視訊擷取視窗的影像仍然是靜態的, 並不是即時動態的視訊資料, 這是由於尚未 設定顯示模式 的緣故。
 

VFW: 如何建立一個視訊擷取視窗

The capCreateCaptureWindow function creates a capture window.
HWND VFWAPI capCreateCaptureWindow(
LPCSTR lpszWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWnd,
int nID
);

Parameters
lpszWindowName Null-terminated string containing the name used for the capture window.
dwStyle Window styles used for the capture window.
( Note: Window styles are described with the CreateWindowEx function.)
x and y The x- and y-coordinates of the upper left corner of the capture window.
nWidth and nHeight Width and height of the capture window.
hWnd Handle of the parent window.
nID Window identifier.

Return Values
Returns a handle of the capture window if successful or NULL otherwise.
看完 BCB Help 的說明後, 我們一樣也來看看 vfw.h 之中, capCreateCaptureWindow 是如何宣告的:
HWND VFWAPI capCreateCaptureWindowA (
LPCSTR lpszWindowName,
DWORD dwStyle,
int x, int y, int nWidth, int nHeight,
HWND hwndParent, int nID);

HWND VFWAPI capCreateCaptureWindowW (
LPCWSTR lpszWindowName,
DWORD dwStyle,
int x, int y, int nWidth, int nHeight,
HWND hwndParent, int nID);
我們要建立一個視訊擷取視窗, 自然要告訴電腦要把視窗建立在哪邊? 是要直接放在 Form 上呢? 還是放在 Form 上的 Panel 物件上呢? 因此, 我們必須透過 handleParent 這個參數來告訴電腦, 也就是需要告訴電腦一個代碼, 這個代碼表示了所產生的視窗將要顯示在哪個物件之上。除此, 要放在這個物件的何處, 則是透過 x, y 來指定視窗的左上角要放這個物件的哪一個 ( x, y ) 座標上; 至於所建立的擷取視窗大小則是透過 nWidth 與 nHeight 兩個參數來表示。

capCreateCaptureWindow 的傳回值的資料型態為 HWND, 也就是所建立的視訊擷取視窗的代碼 ( handle ), 將來我們程式中要提到或針對此視窗的相關處理時, 只要指明這個代碼即可。

要關閉視訊擷取視窗的方法, 如同要關閉一般視窗一樣, 只要利用 Win32 API 的 DestroyWindow 函數, 並告訴電腦你要關閉的視窗代碼 ( handle ) 即可。

程式範例:
HWND hwndVideo;

hwndVideo = capCreateCaptureWindow(
(LPSTR) "My Capture Window", WS_CHILD | WS_VISIBLE,
0, 0, iImageWidth, iImageHeight, Form1->pnlCapture1->Handle, 1 );

Thursday, October 12, 2006

RGB macro

The RGB macro selects a red, green, blue (RGB) color based on the arguments supplied and the color capabilities of the output device.
COLORREF RGB(
BYTE bRed, // red component of color
BYTE bGreen, // green component of color
BYTE bBlue // blue component of color
);

Parameters
cRed Specifies the intensity of the red color.
cGreen Specifies the intensity of the green color.
cBlue Specifies the intensity of the blue color.

Return Values
The return value is the resultant RGB color.

Remarks
The intensity for each argument is in the range 0 through 255. If all three intensities are zero, the result is black. If all three intensities are 255, the result is white.

The RGB macro is defined as follows:

#define RGB(r, g ,b) ((DWORD) (((BYTE) (r) | \
((WORD) (g) << 8)) | (((DWORD) (BYTE) (b)) << 16)))

Friday, October 06, 2006

TCanvas

TCanvas 這個類別是用來處理 Window 繪圖的介面, 負責與 Window 的裝置驅動程式溝通, 透過裝置驅動程式將資料顯示在顯示器上面。

C++ Builder 中, 具有 Canvas 的元件有 TForm, TImage, TbitButton ... 等等, 換句話說, 你可以在這些元件上繪圖。

TCanvas 透過畫筆 (TPen) 和 畫刷 (TBrush) 兩個類別來進行繪圖。除此, 也可以直接透過 Pixels property 對畫布上的像素色彩值進行存取。

TCanvas provides an abstract drawing space for objects that must render their own images.
Hierarchy
TObject -> TPersistent -> TCanvas

Unit
Graphics

Description
Use TCanvas as a drawing surface for objects that draw an image of themselves. Standard window controls such as edit controls or list boxes do not require a canvas, as they are drawn by the system.

TCanvas provides properties, events and methods that assist in creating an image by
。Specifying the type of brush, pen and font to use.
。Drawing and filling a variety of shapes and lines.
。Writing text.
。Rendering graphic images.
。Enabling a response to changes in the current image.

TCanvas has two descendants, TControlCanvas and TMetafileCanvas, which assist in drawing images of controls and in creating metafile images for objects.

TColor type

TColor is used to specify the color of an object.
Unit
Graphics

enum TColor {clMin=-0x7fffffff-1, clMax=0x7fffffff};

Description
TColor is used to specify the color of an object. It is used by the Color property of many components and by a number of other properties that specify color values.

The Graphics unit contains definitions of useful constants for TColor. These constants map either directly to the closest matching color in the system palette (for example, clBlue maps to blue) or to the corresponding system screen element color defined in the Color section of the Windows Control panel (for example, clBtnFace maps to the system color for button faces).

If you specify TColor as a specific 4-byte hexadecimal number instead of using the constants defined in the Graphics unit, the low three bytes represent RGB color intensities for blue, green, and red, respectively. The value 0x00FF0000 represents full-intensity, pure blue, 0x0000FF00 is pure green, and 0x000000FF is pure red. 0x00000000 is black and 0x00FFFFFF is white.

If the highest-order byte is zero (0x00), the color obtained is the closest matching color in the system palette. If the highest-order byte is one (0x01), the color obtained is the closest matching color in the currently realized palette. If the highest-order byte is two (0x02), the value is matched with the nearest color in the logical palette of the current device context.
注意: TColor 本身已經是一個最底層的資料型態了, 本身是一個 enum 的型態, 長度為 4 個位元組(bytes) 的整數。

Friday, September 29, 2006

VFW: 取得視訊裝置驅動程式的資訊

任何一個電腦週邊硬體裝置安裝時, 作業系統必須要能與硬體裝置溝通, 我們把溝通媒介稱為驅動程式 ( device driver )。電腦與周邊裝置的溝通必需透過特定介面傳送資料, 傳送的資料也必須符合特定格式, 驅動程式可以認得傳送的資料為何, 就可以驅動硬體裝置執行電腦所派達的命令。

我們可以透過 capGetDriverDescription 這個函數, 讓應用程式知道你所使用的視訊裝置驅動程式相關資訊。如果你在 vfw.h 中搜尋, 你可以在 line 3618 找到底下這段定義與函數的宣告。

BOOL VFWAPI capGetDriverDescriptionA (UINT wDriverIndex,
LPSTR lpszName, int cbName,
LPSTR lpszVer, int cbVer);

BOOL VFWAPI capGetDriverDescriptionW (UINT wDriverIndex,
LPWSTR lpszName, int cbName,
LPWSTR lpszVer, int cbVer);

#ifdef UNICODE
#define capCreateCaptureWindow capCreateCaptureWindowW
#define capGetDriverDescription capGetDriverDescriptionW
#else
#define capCreateCaptureWindow capCreateCaptureWindowA
#define capGetDriverDescription capGetDriverDescriptionA
#endif
/* 說明:
1. 有關 #ifdef 的 C 前置處理的部份, 請參考 http://nknucc.nknu.edu.tw/~jwu/c/cpgch8.htm
2. capGetDriverDescriptionA 函數的傳回值為 BOOL ( 布林值, true or false ) , 傳入值一共有 5 個分別如下:
UINT wDriverIndex, 指定要取得的視訊裝置編號。( 你要先告訴人家要取得哪一個視訊裝置的相關資訊! )
LPSTR lpszName, 取得驅動程式的名稱後, 要儲存到哪一個字串給你知道呢?
( 注意: 這邊傳入的是這個字串的指標! )
int cbName, 指定存放驅動程式名稱的字串的大小。
LPSTR lpszVer, 取得驅動程式的版本後, 存放在這個字串中。
int cbVer, 指定存放驅動程式版本的字串的大小。
*/

範例程式:
long dwDriverIndex;
char szDeviceName[80]; // Driver Name
char szDeviceVersion[80]; // Driver Version

dwDriverIndex = 0;
if (capGetDriverDescription(dwDriverIndex, szDeviceName, sizeof(szDeviceName),
szDeviceVersion, sizeof(szDeviceVersion)))
{
lblCapDriverName->Caption = szDeviceName;
lblCapDriverVer->Caption = szDeviceVersion;
}

Thursday, September 28, 2006

VFW.H

Video For Windows ( VFW ) 是 Microsoft 於 1992 年所推出, 針對多媒體視訊的應用程式開發介面 ( Application Programming Interface , API )。只要本身有支援 VFW 的硬體裝置, 都可以透過 VFW SDK ( Software Development Kit ) 來控制, 並開發出有關音訊、視訊的多媒體處理軟體。

在 BCB 的目錄( C:\Program Files\Borland\CBuilder6\ ) 中, 你可以在 Include 子目錄裏找到 vfw.h 這個 header file, 當我們在 BCB 中要使用 VFW SDK 所提供的函數時, 就要將下面一行指令加入到程式的最前面。

#include <vfw.h>