一个模糊工具的算法?

3
我正在尝试实现一个涂抹工具,类似于Gimp或Photoshop中的工具。我尝试了许多变化,但它们都有问题。我已经尝试了从图像位置P1到P2进行涂抹的基本方法:
  1. 从P1拷贝当前画笔大小的矩形。
  2. 以低不透明度在P2处绘制此矩形。
看起来很好,也达到了预期的涂抹效果,但主要问题是涂抹似乎会使图像变暗。特别是当使用小画笔间距时,反复涂抹会将区域变成黑色。您有什么建议或标准算法可以供我参考吗?我已经查看了Gimp源代码,但很难理解。
如果有影响的话,我是在移动设备(Android,Java)上工作,因此最好使用一些快速的方法。
3个回答

4
我怀疑你的算法不断地将矩形绘制在彼此之上,很可能会对其值进行平均以获取下方的新颜色值。根据程序设置的具体情况,我敢打赌,由于这种重复的平均,RGB值即将变为0x000000。这也解释了为什么步长较小的区域更快地变黑,因为更多的步骤意味着更多的平均。我曾经拥有一个类似的问题,一个颜色变换器反复模糊,在边缘处变黑。
在这里可以找到一个关于如何创建自己的涂抹工具的好教程:https://web.archive.org/web/20100916174858/http://losingfight.com:80/blog/2007/09/04/how-to-implement-smudge-and-stamp-tools/ 不幸的是,所有的例子都是用Objective-C编写的,但文本解释得相当不错。
希望这能有所帮助。

谢谢提示。您能建议我在将涂抹图像混合回目标图像时该怎么做,以避免它变黑吗?实际上,我已经读了那篇教程(这是我唯一能找到的!)几次,但我看不出他与我有什么不同。他没有提到混合模式。有什么想法吗? - RichardNewton
我已经有一段时间没做计算机图形了,但还是试着解决一下问题。从我的观察来看,问题可能是由于你的不透明度引起的。你实际上是如何执行变换的呢?如果我们将值推向极端,会有几种清晰的可能性。例如,使用平均值合成蓝色和自身时应该始终得到蓝色,就像将一个实心颜色块涂抹到自己上面的情况一样。那么,如果你把蓝色拖进红色中呢?理论上,你应该得到紫色。重复涂抹应该会得到更均匀的紫色,直到达到0xFF00FF。 - MysteryMoose
谢谢回复。我所做的只是使用标准的绘制位图过程(因此位图将出现在第一个轻微透明之上),说“将位图从先前位置绘制到新位置,透明度设置为X百分比”。将蓝色涂入红色确实会产生紫色。奇怪的是,我可以继续单独擦拭紫色、红色和蓝色,它们不会变暗。然而,在紫色和蓝色重叠的地方擦拭很快就会产生黑色(这对于紫色+红色来说并非如此),而擦拭任何带有一些黑色的东西很快就会产生更多的黑色。 - RichardNewton
嗯,我觉得从蓝色和紫色中得到黑色的行为相当令人困惑,因为在任何时候,你都没有手动引入任何绿色通道。我猜你开始使用的是白色画布,只有在我敦促下才转移到蓝色+红色?如果是这样,绿色通道应该是255,而不是零。你能发一下你的代码吗?抱歉,否则我会很困惑。 - MysteryMoose
哎呀,我发现我的颜色选择器有一个错误,所以蓝色和红色都带有一点绿色...混合蓝色和红色的行为是符合预期的。然而,如果我使用蓝绿色和红色,我可以通过涂抹使它们变成黑色。:-\ - RichardNewton
我发现答案中的链接无效 - 在这里提供正确的链接,以防其他人找到此页面 - http://losingfight.com/blog/2007/09/05/how-to-implement-smudge-and-stamp-tools/ - 这是示例代码 - https://bitbucket.org/andyfinnell/smudge - Hugo Scott-Slade

1

你的问题在于Android使用预乘alpha来处理位图。当合成时,alpha通道与RGB相乘以节省时间。

以下是问题的示例。这两个画笔完全相同,唯一的区别是底部的画笔渲染时透明度为5%。

Demonstration of the premultiplied alpha effect in rendering with Android

当创建一个模糊工具时,这将如何呈现是模糊正在呈现非常低的alpha像素(通常来自掩蔽效果,或者仅来自于原始位图本身)。当许多这些位图在彼此之上呈现(如模糊)时,它会变成灰色。

我在为我正在编写的Android照片编辑应用程序构建模糊工具时也遇到了这个错误,但遗憾的是我尚未找到一个好的解决方案。

alpha和rgb通道需要在不透明的位图中分别呈现,然后以某种方式重新组合。不幸的是,在Android目前似乎没有很好的方法来做到这一点。

如果您想出解决方案,我很想听听您的想法。希望这将为您提供有关问题原因的一些信息,并为修复提供一些灵感。


0

这是一个相对较旧的话题,但我发现自己也遇到了同样的问题(涂抹变成黑色)。我也在按照这个教程进行操作:

http://losingfight.com/blog/2007/09/05/how-to-implement-smudge-and-stamp-tools/

正如GuyNoir所提到的,问题在于Android中位图的预乘alpha,其中存储在内存中的颜色值已经乘以alpha值。顺便说一下,模糊也会受到同样的问题,形成一个暗色光晕。
使用画布API没有办法解决这个问题,因为:
“只有预乘位图才能由视图系统或画布绘制。”
因此,我们必须通过Bitmap#getPixels()提取像素并手动进行混合。这肯定会对性能产生影响,但实现起来并不太难。
因此,对于每个像素:
alpha = ( SourceAlpha * strength ) + ( DestinationAlpha * ( 1 - strength ) )

color = ( SourceColor * strength ) + ( DestinationColor * ( 1 - strength ) )

目标是要涂抹的图像,源是画笔。 强度表示你在涂抹画笔时施加的力度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接