kirby-blurry-placeholder icon indicating copy to clipboard operation
kirby-blurry-placeholder copied to clipboard

Artifacts when using transparent images

Open ChristophLabacher opened this issue 3 years ago • 5 comments

First of all, thanks for the plugin – it’s awesome!

Unfortunately I am having some problems when using it for transparent PNG files, there are some heavy artifacts in the blurred version of the image:

image

ChristophLabacher avatar Apr 03 '21 21:04 ChristophLabacher

Hi Christoph,

first and foremost: thanks for the flowers.

That does look ugly, indeed. The plugin uses Kirby's thumbnail generation, which itself uses PHP's GD library (unless you're using ImageMagick). It seems like your transparent image isn't handled well. Maybe we can detect images containing transparent pixels and process them differently. Or seimpler, use a different SVG overlay for those images to hide the artifacts.

For the time being I don't have a quick solution, sorry. Would you mind posting the source image here so I can replicate the artifacts?

johannschopplich avatar Apr 05 '21 13:04 johannschopplich

Sure! Here are the files from a different example.

This is the original:

charapitachilli

This is the thumbnail generated by Kirby (I took it from the media folder, scaled up for reference):

image

And this is what it looks like in the fronend:

image

ChristophLabacher avatar Apr 05 '21 14:04 ChristophLabacher

I had a look at the way the blurry SVG is generated. In addition to the self-explanatory gaussian blur there's also a feFuncA which essentially eliminates the transparent areas on the blurry image. This makes sense for images without an alpha channel because you don't have to zoom but still receive a "full" image.

For transparent images it might make sense to simply remove this.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {$svgWidth} {$svgHeight}">
  <filter id="b" color-interpolation-filters="sRGB">
    <feGaussianBlur stdDeviation=".5"></feGaussianBlur>
-   <feComponentTransfer>
-     <feFuncA type="discrete" tableValues="1 1"></feFuncA>
-   </feComponentTransfer>
  </filter>
  <image filter="url(#b)" x="0" y="0" width="100%" height="100%" href="{$placeholderImage}"></image>
</svg>
CleanShot 2022-03-02 at 17 06 37@2x

medienbaecker avatar Mar 02 '22 16:03 medienbaecker

Depending on the project it might make sense to add a white background behind images via a feFlood filter instead:

<feFlood flood-color="white" result="bg" />
<feMerge>
  <feMergeNode in="bg"/>
  <feMergeNode in="SourceGraphic"/>
</feMerge>

medienbaecker avatar Mar 07 '22 15:03 medienbaecker

@medienbaecker Thanks a lot for your thorough research! Amazing. 🤯 I haven't had the time to think of a better implementation yet. I prefer the latter solution.

johannschopplich avatar Mar 24 '22 09:03 johannschopplich

I use a forked version of this plugin in my project and added a custom transparent option that lets me toggle the snippet @medienbaecker highlighted. It's not the best idea, as I haven't implemented a way to detect transparent images, but most of the time when I use them I know beforehand (e.g. logos, clip arts, etc.), so I can set the value in code.

tobimori avatar Jan 04 '23 19:01 tobimori

@ChristophLabacher @medienbaecker With all of your help and @tobimori's implementation, this issue can finally be closed. Thank you all for your input! I wouldn't have managed to find time for a deep-dive into the issue. Feels good to finally close this.

With version 3.0.0, the presence of an alpha channel in the image will be evaluated by the plugin. In any case, you can now pass an option parameter to disable the SVG filter, which resolves the blur artifacts:

$file->placeholderUri([
  'transparent' => true
]);

johannschopplich avatar Jan 05 '23 19:01 johannschopplich