将 alpha 值添加到双线性调整大小算法
因此,我尝试采用双线性插值算法来调整图像大小并添加 alpha 值。 我正在使用 Actionscript 3 来执行此操作,但我并不认为该语言是相关的。
我下面的代码实际上工作得很好,但“擦除”区域周围的边缘似乎变得更暗。 有没有一种简单的方法可以让它在找到平均值时不包含我只能假设为黑色(0x00000000)的内容?
代码:
x_ratio = theX - x;
y_ratio = theY - y;
x_opposite = 1 - x_ratio;
y_opposite = 1 - y_ratio;
a = getPixel32(x, y);
be =getPixel32(x + 1, y);
c = getPixel32(x, y + 1);
d = getPixel32(x + 1, y + 1);
alph = (t(a) * x_opposite + t(be) * x_ratio) * y_opposite + (t(c) * x_opposite + t(d) * x_ratio) * y_ratio;
red = (r(a) * x_opposite + r(be) * x_ratio) * y_opposite + (r(c) * x_opposite + r(d) * x_ratio) * y_ratio;
green = (g(a) * x_opposite + g(be) * x_ratio) * y_opposite + (g(c) * x_opposite + g(d) * x_ratio) * y_ratio;
blue = (b(a) * x_opposite + b(be) * x_ratio) * y_opposite + (b(c) * x_opposite + b(d) * x_ratio) * y_ratio;
效果图片: http://beta.shinyhammer.com/images/site /eraser_pixelborders.jpg
发布解决方案代码!
a = getPixel32(x, y);
be =getPixel32(x + 1, y);
c = getPixel32(x, y + 1);
d = getPixel32(x + 1, y + 1);
asum = (t(a) + t(be) + t(c) + t(d)) / 4;
alph = (t(a) * x_opposite + t(be) * x_ratio) * y_opposite + (t(c) * x_opposite + t(d) * x_ratio) * y_ratio;
red = ((r(a) * t(a) * x_opposite + r(be) * t(be) * x_ratio) * y_opposite + (r(c) * t(c) * x_opposite + r(d) * t(d) * x_ratio) * y_ratio);
red = (asum > 0) ? red / asum : 0;
green = ((g(a) * t(a) * x_opposite + g(be) * t(be) * x_ratio) * y_opposite + (g(c) * t(c) * x_opposite + g(d) * t(d) * x_ratio) * y_ratio);
green = (asum > 0) ? green / asum : 0;
blue = ((b(a) * t(a) * x_opposite + b(be) * t(be) * x_ratio) * y_opposite + (b(c) * t(c) * x_opposite + b(d) * t(d) * x_ratio) * y_ratio);
blue = (asum > 0) ? blue / asum : 0;
So I'm trying to take a bilinear interpolation algorithm for resizing images and add in alpha values as well. I'm using Actionscript 3 to do this, but I don't really think the language is relevant.
The code I have below actually works really well, but edges around "erased" regions seem to get darker. Is there an easy way for it to not include what I can only assume is black (0x00000000) when it's finding its average?
Code:
x_ratio = theX - x;
y_ratio = theY - y;
x_opposite = 1 - x_ratio;
y_opposite = 1 - y_ratio;
a = getPixel32(x, y);
be =getPixel32(x + 1, y);
c = getPixel32(x, y + 1);
d = getPixel32(x + 1, y + 1);
alph = (t(a) * x_opposite + t(be) * x_ratio) * y_opposite + (t(c) * x_opposite + t(d) * x_ratio) * y_ratio;
red = (r(a) * x_opposite + r(be) * x_ratio) * y_opposite + (r(c) * x_opposite + r(d) * x_ratio) * y_ratio;
green = (g(a) * x_opposite + g(be) * x_ratio) * y_opposite + (g(c) * x_opposite + g(d) * x_ratio) * y_ratio;
blue = (b(a) * x_opposite + b(be) * x_ratio) * y_opposite + (b(c) * x_opposite + b(d) * x_ratio) * y_ratio;
Image of the effect: http://beta.shinyhammer.com/images/site/eraser_pixelborders.jpg
Posting code of solution!
a = getPixel32(x, y);
be =getPixel32(x + 1, y);
c = getPixel32(x, y + 1);
d = getPixel32(x + 1, y + 1);
asum = (t(a) + t(be) + t(c) + t(d)) / 4;
alph = (t(a) * x_opposite + t(be) * x_ratio) * y_opposite + (t(c) * x_opposite + t(d) * x_ratio) * y_ratio;
red = ((r(a) * t(a) * x_opposite + r(be) * t(be) * x_ratio) * y_opposite + (r(c) * t(c) * x_opposite + r(d) * t(d) * x_ratio) * y_ratio);
red = (asum > 0) ? red / asum : 0;
green = ((g(a) * t(a) * x_opposite + g(be) * t(be) * x_ratio) * y_opposite + (g(c) * t(c) * x_opposite + g(d) * t(d) * x_ratio) * y_ratio);
green = (asum > 0) ? green / asum : 0;
blue = ((b(a) * t(a) * x_opposite + b(be) * t(be) * x_ratio) * y_opposite + (b(c) * t(c) * x_opposite + b(d) * t(d) * x_ratio) * y_ratio);
blue = (asum > 0) ? blue / asum : 0;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在使用之前,您需要将每个 r、g、b 值乘以相应的 alpha,然后在完成后将这些值除以最终的 alpha。 很容易想象当其中一个像素的 alpha 为零时会产生什么效果 - 每个 r、g、b 值都将乘以零,因此它们的原始值是什么根本不重要! 他们不会对最终结果做出贡献。
您需要添加一个检查,以便永远不会被零除,并确保舍入误差不会使最终值超过上限。
通常,图像将存储在内存中,其中 alpha 已经乘以 r、g、b 值 - 这称为预乘 alpha (维基百科参考)。
You need to multiply each of your r,g,b values by the corresponding alpha before working with them, then divide the values by the final alpha when you're done. It's easy to imagine the effect this will have when one of the pixels has an alpha of zero - each of the r,g,b values will be multiplied by zero, so it won't matter what their original values are at all! They won't contribute to the final result.
You'll need to add a check so that you never divide by zero, and make sure that roundoff error doesn't push your final values past the upper limit.
Often images will be stored in memory with the alpha already multiplied into the r,g,b values - this is called premultiplied alpha (Wikipedia reference).
这是使用预乘 alpha 具有巨大优势的领域之一。 通过预乘 Alpha,您可以将图像的 RGB 分量视为已提前在黑色上进行预合成。
这消除了与对具有 Alpha 的图像进行任何类型的图像处理相关的许多麻烦的影响,并提供了更快的合成算法。
对于“非预乘 alpha”,熟悉的 LIRP(线性插值)合成算法是
...其中 K 是前景的 alpha,f 是前景值,b 是背景。
对于“预乘阿尔法”,您可以使用
...,它会删除其中一个乘法,这可以使过程更快(并且硬件更便宜)。 需要阅读的关键论文是 Porter 和 Duff 的 - "合成数字图像"
如果您使用的是 Windows,则 Win32 AlphaBlend 函数需要预乘 Alpha,因此最好尽可能保留在预乘域中。
This is one of those areas where the use of pre-multiplied alpha is a huge advantage. With pre-multiplied alpha, you can think of the RGB components of your image as having been pre-composited on black in advance.
This removes many of the troublesome effects associated with any kind of image processing on images with alpha, as well as giving a faster compositing algorithm.
For "non-pre-multiplied alpha", the familiar LIRP (linear interpolation) compositing algorithm is
... where K is the alpha of the foreground, f is the foreground value and b is the background.
For "pre-multiplied alpha", you use
... which removes one of the multiplies, which can make the process faster (and cheaper in hardware). The key paper to read is Porter and Duff's - "Compositing Digital Images"
If you're using Windows, the Win32 AlphaBlend function requires premultiplied alpha, so it's good to stay in the premultiplied domain whenever possible.