【问题标题】:GDI+ image scaling issueGDI+ 图像缩放问题
【发布时间】:2013-09-09 17:04:38
【问题描述】:

我有一个使用 gdi+ 从位图绘制背景的应用程序。一些位图是垂直的非线性渐变(例如,它们是 1 像素宽,应该水平拉伸以填充整个控件宽度)。 问题是对于小图像(如上所述),右侧的某些控制区域未绘制。

我编写了一个将 1x1 图像缩放到不同尺寸的测试程序,它表明当比例因子足够大时会出现问题

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

我希望这个测试能够绘制一个平滑的“三角形”,但线条的大小完全与目标矩形指定的不同: http://i.imgur.com/NNpMvmW.png

有没有办法解决这个问题?我需要输出与指定大小完全相同的位图(考虑源图像 alpha 通道和边缘上没有带背景的插值)。

P.S:我必须使用 GDI+,因为实际代码使用了 gdiplus 提供的一些 ImageAttributes。

【问题讨论】:

  • 我看到了同样的问题,当目标图像尺寸是原始尺寸的 1% 左右时,GDI+ 缩放方法会创建损坏的图像。

标签: c++ image bitmap gdi+ scaling


【解决方案1】:

好的,所以我最终尝试了不同选项的所有可能值,最后找到了适合我的值。

SetSmoothingMode(由娜娜建议)对图像没有任何视觉效果。

但是SetInterpolationMode(InterpolationModeBilinear)(或更好)会产生精确的图像大小,但它也会用背景插入图像边缘。结果看起来像this,不符合我的要求。

最后,设置ImageAttibute 的WrapMode 选项就可以了:

attrs.SetWrapMode(Gdiplus::WrapModeTileFlipXY);

结果正是我想要的:http://i.imgur.com/rYKwAmZ.png

总结:

使用InterpolationModeNearestNeighbor 和默认WrapMode会导致渲染图像大小不准确。为避免这种情况,请设置 WrapModeTileFlipXY => 其他选项(如 InterpolationMode)可以具有任何所需的值,而不会影响渲染图像的大小。

【讨论】:

    【解决方案2】:

    你试过this吗?

    抗锯齿平滑方法可能会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-18
      • 2011-09-22
      • 2012-08-25
      • 2017-12-28
      • 1970-01-01
      相关资源
      最近更新 更多