【问题标题】:Drawing PixelFormat32bppPARGB images with GDI+ uses conventional formula instead of premultiplied one使用 GDI+ 绘制 PixelFormat32bppPARGB 图像使用常规公式而不是预乘公式
【发布时间】:2013-11-06 10:24:37
【问题描述】:

这里有一些显示问题的最小代码:

static const int MAX_WIDTH = 320;
static const int MAX_HEIGHT = 320;

Gdiplus::Bitmap foregroundImg(MAX_WIDTH,MAX_HEIGHT,PixelFormat32bppPARGB);
{
    Gdiplus::Graphics g(&foregroundImg);
    g.Clear(Gdiplus::Color(10,255,255,255));
}

Gdiplus::Bitmap softwareBitmap(MAX_WIDTH,MAX_HEIGHT,PixelFormat32bppPARGB);
Gdiplus::Graphics g(&softwareBitmap);
g.SetCompositingMode(Gdiplus::CompositingModeSourceOver);
g.SetCompositingQuality(Gdiplus::CompositingQualityDefault);

g.Clear(Gdiplus::Color(255,0,0,0));

g.DrawImage(foregroundImg,0,0);

CLSID encoder;
GetEncoderClsid(L"image/png",&encoder);
softwareBitmap.Save(L"d:\\image.png",&encoder);

结果我得到的图像填充的 RGB 值等于10。看来 GDI+ 使用的是常规算法:

255*(10/255) + 0*(1-10/255) == 10。

但我希望会使用预乘算法(因为前景图像具有预乘PixelFormat32bppPARGB 格式):

255 + 0*(1-10/255) == 255

所以我的问题是,当图像为预乘 alpha 格式时,为什么 GDI+ 使用传统公式?是否有任何解决方法可以让 GDI+ 使用预乘 alpha 算法?

【问题讨论】:

  • 源位图和目标位图都是 PARGB。因此无需更改像素,您将获得foregroundImg 的精确副本。
  • 不,我没有得到前景图像的副本。我得到的图像充满了 ARGB(255,10,10,10),这正是传统算法产生的。顺便说一句,我尝试了各种背景格式,但结果总是一样

标签: windows gdi+


【解决方案1】:

前景图像的格式无关紧要(假设它具有 alpha),因为您将其设置为 Gdiplus::Color。颜色值被定义为非预乘,因此 gdiplus 在清除前景图像时将分量乘以 alpha 值。另一种方法是让颜色值根据渲染目标的格式具有不同的含义,这种方式很疯狂。

您可能可以通过直接设置源图像位来执行您想要的操作,或者您可能不会。值大于 100% 的组件在 gdiplus 的渲染模型中并不是真正有效的,所以如果它在渲染期间限制它们,我不会感到惊讶。如果您真的想要对渲染进行这种级别的控制,则必须锁定位图位并自己完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 2021-11-09
    • 2022-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多