【问题标题】:Algorithm for a smudge tool?涂抹工具的算法?
【发布时间】:2011-04-29 14:26:09
【问题描述】:

我正在尝试实现一种涂抹工具,就像您在 Gimp 或 Photoshop 中找到的那样。我尝试了很多变化,但它们都有问题。我尝试在图像上从位置 P1 到 P2 涂抹的基本方法是:

  1. 从 P1 复制一个与当前画笔大小相同的矩形。
  2. 在 P2 处以低不透明度绘制此矩形。

它看起来很好,并且像预期的那样弄脏了,但我遇到的主要问题是弄脏似乎使事情变得更暗。尤其是在使用较小的画笔间距时,反复涂抹会使该区域变黑。关于我做错了什么或我可以查看的一些标准算法的任何建议?我查看了 Gimp 的源代码,但很难理解。

如果重要的话,我正在使用移动设备(Android、Java),所以最好是快速的。

【问题讨论】:

    标签: java android graphics image-processing


    【解决方案1】:

    我怀疑您的算法会不断地将矩形呈现在彼此之上,可能会平均它们的值以获得下面的新颜色值。根据您的程序细节的设置方式,我敢打赌,由于这种重复平均,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 编写的,但是文本很好地解释了正在发生的事情。

    希望这会有所帮助。

    【讨论】:

    • 感谢您的提示。您能否建议将污迹图像混合回目标图像以使其不会变黑时可以做什么?我实际上已经阅读了该教程(这是我能找到的唯一一个!)几次,我看不出他对我做了什么不同。他没有提到混合模式。有什么想法吗?
    • 自从我从事计算机图形学工作以来已经有很长一段时间了,但是这里有。据我所知,问题是由于您的不透明而引入的。您实际上是如何执行转换的那部分的?如果我们将这些值发挥到极致,就会有几种不同的可能性。例如,将蓝色与自身进行平均应该始终为您提供蓝色,就像将纯色块涂抹在自身中一样。现在,如果将蓝色拖入红色会发生什么?理论上,你应该得到紫色。重复涂抹应该会给你更均匀的紫色,直到你达到 0xFF00FF。
    • 感谢您的回复。我所做的只是说“使用标准绘制位图程序将位图从先前位置绘制到新位置,并将 alpha 设置为 X%”(因此位图将出现在第一个轻微透明的上方)。将蓝色涂抹成红色确实会产生紫色。奇怪的是,我可以继续分别摩擦紫色、红色和蓝色,而且它们不会变深。然而,在紫色和蓝色重叠的地方摩擦会很快产生黑色(紫色+红色不是这种情况),摩擦任何带有一些黑色的东西会很快产生更多的黑色。
    • 嗯。我发现从蓝色和紫色变成黑色的行为相当令人费解,因为您在任何时候都没有在绿色通道上手动引入任何东西。我假设您开始使用白色画布,只是在我的敦促下才移动到蓝色 + 红色?在这种情况下,绿色通道应该是 255,而不是零。你可以发布你的代码吗?抱歉,否则我会很困惑。
    • 糟糕,我在颜色选择器中发现了一个错误,因此蓝色和红色都带有一点绿色...混合蓝色和红色具有预期的行为。但是,如果我使用蓝绿色和红色,我可以通过涂抹使黑色。 :-\
    【解决方案2】:

    您的问题是 Android 对位图使用预乘 alpha。 Alpha 通道与 RGB 相乘以节省合成时间。

    这是问题的一个示例。这两个画笔完全相同,除了底部以 5% alpha 渲染。

    在创建涂抹工具时,涂抹工具会渲染非常低的 Alpha 像素(通常来自遮罩效果,或仅来自原始位图本身)。当这些位图中的许多被渲染在彼此之上(如在污迹中)时,它会变成灰色。

    我在为我正在为 Android 编写的照片编辑应用程序构建涂抹工具时遇到了这个错误,遗憾的是我还没有找到一个好的解决方案。

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

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

    【讨论】:

      【解决方案3】:

      相当老的话题,但我发现自己有同样的问题(污迹变黑)。我也在关注这个教程:

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

      正如 GuyNoir 提到的,问题是 android 中位图的预乘 alpha,其中存储在内存中的颜色值已经乘以 alpha 值。顺便说一下,模糊也会以暗光晕的形式出现同样的问题。

      canvas API 无法解决这个问题,因为:

      “视图系统或 Canvas 只能绘制预乘位图。”

      所以我们必须通过 Bitmap#getPixels() 提取像素并手动进行混合。这肯定会对性能产生影响,但实施起来并不难。

      所以对于每个像素:

      alpha = ( SourceAlpha * strength ) + ( DestinationAlpha * ( 1 - strength ) )
      
      color = ( SourceColor * strength ) + ( DestinationColor * ( 1 - strength ) )
      

      目标是要涂抹的图像,源是画笔。 力度代表您在涂抹刷上的按压力度。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-28
        相关资源
        最近更新 更多