Ala*_*met 5 svg perlin-noise svg-filters
当尝试使用feTurbulence滤镜基元时,我在意想不到的地方出现了细而暗的线条。它们在 时最为明显numOctaves="1"。他们为什么在那里?
假设我从https://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement中的参考代码开始(修复它以便编译)。我称其为
turbulence(
0, /* color channel */,
point, /* {x,y} */
1.0, 1.0, /* fBaseFreqX and Y */
1, /* numOctaves */
0, /* bFractalSum */
0, /* bDoStitching */
0.0, 0.0, /* fTileX and Y */
0.0, 0.0, /* fTileWidth and Height */
)
Run Code Online (Sandbox Code Playgroud)
(我的完整来源可在https://gitlab.com/AlanDeSmet/svg-1.1-feturbulence获取)
从 0.0 到 10.0 迭代 x 和 y,获取 300 个样本,并将每个样本乘以 256 创建一个 300x300 灰度图像:
这就是我期望看到的。它看起来类似于由程序产生的柏林湍流,例如
Adobe Flash(来源):
3ds Max(来源):
但是,如果我使用 feTurbulence 创建 SVG 并在 Firefox、Chromium 或 Inkscape(我相信这是 3 个独立的实现)中查看它,我会得到以下结果:
来源:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg height="10" width="10" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<filter color-interpolation-filters="sRGB"
id="test-turbulence" x="0" y="0" width="1" height="1">
<feTurbulence type="turbulence" numOctaves="1" baseFrequency="1" />
<feColorMatrix
values="1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
0 0 0 0 1 " />
</filter>
<rect width="10" height="10" style="filter:url(#test-turbulence)" x="0" y="0" />
</svg>
Run Code Online (Sandbox Code Playgroud)
(我用来color-interpolation-filters="sRGB"更紧密地匹配我的简单程序的输出。它不会改变结构,只是使图像“变暗”。
整个图像中有细密的暗线,这是我没有预料到的。这是并排比较;我使用左侧(或上方)的标准参考实现,以及右侧(或下方)的 Chromium 输出(看起来与 Firefox 和 Inkscape 相同)。
由于三个不同的渲染器都同意,它似乎可能是正确的标准,但这不是我认为标准参考实现所做的事情,也不是其他一些程序所做的事情。
为什么我尝试使用标准的参考实现与 Firefox、Chrome 和 Inkscape 的做法存在差异?该标准是否应该与针对柏林湍流实施的其他计划有所不同?如果是这样,有什么区别?
这是预期的行为。您可以通过使用 alpha\n通道来避免湍流,而不是任何颜色通道。
\n您可以使用feColorMatrixAlpha 通道创建灰度湍流:
<filter id="turbulence-alpha" x="0" y="0" width="1" height="1">\n <feTurbulence type="turbulence" baseFrequency="0.02" />\n <feColorMatrix\n values="0 0 0 1 0\n 0 0 0 1 0\n 0 0 0 1 0\n 0 0 0 0 1 " />\n</filter>\nRun Code Online (Sandbox Code Playgroud)\n该行为令人惊讶,但它符合 SVG 规范,并且\n对于某些用途可能是正确的。
\n意外的线条来自 Alpha 通道,尽管已丢弃它!\n例如,这里是所有四个通道。观察到线程跨越所有颜色通道并与 Alpha 通道的接近零的部分完全匹配。
\n\n(用于生成此内容的 SVG 位于下面的“Alpha Comparison SVG”下。)
\n\n\n\n除非另有说明,所有图像过滤器都对预乘的 RGBA\n样本进行操作。对非预乘数据(feColorMatrix 和 feComponentTransfer)更自然地工作的过滤器将根据指定暂时撤消和重做预乘。
\n
在这种情况下,“预乘”指的是预乘 Alpha,其中颜色通道由 Alpha 进行调整。预乘很好,因为它可以使合成和过滤正常工作。它发生在场景后面,您可以忽略它...除非您修改 Alpha 通道。
\n问题是预乘会丢失数据。当 alpha 值接近 0(完全透明)时,数据丢失尤其严重。当feColorMatrix或feComponentTransfer“暂时撤消和重做预乘”时,撤消操作只是一个近似值。该数据丢失表现为整个图像中出现意外的线条。
\n例如,给定一个输入图像,其颜色通道为
\n\n其 alpha 通道是
\n\n颜色通道的预乘版本将是
\n\n尝试撤销预乘会产生以下结果:
\n\n整个图像都有损坏(略低于 50% 的像素不匹配),\n但当 Alpha 接近零时,与原始图像的差异最为显着。
\n(这些图像是由下面的“比较图像生成器”下的 Python 代码创建的。premul_alpha和unpremul_alpha基于
\n Inkscape\ 的实现)
type="fractalNoise"?上述所有内容都适用于<feTurbulence type="fractalNoise">,那么为什么它不是一个问题呢?
因为<feTurbulence type="fractalNoise" numOctaves="1">是原始 Perlin 2d 噪声,而Perlin 噪声的范围为 \xe2\x88\x920.707 到 0.707(备份链接)。它被视为 \xe2\x88\x921 到 1 的范围。将该范围重新映射到 0 到 255,所有值最终都在 37 到 217 之间。损坏是存在的,但因为 alpha 永远不够接近 0,所以您看不到它。
它变得可见,type="turbulence"因为柏林湍流使用原始噪声的绝对值。因此范围变为 0.000 到 0.707,最终范围为 0 到 217。这也是为什么fractalNoise没有纯黑色而turbulence有的原因(以及为什么两者都没有纯白色)。
(其来源在下面的“湍流与噪声”中。)
\n这是比较 发出的四个通道的 SVG feTurbulence。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n<svg\n height="230"\n width="800"\n version="1.1"\n xmlns="http://www.w3.org/2000/svg"\n xmlns:svg="http://www.w3.org/2000/svg">\n <filter id="turbulence-red" x="0" y="0" width="1" height="1">\n <feTurbulence type="turbulence" baseFrequency="0.02" />\n <feColorMatrix\n values="1 0 0 0 0\n 1 0 0 0 0\n 1 0 0 0 0\n 0 0 0 0 1 " />\n </filter>\n <filter id="turbulence-green" x="0" y="0" width="1" height="1">\n <feTurbulence type="turbulence" baseFrequency="0.02" />\n <feColorMatrix\n values="0 1 0 0 0\n 0 1 0 0 0\n 0 1 0 0 0\n 0 0 0 0 1 " />\n </filter>\n <filter id="turbulence-blue" x="0" y="0" width="1" height="1">\n <feTurbulence type="turbulence" baseFrequency="0.02" />\n <feColorMatrix\n values="0 0 1 0 0\n 0 0 1 0 0\n 0 0 1 0 0\n 0 0 0 0 1 " />\n </filter>\n <filter id="turbulence-alpha" x="0" y="0" width="1" height="1">\n <feTurbulence type="turbulence" baseFrequency="0.02" />\n <feColorMatrix\n values="0 0 0 1 0\n 0 0 0 1 0\n 0 0 0 1 0\n 0 0 0 0 1 " />\n </filter>\n <text x="100" y="220" text-anchor="middle">Red Channel</text>\n <rect x="0" y="0" width="200" height="200"\n style="filter:url(#turbulence-red)" />\n\n <text x="300" y="220" text-anchor="middle">Green Channel</text>\n <rect x="200" y="0" width="200" height="200"\n style="filter:url(#turbulence-green)" />\n\n <text x="500" y="220" text-anchor="middle">Blue Channel</text>\n <rect x="400" y="0" width="200" height="200"\n style="filter:url(#turbulence-blue)" />\n\n <text x="700" y="220" text-anchor="middle">Alpha Channel</text>\n <rect x="600" y="0" width="200" height="200"\n style="filter:url(#turbulence-alpha)" />\n</svg>\n\nRun Code Online (Sandbox Code Playgroud)\n此代码生成了上面的四个方形示例图像。
\n#! /usr/bin/python3\n\nfrom PIL import Image\n\ndef premul_alpha(color,alpha):\n temp = alpha * color + 128\n res = (temp + (temp >> 8)) >> 8\n return res\n\ndef unpremul_alpha(color, alpha):\n if alpha == 0: return color # Nonsensical operation\n res = int((255 * color + alpha/2) / alpha)\n return res\n\noriginalimg = Image.new("L",(256,256))\noriginal_px = originalimg.load()\nalphaimg = Image.new("L",(256,256))\nalpha_px = alphaimg.load()\npremulimg = Image.new("L",(256,256))\npremul_px = premulimg.load()\nrestoredimg = Image.new("L",(256,256))\nrestored_px = restoredimg.load()\ndamagedimg = Image.new("L",(256,256),0)\ndamaged_px = damagedimg.load()\n\n\ntotal = 0\ndmg_count =0\nfor color in range(256):\n for alpha in range(0,256):\n original_px[color,alpha] = color;\n alpha_px[color,alpha] = alpha;\n during = premul_alpha(color,alpha)\n premul_px[color,alpha] = during\n restored = unpremul_alpha(during,alpha)\n restored_px[color,alpha] = restored\n total += 1\n if restored != color:\n dmg_count += 1\n damaged_px[color,alpha] = 255\nprint(f"{dmg_count}/{total} -> {dmg_count/total}")\n\noriginalimg.save("original.png")\nalphaimg.save("alpha.png")\npremulimg.save("premul.png")\nrestoredimg.save("restored.png")\ndamagedimg.save("damaged.png")\nRun Code Online (Sandbox Code Playgroud)\n噪音:
\n<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n<svg\n height="200"\n width="200"\n version="1.1"\n xmlns="http://www.w3.org/2000/svg"\n xmlns:svg="http://www.w3.org/2000/svg">\n <filter id="turbulence-alpha" x="0" y="0" width="1" height="1">\n <feTurbulence type="fractalNoise" baseFrequency="0.02" />\n <feColorMatrix\n values="0 0 0 1 0\n 0 0 0 1 0\n 0 0 0 1 0\n 0 0 0 0 1 " />\n </filter>\n <rect x="0" y="0" width="200" height="200"\n style="filter:url(#turbulence-alpha)" />\n</svg>\nRun Code Online (Sandbox Code Playgroud)\n湍流:
\n<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n<svg\n height="200"\n width="200"\n version="1.1"\n xmlns="http://www.w3.org/2000/svg"\n xmlns:svg="http://www.w3.org/2000/svg">\n <filter id="turbulence-alpha" x="0" y="0" width="1" height="1">\n <feTurbulence type="turbulence" baseFrequency="0.02" />\n <feColorMatrix\n values="0 0 0 1 0\n 0 0 0 1 0\n 0 0 0 1 0\n 0 0 0 0 1 " />\n </filter>\n <rect x="0" y="0" width="200" height="200"\n style="filter:url(#turbulence-alpha)" />\n</svg>\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
504 次 |
| 最近记录: |