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

当您缩小位图图像时,您有几个选择。您可以以缓慢的方式“模糊和二次采样”全尺寸图像,以便在您有一个像素且源图像有 2+ 个像素的地方,新像素成为平均值。如果你不这样做,你会获得更快的性能,但你的图像不会像你想要的那样平滑。

StretchDIBits 可能在 2D 中平均像素,这意味着它从旧图像中查找 4+ 像素块以获得新像素的平均颜色。如果是这种情况,您可以编写自己的 1D 平均,仅对旧图像的相同扫描线的像素进行平均以获得新像素。Windows api 大师可能知道 DrawDIBDraw 的一个很酷的选项,它可以执行类似的操作。

于 2009-07-13T03:07:59.290 回答
-1

如果您不想使用 opengl/directx/gdi+ 但被困在 DIB 中,我发现最快的方法就是自己动手。

唯一的问题是您需要访问图像的实际字节。此外,目标需要是一个 DIBbitmap,因为这需要被 blitted(而不是 stretchblitted)到您的 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

我不知道您在应用程序中还做了什么,也不知道绘制拉伸位图对您有多重要,但您可能只想使用更现代的 API,如 GDI+ 或 DirectX 或 OpenGL。

自 1995 年左右以来,没有人改变过 StretchDIBits 或 DrawDibDraw 的工作方式——你真的想要一些可以利用 GPU 的东西。(我原以为即使使用 CPU 绘图也会“足够快”,只是因为处理器比当时快得多,但显然不是。)

于 2009-07-21T20:58:22.680 回答