2008年2月23日 星期六

講義 1.2 程式 & 提問 (二)

(接上文)

接著是把 Image 儲存到陣列的部分

 for(i=0;i<BitmapInfoHead.biHeight;++i)
 {
  ptr=(Byte*)Image1->Picture->Bitmap->ScanLine[i];
  for(k=0,j=0;j<BitmapInfoHead.biWidth;++j)
  {
   Source[i][j][0] = ptr[k+2];
   Source[i][j][1] = ptr[k+1];
   Source[i][j][2] = ptr[k];
   k+=3;
  }
 }

我在 compile 的時候,錯誤訊息都是在 Source[i][j][0] = ptr[k+2]; 這三行
內容是什麼我忘了
應該是因為型態的不同吧,我猜的
要研究一下 Byte 和 TBitmap 的內容是什麼才能知道
ptr 是 *Byte
Source 是 *Graphics::TBitmap


又或許是要另外宣告一個動態陣列來儲存而不是用 Source !?
我還沒試過

補充:
for loop 前面要先宣告 ptr,然後用動態配置 ptr 的長度
 Byte *ptr;
 ptr = new Byte [ Image1->Width*3 ];
寬度 x3是因為 Source[ ][ ][ ] 在這裡儲存的應該是 RGB
每次執行 ScanLine 函數都是讀取一整行的 RGB 值

至於 BitmapInfoHead.biHeight 和 BitmapInfoHead.biWidth
是經由宣告 BITMAPINFOHEADER 類別得到的
也就是如這一行程式碼
 BITMAPINFOHEADER BitmapInfoHead;
不過這樣還要去指定 BitmapInfoHead 的長寬
有點多此一舉的感覺, 所以在講義裡應該只是示意用
在 for loop 中用 Panel1->Width & Panel1->>Height
或是 Source->Width & Source->>Height 應該也可以
因為都是一樣的數值, 也就是會變成如下
 for(i=0;i<Source->>Height;++i)
 {
  ptr=(Byte*)Image1->Picture->Bitmap->ScanLine[i];
  for(k=0,j=0;j<Source->Width;++j)
  {
   Source[i][j][0] = ptr[k+2];
   Source[i][j][1] = ptr[k+1];
   Source[i][j][2] = ptr[k];
   k+=3;
  }
 }
不過這個部分我到現在還是沒 compile 過過


然後是第二個方法
先把單張擷取畫面儲存到 buffer 中再複製到剪貼簿裡,
然後再 assign 給 Image

在這裡要先引進剪貼簿的標頭檔
 #include <vcl\Clipbrd.hpp>
才能使用 Clipboard( ) 函數

一樣用個 button 然後丟進程式碼, 內容很短, 只有這樣
 capGrabFrameNoStop( hwndCapture );
 capEditCopy( hwndCapture );
 if( Clipboard()->HasFormat(CF_DIB) )
  Image1->Picture->Bitmap->Assign( Clipboard() );
就可以在 Image 中顯示擷取的圖片了

有個好玩的地方是,
當這裡的程式結束後,
開個小畫家按 Ctrl+V 也會在小畫家中顯示剛剛擷取到的圖片

沒有留言: