2009-07-13 16 views
1

私はC++、gdiでコーディングしています 私はstretchDIBitsを使用してイメージをDCに描画します。DrawDIBの品質を向上させる方法は?

 ::SetStretchBltMode(hDC, HALFTONE); 
     ::StretchDIBits(
      hDC, 
      des.left,des.top,des.right - des.left,des.bottom - des.top, 
      0, 0, 
      img.getWidth(), 
      img.getHeight(), 
      (img.accessPixels()), 
      (img.getInfo()), 
      DIB_RGB_COLORS, 
      SRCCOPY 
      ); 

しかし、それは遅いです。 私はDrawDib関数を使うように変更しました。

::SetStretchBltMode(hDC, HALFTONE); 
DrawDibDraw(
         hdd, 
         hDC, 
         des.left,des.top,des.right - des.left,des.bottom - des.top, 
         (LPBITMAPINFOHEADER)(img.getInfo()), 
         (img.accessPixels()), 
         0, 0, 
         img.getWidth(), 
         img.getHeight(), 
         DDF_HALFTONE 
         ); 

ただし、結果はCOLORONCOLORモードによる描画と同じです。 描画品質を改善するにはどうすればよいですか?

+2

'DrawDib'はかなり古くなっています。あまりにも遅いということを説明できますか?リアルタイムビデオでこれをしようとしていますか?それを非常に大きな画像に適用しようとしていますか?どのくらいの時間がかかりますか、どのくらい速くする必要がありますか? –

答えて

0

ビットマップイメージを縮小すると、いくつかの選択肢があります。フルサイズの画像を「ぼかしてサブサンプルする」と、ゆっくりしたやり方で、1つのピクセルとソースイメージのある場所に2以上のピクセルがあり、新しいピクセルが平均となります。あなたがそれをしないと、あなたはもっと速く演技することができますが、あなたのイメージはあなたが望むほど滑らかではありません。

StretchDIBitsは2Dのピクセルを平均化することがあります。つまり、古い画像から4+ピクセルブロックを探して新しいピクセルの平均色を取得します。そうであれば、新しいピクセルを得るために古い画像の同じ走査線を平均化する独自の1D平均を書くことができます。 Windowsのapiの達人は、このようなことをするDrawDIBDrawのクールなオプションを知っているかもしれません。

2

よくDrawDibDrawは古くなっています。

あなたはStretchDIBitsのスピードアップを検討しましたか?良い答えがありますhere

もちろん、StretchDIBitsを一切使わずに行うこともできます。

あなたが最初に

hBitmap = LoadImage(NULL, _T("c:\\Path\File.bmp"), IMAGE_BITMAP, LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_LOADFROMFILE); 

SIZE size; 
BITMAP bmp; 
GetObject((HGDIOBJ)hBitmap, sizeof(BITMAP), &bmp); 
size.cx = bmp.bmWidth; 
size.cy = bmp.bmHeight; 

して画像を読み込む場合は、次のようにあなたは、その後、ビットマップをレンダリングすることができます。あなたが実際に互換性のDCにかなり物事をスピードアップしますあなたはBLTするたびに作成する必要はありません念頭にその価値はもちろん

HDC hBitmapDC = CreateCompatibleDC(hDC); 

HGDIOBJ hOld = SelectObject(hBitmapDC, (HGDIOBJ)hBitmap); 

SetStretchBltMode(hDc, HALFTONE); 

StretchBlt(hDC, rcItem.left,rcItem.top, rcItem.right,rcItem.bottom, hBitmapDC, 0, 0, size.cx, size.cy, SRCCOPY); 

SelectObject(hBitmapDC, hOld); 
DeleteObject(hBitmapDC); 

。互換性のあるDCを作成し、イメージをロードするときにビットマップオブジェクトを選択するだけです。それが必要になるまでそれを保持します。上記のように、単にシャットダウン時にDeleteObjectを実行します。

+0

ありがとうございました。画像が大きすぎない場合は、良い解決策です。 Videocardに十分なメモリがない場合、CompatibleDCはVideocardのメモリを占有しているためです。この方法は動作しません – user25749

-2

あなたのアプリで何をやっているのか、図面の伸ばしたビットマップがどれほど重要かわかりませんが、GDI +やDirectX、OpenGLなどの最新のAPIを使いたいかもしれません。

1995年以降、StretchDIBitsやDrawDibDrawがどのように機能するかは変わっていません。本当にGPUを利用するものが本当に必要です。 (私は、CPUがあっても描画速度が十分に速いと予想していたのは、当時のプロセッサよりもはるかに高速だったが、明らかにそうではなかったからだ。)

-1

OpenGL/directx/gdi +がDIBに固執していますが、私は最も速いのが自分でやっていることがわかりました。

画像の実際のバイトにアクセスする必要があります。さらに、宛先はDIBbitmapである必要があります。これは、あなたのウィンドウのフォームにblit(伸長されていない)する必要があるためです。

あなたは2バイトのポインタ、1 srcと1 destを持っているとします。どちらも(各ピクセルは3バイト(RGB)からなる)RAWBYTESを指すが、その後、あなたのアルゴリズムは、この

//these need to be filled out by you 
//byte *src; //points to the first raw byte of your source RGB picture 
//byte *dest; //points to the first raw byte of your destination RGB picture 
//int srcWidth = 640; //width of original image 
//int srcHeight = 480; //height of original image 
//int destWidth = 200; //width of destination image 
//int destHeight = 100; //height of destination image 


void scaleImage(byte *src, byte*dest, int srcWidth, int srcHeight, int destWidth, int destHeight) 
{ 
     //these are internal counters 
     register int srcx; 
     register int srcy; 
     register int skipx; 
     register int skipy; 

     skipx = (destWidth>>8)/srcWidth; 
     skipy = (destHeight>>8)/srcHeight; 

     for(int y=0; y<destHeight; y++) 
     { 
      //calc from which y coord we need to copy pixel 
      register byte *src2 = src + ((srcy>>8)*srcWidth*3); 

      for(int x=0; x<destWidth; x++) 
      { 
       //calc from which x coord we need to copy pixel 
       register byte *src3 = src2 + ((srcx>>8)*3); 

       //copy rgb 
       *dest++ = *src3++; 
       *dest++ = *src3++; 
       *dest++ = *src3++; 

       //go to next x pixel 
       srcx += skipx; 
      } 

      //go to next y pixel 
      srcy += skipy; 
     } 
} 

のようになります。あなたは、コードを散在見る>> 8と< < 8 'を使用することです固定小数点 'です。

スケーリングをより良くするには(このスケールは「最近隣」を使用して行われるため)、隣接する右ピクセル、隣接下端ピクセル、および隣接する右下ピクセルの平均値を取る必要があります。 ディビジョン( '/')は使用しないでくださいが、もっと速い>> 2を使用してください。

p.s.ああ、コードは頭の上から外れているので、小さなタイプミスに気をつけてください。

関連する問題