SVG拡張/侵食フィルタ対イラストレーターオフセット経路
-
13-12-2019 - |
質問
左の画像はSVG:S拡張および侵食フィルタを使用して行われます。右のものはイラストレーターのオフセットパス効果を使用して行われます。
左のものには問題があります。底部の境界は歪められ、曲線は滑らかではありません。その間、太い黒い境界線は両方で同じです。
私のSVGが間違っているか、拡張され侵食的なフィルタであるため、一見バグのあるフィルタはありますか?
編集:目的はSVGで薄くまたは厚く経路を作ることですが、この例によれば、侵食/拡張は依存するのに十分安定していません。
解決
フィルタ効果はピクセルデータ(ラスタライズパス)で行われ、イラストレータのパスオフセット動作(Inkscapeが似ています)は、元のパスデータ(または必要な場合はベクトルデータ)を使用して行われます。
前者はPhotoshopフィルタを使用するようなものです。後者は既存のパスを使用して新しいパスを作成しています。彼らは両方とも安定していますが、彼らは同じ操作ではありません。
他のヒント
IllustratorのパスオフセットとSVGフィルタ侵食/拡張は異なる操作です。
この侵食フィルタは設計どおりに機能しています - ここでのバグはありません。入力画像内のすべてのピクセルについて、フィルタは最大RGBA値(半径)の周囲の矩形内の最大RGBA値を調べます。通常の画像では、これは、より良い用語のために「長方形のハイライト」を生成する傾向があります。そして湾曲した描画経路に適用されると奇妙なアーティファクトをもたらす。仕様から:
拡張(または浸食)カーネルは幅の長方形です。 2 * X r - 半径2 * y - 半径の高さ。拡張では、出力ピクセル 対応するR、G、B、Aの個々の構成要素間の最大値です。 入力画像のカーネル長方形の値。侵食では、出力 ピクセルは、対応する個々のコンポーネントの最小値です。 R、G、B、入力画像のカーネル長方形の値。
それで、そのシングルピクセルがあなたの形の先端にあると想像してください。あなたのフィルタの10ピクセルの "RADIUS"で(そしてそれは円ではなく長方形を使用しているので、半径は非常に誤解を招く用語であることを覚えています!)。議論のために、100,100であると言ってみましょう。フィルタが90,110から110,110の範囲のピクセルの値を処理するとき、その拡張半径は100,100のピクセルを検出し、その範囲のすべてのピクセルをペイントする。そしてそのように、あなたの素晴らしい先端の端は直線に拡張されました。
ネストストロークを使用してほとんどのオフセットパス効果を達成することができます(そのうちのいくつかはパスの内側または外側をトリミングするためのマスクを持っています。
たとえば、このようにして再実装されたOPのパスがここにあります。
<!-- 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>
.