GDI+ image scaling issue

I have an application which draws background from some bitmap using gdi+. Some of bitmaps are vertical non-linear gradients (eg they are 1 pixel wide and should be stretched horizontally to fill whole control width). The problem is that with small images (like described above), some control area on the right is not painted.

I've written a test program that scales a 1x1 image to different sizes, and it shows that issue occurs when scale factor is big enough

void Draw(HDC hDestDC, int destleft, int desttop, int destwidth, int destheight)
{
    COLORREF buffer[] = {0xFF0000FF }; // 1 pixel image
    const int width = 1, height = 1;
    Gdiplus::Bitmap gdipBitmap(width, height, 4*width, PixelFormat32bppARGB, (BYTE*)buffer);

    Gdiplus::ImageAttributes attrs;
    Gdiplus::Rect dest(destleft, desttop, destwidth, destheight);

    Gdiplus::Graphics graphics(hDestDC);
    graphics.SetInterpolationMode(Gdiplus::InterpolationModeNearestNeighbor);
    graphics.SetPixelOffsetMode(Gdiplus::PixelOffsetModeHalf);

    graphics.DrawImage(&gdipBitmap, dest, 0, 0, width, height, Gdiplus::UnitPixel, &attrs);
}

// OnPaint:
for(int i=0; i<800; ++i)
    Draw(hdc, 0, i, i, 1); // scale 1x1 image to different width

I would exptect this test to draw a smooth 'triangle', but instead lines do not have size exactly as specified by destination rect: http://i.imgur.com/NNpMvmW.png

Is there any way to fix this behavior? I need to output bitmap with size exactly as specified (considering source image alpha-channel and no interpolation with background on the edges).

PS: I have to use GDI+ because actual code uses some ImageAttributes provided by gdiplus.


Ok, so I just ended up trying all possible values for different options and finally found ones suitable for me.

SetSmoothingMode (as suggested by Na Na) didn't have any visual effect on the image.

However SetInterpolationMode(InterpolationModeBilinear) (or better) produces exact image size, but it also interpolates image edges with background. The result looks like this, which doesn't suit my requirements.

Finally, setting ImageAttibute 's WrapMode option does the trick:

attrs.SetWrapMode(Gdiplus::WrapModeTileFlipXY);

The result is exactly what I wanted: http://i.imgur.com/rYKwAmZ.png

Summary:

Using InterpolationModeNearestNeighbor and default WrapMode results in inaccurate rendered image size. To avoid this, set WrapModeTileFlipXY => Other options (like InterpolationMode ) can have any desirable value without influence on the rendered image size.


Have you tried this?

Anti-aliasing smoothing method might help.

链接地址: http://www.djcxy.com/p/50312.html

上一篇: 如何在double中使用wxGLCanvas

下一篇: GDI +图像缩放问题