Why is a homogeneous gray non-neutral DisplacementMap?

I am trying to create a specific feDisplacementMap map and fail. I believe, because I have a fundamental misunderstanding of the mechanism. The SVG 1.1 specification says:

This filter primitive uses the pixel values ​​from the image from 'in2 to spatially offset the image from' in. This is the transformation to accomplish:

P '(x, y) <- P (x + scale * (XC (x, y) -.5), y + scale * (YC (x, y) -.5)) where P (x, y) is the input image, 'in and P' (x, y) is the destination. XC (x, y) and YC (x, y) are the values ​​of the components of the channel indicated by xChannelSelector and yChannelSelector. For example, to use the R component 'in2 to control the x offset and the G component from Image2 to control the y offset, set xChannelSelector to "R" and yChannelSelector to "G".

According to my data, this means that a neutral gray image should not lead to the absence of movement of pixel pixels. Aka in the filter with a scale = 50, a pixel per 100 100 should get its new value from (100 + 50 * (0.5-0.5), 100 + 50 * (0.5-0.5)) = 100 100 However, when I try to display grayscale, it displays pixels up and to the left of the original image.

<svg width="800px" height="600px" > <defs> <g id="displacerect"> <rect x="50" y="50" width="300" height="300" fill="rgb(127, 127, 127)"/> <rect x="90" y="90" width="50" height="50" fill="red"> </rect> </g> <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" stop-color="rgb(255,255,0)" stop-opacity="1" /> <stop offset="100%"stop-color="rgb(255,0,0)" stop-opacity="1" /> </linearGradient> <filter id="displaceME" x="0%" y="0%" width="100%" height="100%"> <feImage xlink:href="#displacerect" result="displaceImage"/> <feDisplacementMap scale="125" xChannelSelector="R" yChannelSelector="G" in="SourceGraphic" in2="displaceImage"/> </filter> </defs> <g filter="url(#displaceME)"> <rect x="50" y="50" width="300" height="300" fill="url(#grad1)"/> </g> <use xlink:href="#displacerect" x="400"/> </svg> 

According to other sources: ACTUAL neutral movement Map should be as follows:

enter image description here

+5
source share
3 answers

Browsers don't seem to follow the spec for this, and simply duplicate Photoshop's behavior when calculating the offset.

0
source

I see in your example at least one error.

In the <feDisplacementMap> you reference the displacement image ( in2 ) using in2="displacerect" . But there is no filter primitive with this result value. I suppose you mean in2="displaceImage" ?

0
source

I had a similar problem. My original image and the image of my displacement map were the same size, so the neutral displacement image shown above could not be correct. The red channel and the green channel must have the same constant values ​​throughout the image for zero shift. I could not understand why I had to use 188 to change the zero pixel instead of 128, as expected. The blog http://www.tapper-ware.net/blog/?p=39 offered the following hint that solved the problem for me:

 color-interpolation-filters="sRGB" 

The hidden svg code snippet was:

 <svg:filter id="myFilterId" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" x="0" y="0" width="768" height="512"> </svg:filter> 

After specifying the color space, which should be sRGB, it all started as I expected.

0
source

Source: https://habr.com/ru/post/1247831/


All Articles