SVG dilate/erode filter vs. Illustrator Offset Path

ⅰ亾dé卋堺 提交于 2019-12-01 21:19:13

Filter effects are done on pixel data (the rasterized path), while the path offset operation in Illustrator (similar in Inkscape) is done using the original path data (or vector data if you wish).

The former is like using photoshop filters, the latter is creating new paths by using the existing path. They're both stable, but they're not the same operation.

Illustrator's path offset and SVG filters erode/dilate are different operations.

This erode filter is working as designed - there is no bug here. For every pixel in the input image, the filter looks at the maximum RGBA values in a rectangle around it (the radius). In a normal image this tends to generate "rectangular highlights" for want of a better term. And results in weird artifacts when applied to curved draw paths. From the spec:

The dilation (or erosion) kernel is a rectangle with a width of 2*x-radius and a height of 2*y-radius. In dilation, the output pixel is the individual component-wise maximum of the corresponding R,G,B,A values in the input image's kernel rectangle. In erosion, the output pixel is the individual component-wise minimum of the corresponding R,G,B,A values in the input image's kernel rectangle.

So, imagine that that single pixel at the pointy end of your shape. With a 10 pixel "radius" in your filter (and remember that radius is an incredibly misleading term because it's using a rectangle not a circle!). Let's say it's at 100,100, for arguments sake. When the filter processes values for pixels in the range 90,110 to 110,110, its dilation radius is going to detect that pixel at 100,100 and paint all pixels in that range black. And just like that, your nice pointy end has been dilated into a straight line.

Note that you can achieve most offset path effects using nested strokes (some of which have masks to trim the inside or outside of the path.

For example, here is the OP's path reimplemented this way:

<!-- Left drawing is made using erode and dilate -->  <!-- Right one is made by Illustrator's Offset Path -->        <svg width="612" height="792" viewBox="0 0 612 792" xmlns="http://www.w3.org/2000/svg">      <defs>      <path id="curve" d="M21.552,74.438c2.531-28.879,73.668-52.734,102.629-53.971          c32.164-1.373,74.764,23.746,61.766,53.197c-32,72.5-84.236-59.594-109.5-29.5c-23.367,27.833,55.4,142.969,55.4,142.969          S18.109,113.708,21.552,74.438z"/>        <mask id="inner">        <use xlink:href="#curve" fill="white"/>      </mask>    </defs>      <!-- this black outermost line -->    <use x="10" y="10" xlink:href="#curve" style="stroke:black;stroke-width:26;stroke-linejoin:miter;stroke-miterlimit:10"></use>    <!-- thick red outer line -->    <use x="10" y="10" xlink:href="#curve" style="stroke:#f00;stroke-width:24;stroke-linejoin:miter;stroke-miterlimit:10"></use>        <!-- innermost black thin line, with green fill -->    <use x="10" y="10"  xlink:href="#curve" style="fill:#1CFF00;stroke:black;stroke-width:32;stroke-linejoin:miter;stroke-miterlimit:10" mask="url(#inner)"></use>    <!-- blue inner stroke -->    <use x="10" y="10"  xlink:href="#curve" style="fill:none;stroke:#5555FF;stroke-width:30;stroke-linejoin:miter;stroke-miterlimit:10" mask="url(#inner)"></use>    <!-- lastly, the black line -->    <use x="10" y="10"  xlink:href="#curve" style="fill:none;stroke:black;stroke-width:10;stroke-linejoin:miter;stroke-miterlimit:10"></use>        <g transform="translate(210,10)">      <path fill="#FF0000" stroke="#231F20" d="M126.273,201.917c-1.188-0.766-29.407-19.044-57.679-42.532c-41.739-34.676-60.31-60.754-58.441-82.068          c1.575-17.974,18.042-34.105,48.943-47.945c21.673-9.707,48.782-16.997,65.925-17.729c1.023-0.043,2.057-0.065,3.096-0.065          c26.722,0,55.103,13.789,67.484,32.787c7.866,12.07,9.101,25.736,3.476,38.482c-8.697,19.704-20.608,29.697-35.403,29.702          c-0.002,0-0.007,0-0.01,0C144.382,112.551,127.62,95,111.407,78.028c-7.054-7.385-18.575-19.446-23.912-21.338          c-1.086,2.002-6.186,15.821,20.666,67.477c16.226,31.214,35.475,59.438,35.668,59.72l35.977,52.589L126.273,201.917z"/>  <path fill="#5555FF" stroke="#231F20" stroke-width="10" stroke-miterlimit="10" d="M22.939,78.438      c2.531-28.879,73.668-52.734,102.629-53.971c32.164-1.373,74.764,23.746,61.766,53.197c-32,72.5-84.237-59.594-109.5-29.5      c-23.366,27.833,55.401,142.969,55.401,142.969S19.497,117.709,22.939,78.438z"/>        <path fill="#00FF00" stroke="#231F20" d="M79.986,131.678C38.498,95.796,38.41,81.397,38.549,79.807c0.289-3.29,5.843-10.151,19.371-17.933          C57.676,78.899,64.972,101.816,79.986,131.678L79.986,131.678z M163.665,84.044c-7.09,0-22.461-16.091-31.646-25.706          c-5.867-6.143-11.433-11.969-16.966-16.846c4.324-0.776,8.128-1.238,11.184-1.368c0.621-0.027,1.249-0.04,1.88-0.04          c16.911,0,36.471,8.903,43.603,19.846c3.317,5.089,2.508,8.623,1.278,11.408C168.884,80.659,165.163,84.043,163.665,84.044          L163.665,84.044z"/>      </g>        </svg>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!