線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2879
推到 Plurk!
推到 Facebook!

請教一個關於TBitmap神秘的問題

尚未結案
yuwenyang
一般會員


發表:1
回覆:5
積分:1
註冊:2003-04-04

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-04-04 00:14:49 IP:218.166.xxx.xxx 未訂閱
這是將一張存在IMatrixGray二維陣列中的圖片放到Image2..只要一按 Buttom1就會執行..執行結果也很好..但是我發現只要我按三次以上這按鈕. setbitmapbit就會出錯..後來我把delete pBitmap拿掉就可以解決這問題.. 可是這樣似乎會導致記憶體一直無法被釋放..這問題該怎麼解決呢? 請板上高手幫忙一下..謝謝. :) -- void __fastcall TForm1::Button1Click(TObject *Sender) {    //Graphics::TBitmap *pBitmap = new Graphics::TBitmap();    Graphics::TBitmap *pBitmap = new Graphics::TBitmap();    pBitmap->Height = ImageHeight;    pBitmap->Width = ImageWidth;    pBitmap->PixelFormat = pf24bit;    Byte *temp;    Byte *bmbuf = new Byte[ImageHeight * ImageWidth *3];       for (i=0;iPosition ; } bmbuf -= ImageHeight * ImageWidth * 3 ; if (SetBitmapBits(pBitmap->Handle, ImageHeight * ImageWidth * 3, bmbuf) == 0) ShowMessage("Wrong"); Image2->Visible = true; Image2->Picture->Assign(pBitmap); ProgressBar1->Position =0; delete[] bmbuf; delete pBitmap; // 就是神秘的這一行!! }
integrand
一般會員


發表:8
回覆:27
積分:17
註冊:2002-10-22

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-04-04 00:52:19 IP:218.163.xxx.xxx 未訂閱
你的程式沒貼好    為什麼有這行 bmbuf -= ImageHeight * ImageWidth * 3 ; 第一次看到這種指標減法 不知道這樣合法嗎?    我跑了一下 錯的好像是這行 delete[] bmbuf;    ~剩下的就交給帥氣了~
yuwenyang
一般會員


發表:1
回覆:5
積分:1
註冊:2003-04-04

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-04-04 01:45:38 IP:218.166.xxx.xxx 未訂閱
用Draw死的更快...按第二次就掛了... >"< 這兩天快被setbitmapbits搞死了.. :~ 請板上高手指導一下. :)
yuwenyang
一般會員


發表:1
回覆:5
積分:1
註冊:2003-04-04

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-04-04 01:56:57 IP:218.166.xxx.xxx 未訂閱
引言: 你的程式沒貼好 為什麼有這行 bmbuf -= ImageHeight * ImageWidth * 3 ; 第一次看到這種指標減法 不知道這樣合法嗎? 我跑了一下 錯的好像是這行 delete[] bmbuf; ~剩下的就交給帥氣了~
這行我試沒問題阿.. >"< 如果只按一次沒問題..超過三次就掛.. 完全不知道發生什麼事情.. >"< Btw,我把回圈的部分同貼一次..
   for (i=0;i<ImageHeight;i  ){
      for (j=0;j<ImageWidth;j  ,bmbuf =3){
        *(bmbuf 2) = IMatrixGray[i][j];
        *(bmbuf 1) = IMatrixGray[i][j];
        *(bmbuf)= IMatrixGray[i][j];
      }
      ProgressBar1->Position  ;
   }
   bmbuf -= ImageHeight * ImageWidth * 3 ;
bmbuf應該沒問題吧?..我快風了 :~
yuwenyang
一般會員


發表:1
回覆:5
積分:1
註冊:2003-04-04

發送簡訊給我
#5 引用回覆 回覆 發表時間:2003-04-04 02:01:39 IP:218.166.xxx.xxx 未訂閱
引言: 這是將一張存在IMatrixGray二維陣列中的圖片放到Image2..只要一按 Buttom1就會執行..執行結果也很好..但是我發現只要我按三次以上這按鈕. setbitmapbit就會出錯..後來我把delete pBitmap拿掉就可以解決這問題.. 可是這樣似乎會導致記憶體一直無法被釋放..這問題該怎麼解決呢? 請板上高手幫忙一下..謝謝. :) --
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   //Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
   Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
   pBitmap->Height = ImageHeight;
   pBitmap->Width = ImageWidth;
   pBitmap->PixelFormat = pf24bit;
   Byte *temp;
   Byte *bmbuf = new Byte[ImageHeight * ImageWidth *3];       for (i=0;i〈ImageHeight;i  ){
      for (j=0;j〈ImageWidth;j  ,bmbuf =3){
        *(bmbuf 2) = IMatrixGray[i][j];
        *(bmbuf 1) = IMatrixGray[i][j];
        *(bmbuf)= IMatrixGray[i][j];
      }
      ProgressBar1->Position  ;
   }
   bmbuf -= ImageHeight * ImageWidth * 3 ;
   if (SetBitmapBits(pBitmap->Handle, ImageHeight * ImageWidth * 3, bmbuf) == 0)
        ShowMessage("Wrong");
   Image2->Visible = true;
   Image2->Picture->Assign(pBitmap);
   ProgressBar1->Position =0;
   delete[] bmbuf;
   delete pBitmap;  // 就是神秘的這一行!!
}
發表人 - yuwenyang 於 2003/04/04 01:58:39
我說詳盡點..就是整個程式可以執行..結果也很正確..但是只要我按超過三次. setbitmapbits就會神秘的失效..出現"Worng" (我debug用)..然後image2 就變成一片空白..我已經不知道該怎麼辦了..請板上高手們幫幫忙.. p.s.如果需要我的完整source code請mail給我. :)
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#6 引用回覆 回覆 發表時間:2003-04-04 13:02:39 IP:61.231.xxx.xxx 未訂閱
我也來測試一下:
// 請您新增個 Application,加入兩個TButton 一個 TEdit 一個 TImage,並指示好如下的事件:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  Image1->Width=Edit1->Text.ToIntDef(499);
  int ImageHeight=Image1->Height;
  int ImageWidth=Image1->Width;
  Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
  pBitmap->Height = ImageHeight;
  pBitmap->Width = ImageWidth;
  pBitmap->PixelFormat = pf24bit;
  Byte *bmbuf = new Byte[ImageHeight * ImageWidth *3];
  for (int i=0;i<ImageHeight;i  )
  {
    for (int j=0;j<ImageWidth;j  ,bmbuf =3)
    {
      *(bmbuf 2) = i j;    // IMatrixGray[i][j];
      *(bmbuf 1) = 4*i j;  // IMatrixGray[i][j];
      *(bmbuf)   = 4*j i;  // IMatrixGray[i][j];
    }
  }
  bmbuf -= ImageHeight * ImageWidth * 3 ;
  if (SetBitmapBits(pBitmap->Handle, ImageHeight * ImageWidth * 3, bmbuf) == 0)
  { // 我的測試,會有錯的是這個 SetBitmapBits()!!
    ShowMessage("Wrong");
  }
  Image1->Visible = true;
  Image1->Picture->Assign(pBitmap);
  delete[] bmbuf;
  delete pBitmap;
}
//----------------------------------------------------------------------------//
void __fastcall TForm1::Button2Click(TObject *Sender)
{
  Image1->Width=Edit1->Text.ToIntDef(499);
  int ImageHeight=Image1->Height;
  int ImageWidth=Image1->Width;
  Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
  pBitmap->Height = ImageHeight;
  pBitmap->Width = ImageWidth;
  pBitmap->PixelFormat = pf24bit;
  for (int i=0;i<ImageHeight;i  )
  {
    for (int j=0;j<ImageWidth;j  )
    {
      ((Byte*)pBitmap->ScanLine[i])[j*3 2]=i j;    // IMatrixGray[i][j];
      ((Byte*)pBitmap->ScanLine[i])[j*3 1]=4*i j;  // IMatrixGray[i][j];
      ((Byte*)pBitmap->ScanLine[i])[j*3]  =4*j i;  // IMatrixGray[i][j];
    }
  }
  Image1->Visible = true;
  Image1->Picture->Assign(pBitmap);
  delete pBitmap;
}
//----------------------------------------------------------------------------//
void __fastcall TForm1::Edit1Exit(TObject *Sender)
{
  int Value=Edit1->Text.ToIntDef(499);
  Edit1->Text=IntToStr(Value);
}
//----------------------------------------------------------------------------//
測試的結果, delete 並不會有問題,而有問題的是 SetBitmapBits() 這個 API。在我的電腦,約三次會有一次到兩次不成功,即秀出 Wrong。 改成 Button2 的 Scanline 的方式,則不會有任何的問題。 但我發現使用 Scanline 的處理顯示速度沒有 SetBitmapBits() 的方式快。 不過,按 BCB5 所附的 MSHelp 中提到 SetBitmapBits() 是舊的方法,最好不要使用,而且在以上的 code 中,我故意將 ImageWidth 設為 499 時,發現 SetBitmapBits() 與 Scanline[] 的結果不同,而很明顯可以看出是 SetBitmapBits() 錯誤!!而寬度為 512 時,則相同,表示 SetBitmapBits 只適用於 Width 是 8 的倍數,或是有一定的限制。除非您的應用中,可以很確定 SetBitmapBits() 不會有問題,否則最好別用。 我很佩服您指標的寫法,不過,建議您儘量不要改 new 出來的指標,否則到時可能 delete 不回去! 如您原來的 code 那個 temp 可以那來運算用:
Byte *bmbuf = new Byte[ImageHeight * ImageWidth *3];
Byte *temp=bmbuf;
for (i=0;i<ImageHeight;i  )
{      
  for (j=0;j<ImageWidth;j  ,temp =3)
  {        
    *(temp 2) = IMatrixGray[i][j];        
    *(temp 1) = IMatrixGray[i][j];        
    *(temp)= IMatrixGray[i][j];      
  }      
  ProgressBar1->Position  ;   
}
if (SetBitmapBits(pBitmap->Handle, ImageHeight * ImageWidth * 3, bmbuf) == 0)
...
delete[] bmbuf;
...
這樣,就不會有人被 bmbuf -= ImageHeight * ImageWidth * 3; 嚇到。 沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://big5.to/吃軟也吃硬 http://coolsite.to/ushells 介紹Shells,LiteStep,GeoShell.... 發表人 - dllee 於 2003/04/04 13:05:59
------
http://www.ViewMove.com
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#7 引用回覆 回覆 發表時間:2003-04-04 13:33:11 IP:61.231.xxx.xxx 未訂閱
對了,我忘了提到,我在測試時,把 delete pBitmap; 刪掉,但執行時,還是會發生 SetBitmapBits() 的錯誤,與有 delete 只是機率上的不同而已,都是會有問題的。    沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://big5.to/吃軟也吃硬 http://coolsite.to/ushells 介紹Shells,LiteStep,GeoShell....
------
http://www.ViewMove.com
yuwenyang
一般會員


發表:1
回覆:5
積分:1
註冊:2003-04-04

發送簡訊給我
#8 引用回覆 回覆 發表時間:2003-04-05 00:56:05 IP:218.166.xxx.xxx 未訂閱
引言: 但我發現使用 Scanline 的處理顯示速度沒有 SetBitmapBits() 的方式快。 不過,按 BCB5 所附的 MSHelp 中提到 SetBitmapBits() 是舊的方法,最好不要使用,而且在以上的 code 中,我故意將 ImageWidth 設為 499 時,發現 SetBitmapBits() 與 Scanline[] 的結果不同,而很明顯可以看出是 SetBitmapBits() 錯誤!!而寬度為 512 時,則相同,表示 SetBitmapBits 只適用於 Width 是 8 的倍數,或是有一定的限制。除非您的應用中,可以很確定 SetBitmapBits() 不會有問題,否則最好別用。 這樣,就不會有人被 bmbuf -= ImageHeight * ImageWidth * 3; 嚇到。 沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://big5.to/吃軟也吃硬 http://coolsite.to/ushells 介紹Shells,LiteStep,GeoShell.... 發表人 - dllee 於 2003/04/04 13:05:59
這位高手您好,小的我目前先暫時先用Scanline來解決..當初就是因為scanline 速度不夠快才改用setbitmapbits.我查了一下Help檔,他建議在Win32-Based的 application改用SetDIBits,於是參考了一下SetDIBits如下:
The SetDIBits function sets the pixels in a bitmap using the color 
data found in the specified device-independent bitmap (DIB).     int SetDIBits(        HDC hdc,        // handle of device context 
    HBITMAP hbmp,        // handle of bitmap 
    UINT uStartScan,        // starting scan line 
    UINT cScanLines,        // number of scan lines 
    CONST VOID *lpvBits,        // array of bitmap bits 
    CONST BITMAPINFO *lpbmi,        // address of structure with bitmap data 
    UINT fuColorUse         // type of color indices to use 
   );        
     Parameters    hdc    Identifies a device context.     hbmp    Identifies the bitmap that is to be altered using the color data from 
the specified DIB.     uStartScan    Specifies the starting scan line for the device-independent color data in the array pointed to by the lpvBits parameter.     cScanLines    Specifies the number of scan lines found in the array containing 
device-independent color data.     lpvBits    Points to the DIB color data, stored as an array of bytes. The format 
of the bitmap values depends on the biBitCount member of the 
BITMAPINFO structure pointed to by the lpbmi parameter.     lpbmi    Points to a BITMAPINFO data structure that contains information about the DIB.    fuColorUse    Specifies whether the bmiColors member of the BITMAPINFO structure 
was provided and, if so, whether bmiColors contains explicit red, 
green, blue (RGB) values or palette indices. The fuColorUse parameter 
must be one of the following values:     Value        Meaning
DIB_PAL_COLORS        The color table consists of an array of 16-bit
 indices into the logical palette of the device context identified by 
the hdc parameter.
DIB_RGB_COLORS        The color table is provided and contains literal 
RGB values.    Return Values    If the function succeeds, the return value is the number of scan lines copied.
If the function fails, the return value is zero. 
想請教一下,如果以我的情況,能改用此函數嗎?如果能,又應該怎麼寫呢? 我想做的是把一個unsigned char的二維陣列IMatrixGray放到Image2裡面, 懇請大大賜教,我試了很多次都不成功.. >"< 再次感謝. :)
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#9 引用回覆 回覆 發表時間:2003-04-05 18:04:17 IP:203.204.xxx.xxx 未訂閱
說真的,我自己沒有用過,找一下只有 Delphi 的 Example Code 的連結: http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20091673.html http://homepages.borland.com/efg2lab/Library/UseNet/2002/0114.txt 如果還有問題,再提吧。 沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://big5.to/吃軟也吃硬 http://coolsite.to/ushells 介紹Shells,LiteStep,GeoShell....
------
http://www.ViewMove.com
yuwenyang
一般會員


發表:1
回覆:5
積分:1
註冊:2003-04-04

發送簡訊給我
#10 引用回覆 回覆 發表時間:2003-04-05 23:34:28 IP:218.166.xxx.xxx 未訂閱
問題解決了~~po上來跟板上高手們分享一下. :) Btw,困擾我五天的問題終於搞定了 :~~~~~~~~~~~~~~
void __fastcall TForm1::Gray1Click(TObject *Sender)
{
        BITMAPINFOHEADER bmih = {
          sizeof(BITMAPINFOHEADER), // biSize
          ImageWidth,            // biWidth
          -1 *ImageHeight,           // biHeight, *** note this is top-down ***
          1,                        // biPlanes
          24,                       // biBitCount
          BI_RGB,                   // biCompression
          0,                        // biSizeImage (not reqd. in this case)
          0,                        // biXPelsPerMeter (not reqd.)
          0,                        // biYPelsPerMeter (not reqd.)
          0,                        // biClrUsed
          0                         // biClrImportant
          };
        RGBQUAD rgb0 = {0,0,0,0};
        BITMAPINFO bmi;
        bmi.bmiHeader = bmih;
        bmi.bmiColors[0] = rgb0;    // no palette
        // Create array of BYTE to hold 24 bit rgb values
        int RowSize = ((((ImageWidth   1) * 3) / 4) * 4);
                                    // round up each row to 4 byte boundary
        BYTE *Bits = new BYTE[RowSize * ImageHeight];
        BYTE *BitsPtr;
        for (int y=0; y〈ImageHeight; y  ){
          BitsPtr = Bits   (RowSize * y);
          for (int x=0; x〈ImageWidth; x  ){
            *BitsPtr   = (BYTE)IMatrixGray[y][x];   // Blue 'noise'
            *BitsPtr   = (BYTE)IMatrixGray[y][x];   // Green
            *BitsPtr   = (BYTE)IMatrixGray[y][x];   // Red
            }
          }
        Image2->Picture->Bitmap->Width = ImageWidth;
        Image2->Picture->Bitmap->Height = ImageWidth;
        HBITMAP hbmp = Image2->Picture->Bitmap->Handle;
        HDC hdc = Image2->Canvas->Handle;
        SetDIBits (
          hdc,
          hbmp,
          0,
          ImageHeight,
          Bits,
          &bmi,
          DIB_RGB_COLORS
        );
        delete[] Bits;
        Image2->Visible = true;
        Image2->Repaint();    }
系統時間:2024-05-03 9:14:23
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!