1

私は c++、gdi でコーディングしています。stretchDIBits を使用してイメージを DC に描画します。

        ::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 モードで描画した場合と同じです。描画品質を向上させるにはどうすればよいですか?

4

4 に答える 4

2

DrawDibDraw は時代遅れです。

StretchDIBits を高速化しようと考えたことはありますか? ここに良い答えがあります

もちろん、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;

その後、次のようにビットマップをレンダリングできます。

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 );

もちろん、blt するたびに互換性のある DC を実際に作成する必要がないことを心に留めておく価値があります。これにより、処理が大幅に高速化されます。互換性のある DC を作成し、イメージをロードするときにビットマップ オブジェクトを選択するだけです。次に、必要になるまで保持します。シャットダウン時には、上記のように単純に DeleteObject を実行します。

于 2009-07-17T10:43:31.100 に答える
0

ビットマップ画像を縮小する場合、いくつかの選択肢があります。フルサイズの画像を「ぼかしてサブサンプリング」するというゆっくりとした方法で、1つのピクセルがあり、ソース画像に2つ以上のピクセルがある場所で、新しいピクセルが平均になるようにすることができます。そうしないと、パフォーマンスが大幅に向上しますが、画像は思ったほど滑らかになりません。

StretchDIBitsは、2Dでピクセルを平均化している可能性があります。つまり、古い画像から4+ピクセルのブロックを探して、新しいピクセルの平均色を取得します。その場合は、古い画像と同じスキャンラインのピクセルを平均して新しいピクセルを取得する独自の1D平均を作成できます。Windows APIの第一人者は、このようなことを行うDrawDIBDrawのクールなオプションを知っているかもしれません。

于 2009-07-13T03:07:59.290 に答える
-1

opengl/directx/gdi+ を使用したくないが、DIB でスタックしている場合は、自分で行うのが最も速いことがわかりました。

唯一のことは、画像の実際のバイトにアクセスする必要があることです。さらに、宛先は DIBbitmap である必要があります。これは、Windows フォームにブリットする (ストレッチブリットではなく) 必要があるためです。

したがって、2バイトのポインター、1つのsrcと1つのdestがあるとします。どちらも rawbytes (各ピクセルは 3 バイト (RGB) で構成されます) を指している場合、アルゴリズムは次のようになります

 //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 を使用してください。

psああそうです..コードは私の頭のてっぺんから外れているので、小さなタイプミスに注意してください

于 2009-07-23T12:22:41.437 に答える
-2

アプリで他に何をしているのか、またはストレッチされたビットマップの描画がどれほど重要かはわかりませんが、GDI+、DirectX、OpenGL などの最新の API を使用したいだけかもしれません。

1995 年以降、StretchDIBits や DrawDibDraw の動作を変更した人は誰もいません。GPU を利用する何かが本当に必要です。(プロセッサが当時よりもはるかに高速であるという理由だけで、CPU を使用しても描画が「十分に高速」になると予想していましたが、明らかにそうではありません。)

于 2009-07-21T20:58:22.680 に答える