resvg icon indicating copy to clipboard operation
resvg copied to clipboard

Support `edgeMode` in `feGaussianBlur`

Open RazrFalcon opened this issue 2 years ago • 4 comments

https://www.w3.org/TR/filter-effects-1/#element-attrdef-fegaussianblur-edgemode

RazrFalcon avatar Aug 26 '21 19:08 RazrFalcon

Hi, thanks for your crate.

I am trying to narrow a change in Alpha rendering from an svg from version 0.17 to above until 0.23.

This below code does not render the same image, Alpha is missing. Did resvg maybe drop support of feGaussianBlur with stdDeviation somehow or am I missing a configuration ? thanks for any tip because I would like to use the Transform from versions above.

use tiny_skia::*;
use usvg::{Options, Tree};

fn main() {
    let svg = "<svg width='560' height='560' viewBox='0 0 560 560' xmlns='http://www.w3.org/2000/svg'>
    <defs>
      <filter id='filter14148-8' x='-0.10750898' y='-0.10849553' width='1.215018' height='1.2169911'>
        <feGaussianBlur color-interpolation-filters='sRGB' in='SourceGraphic' stdDeviation='3.9237191 3.9237191' result='result1' />
      </filter>
    </defs>
    <g xmlns='http://www.w3.org/2000/svg' id='g1405' filter='url(#filter14148-8)'>
      <path id='left_palm_shadow_2' fill='rgba(217,154,3,255)' stroke='none' d='M 140.10966 283.77885 C 141.56481 283.19266 143.20389 283.12821 144.73238 283.47479 C 146.26087 283.82136 147.68195 284.56494 148.92074 285.52179 C 151.39832 287.4355 153.12057 290.13558 154.77493 292.7904 C 158.74502 299.22346 162.62633 305.72421 166.29103 312.35756 C 169.06793 317.3508 171.71573 322.45009 175.12852 327.03648 C 177.39231 330.07802 179.97587 332.86787 182.28639 335.87323 C 184.5969 338.87859 186.65765 342.15537 187.67919 345.8067 C 188.99545 350.51252 188.46184 355.71671 186.18378 360.03952 C 184.54623 363.14528 182.03175 365.78596 178.99769 367.55212 C 175.96363 369.31829 172.41845 370.20135 168.91114 370.04003 C 163.31283 369.78231 158.19985 366.9865 152.93025 365.08932 C 142.82718 361.4236 131.87681 360.93178 121.5141 358.06931 C 117.79931 357.06098 114.17749 355.71655 110.44455 354.77535 C 108.79293 354.35877 107.11152 354.01823 105.54238 353.35605 C 103.97324 352.69386 102.49557 351.66739 101.64486 350.19131 C 101.01204 349.09414 100.75925 347.80293 100.79835 346.5371 C 100.83745 345.27126 101.1575 344.02675 101.60827 342.84324 C 102.50982 340.47623 103.92852 338.33295 104.83739 335.9686 C 106.21609 332.39435 106.38733 328.46448 106.13136 324.64243 C 105.87539 320.82038 105.21026 317.03294 104.9781 313.20883 C 104.87436 311.49987 104.85877 309.76984 105.20444 308.09307 C 105.55008 306.4163 106.2805 304.78336 107.4993 303.58107 C 108.82019 302.27203 110.64046 301.55694 112.47657 301.2768 C 114.31268 300.99667 116.18258 301.11872 118.03136 301.2838 C 119.88013 301.44875 121.73639 301.65651 123.59249 301.54543 C 125.44858 301.43434 127.32819 300.98212 128.86135 299.93849 C 130.25872 298.99388 131.30719 297.61442 132.10574 296.14007 C 132.9043 294.66572 133.47334 293.08463 134.08218 291.52351 C 134.69103 289.96238 135.3489 288.40162 136.30398 287.01378 C 137.25907 285.62593 138.5401 284.40911 140.10966 283.77905'/>
    </g>
  </svg>";
    let mut pixmap = tiny_skia::Pixmap::new(560, 560).unwrap();
    let opt: usvg::Options = usvg::Options {
        ..Options::default()
    };
    let tree = Tree::from_str(svg, &opt.to_ref()).unwrap();
    let fit_to = usvg::FitTo::Original;
    
    resvg::render(&tree, fit_to, Transform::default(), pixmap.as_mut());
    // resvg::render(&tree, fit_to, pixmap.as_mut()); in version 0.17
    
    pixmap.save_png("image.png").unwrap();
}

Image rendered in version 0.17 image_0 17

Image rendered in version 0.23 image

Thanks

gRoussac avatar Aug 31 '22 15:08 gRoussac

Your example produces correct output for me. Are you sure this is the whole code?

What OS/hardware do you have?

RazrFalcon avatar Aug 31 '22 15:08 RazrFalcon

My very bad you made me realize I was messing up with features in to Cargo.toml. I am sorry for this disturbance.

gRoussac avatar Aug 31 '22 15:08 gRoussac

No problem.

RazrFalcon avatar Aug 31 '22 16:08 RazrFalcon

It looks like feGaussianBlur currently uses RGBA8::default() when reading past the edges, which corresponds to edgeMode=none, correct?

transitive-bullshit avatar Nov 15 '22 04:11 transitive-bullshit

Probably. I haven't looked into it much. resvg follows SVG 1.1 behaviour, which is probably none.

RazrFalcon avatar Nov 15 '22 07:11 RazrFalcon

As for https://github.com/vercel/satori/issues/309, I think this actually #215 and #241. This is pretty hard to fix, since it would require a rewrite of filters processing code. Not sure when I will have time for that.

Basically, resvg assumes that the filter region will not leave the canvas, which is not always true.

RazrFalcon avatar Nov 15 '22 08:11 RazrFalcon

Thanks for the hints @RazrFalcon and for all of your work on resvg. It's amazing how useful it's been.

transitive-bullshit avatar Nov 15 '22 22:11 transitive-bullshit

Fixed in v0.33

RazrFalcon avatar May 21 '23 13:05 RazrFalcon