Published
Edited
Jun 16, 2022
2 stars
Insert cell
Insert cell
Insert cell
<svg class="wrapper" width=${width} height="512" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" version="1.1">
<defs>
<filter id="displacement-filter" width="228" height="228" x="580" y="0" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feImage width="228" height="228" href="https://assets.codepen.io/100347/fed_sagrada-384.jpg" />
<feDisplacementMap id="fedisplacementmap" in="SourceGraphic" xChannelSelector="R" yChannelSelector="B" scale="-50" />
</filter>
</defs>
<image href="https://assets.codepen.io/100347/fed_sagrada-384.jpg" x="0" y="0" height="228px" width="228px" />
<image href="https://assets.codepen.io/100347/fed_monalisa-384.jpg" x="238" y="0" height="228px" width="228px" />
<image href="https://assets.codepen.io/100347/fed_monalisa-384.jpg" class="filter--mona" x="580" y="0" height="228px" width="228px" />
</svg>

<style>
.filter--mona {
filter: url(#displacement-filter);
}

.wrapper {
width: 508px;
height: 228px;
overflow: visible;
}
</style>

Insert cell
{
const feImage = document.querySelector('feImage');

fetch('https://assets.codepen.io/100347/fed_sagrada-384.jpg')
.then((response) => {
return response.blob();
})
.then((blob) => {
const objURL = URL.createObjectURL(blob);
feImage.setAttribute('href', objURL);
});
}
Insert cell
# Filter id="displacement-filter"

**[filterUnits](https://www.w3.org/TR/filter-effects-1/#element-attrdef-filter-filterunits)** = "*userSpaceOnUse* | *objectBoundingBox*"

**[color-interpolation-filters](https://www.w3.org/TR/filter-effects-1/#propdef-color-interpolation-filters)** = [auto](https://www.w3.org/TR/filter-effects-1/#valdef-color-interpolation-filters-auto) | [sRGB](https://www.w3.org/TR/filter-effects-1/#valdef-color-interpolation-filters-srgb) | [linearRGB](https://www.w3.org/TR/filter-effects-1/#valdef-color-interpolation-filters-linearrgb)

**[feImage](https://www.w3.org/TR/filter-effects-1/#elementdef-feimage)** The filter image(s) to use.

**[feDisplacementMap](https://www.w3.org/TR/filter-effects-1/#elementdef-fedisplacementmap)** How the filter is applied.

>***scale***: is the strength of the distortion.
***xChannelSelector*** & ***yChannelSelector***: determines which color channels (red, green, blue, alpha) should be applied to which axis for distortion.
***[in](https://www.w3.org/TR/filter-effects-1/#element-attrdef-filter-primitive-in)*** = [SourceGraphic](https://www.w3.org/TR/filter-effects-1/#attr-valuedef-in-sourcegraphic) | [SourceAlpha](https://www.w3.org/TR/filter-effects-1/#attr-valuedef-in-sourcealpha) | [BackgroundImage](https://www.w3.org/TR/filter-effects-1/#attr-valuedef-in-backgroundimage) | [BackgroundAlpha](https://www.w3.org/TR/filter-effects-1/#attr-valuedef-in-backgroundalpha) | [FillPaint](https://www.w3.org/TR/filter-effects-1/#attr-valuedef-in-fillpaint) | [StrokePaint](https://www.w3.org/TR/filter-effects-1/#attr-valuedef-in-strokepaint) | [&lt;filter-primitive-reference&gt;](https://www.w3.org/TR/filter-effects-1/#typedef-result-filter-primitive-reference)
```svg
<filter id="displacement-filter" width="228" height="228" x="580" y="0" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feImage width="228" height="228" href="https://assets.codepen.io/100347/fed_sagrada-384.jpg" />
<feDisplacementMap id="fedisplacementmap" in="SourceGraphic" xChannelSelector="R" yChannelSelector="B" scale="50" />
</filter>
```

https://drafts.fxtf.org/filter-effects/#elementdef-fedisplacementmap
This filter primitive uses the pixels values from the image from **in2** to spatially displace the image from **in**.
This is the transformation to be performed:

> P'(x,y) ← P( x + scale * (XC(x,y) - .5), y + scale * (YC(x,y) - .5))

The displacement map, **in2**, defines the inverse of the mapping performed.

To sum up the inner mechanics of the displacement filter are these three simple sentences:

Any color value above 127 will shift the corresponding pixel into the direction of the scale value;
Any color value below 127 will shift the corresponding pixel into the opposite direction;
A color value of 127 will have no effect.


Insert cell
To remove the jaggies: https://codepen.io/smashingmag/pen/PojNWwW
Insert cell
https://commons.wikimedia.org/wiki/File:Flowers-04.jpg

https://www.piqsels.com/en/public-domain-photo-stiek/

https://www.piqsels.com/en/public-domain-photo-zkuqa/

Insert cell
img = FileAttachment("Flowers-04.jpg").url()
Insert cell
fil = FileAttachment("piqsels.com-id-zkuqa2.jpg").url()
Insert cell
fil2 = FileAttachment("piqsels@1.com-id-stiek.jpg").url()
Insert cell
viewof scale = Inputs.range([-360, 360], {value: 80, step: 1, label: "Scale"})
Insert cell
<svg class="wrapper" width=${width} height=${imageHeight} xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" version="1.1">
<defs>
<filter id="displacement-filter2" width=${imageWidth} height=${imageHeight} x=${imageWidth*2} y="0" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feImage id='fefi' width=${imageWidth} height=${imageHeight} href=${fil} />
<feDisplacementMap id="fedisplacementmap2" in="SourceGraphic" xChannelSelector="R" yChannelSelector="B" scale=${scale} />
</filter>
</defs>
<image href=${img} x="0" y="0" height="${imageHeight}px" width="${imageWidth}px" />
<image href=${fil} x=${imageWidth} y="0" height="${imageHeight}px" width="${imageWidth}px" />
<image href=${img} class="filter--mona2" x=${imageWidth*2} y="0" height="${imageHeight}px" width="${imageWidth}px" />
</svg>

<style>
.filter--mona2 {
filter: url(#displacement-filter2);
}

.wrapper {
width: ${width}px;
height: 228px;
overflow: visible;
}
</style>
Insert cell
imageWidth = 365
Insert cell
imageHeight = 228
Insert cell
Observable might be able to get this blob
Insert cell
{
const feImage = document.querySelector('#fefi');

fetch(fil)
.then((response) => {
return response.blob();
})
.then((blob) => {
const objURL = URL.createObjectURL(blob);
feImage.setAttribute('href', objURL);
});
}
Insert cell
// FileAttachment("piqsels@1.com-id-stiek.jpg").image()
Insert cell
//FileAttachment("Flowers-04.jpg").image()
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more