0

I've an WPF Image control, which use scale shader for zooming around center of the image (ScaleCenter is always 0.5,0.5). But for zooming around specific point on the image (cursor) I guess i should apply some offests to keep the same image pixel under cursor.

I've this code which is works perfect untill Scaleshader < 1.

public void ScalePoint(double zoomFactor, Point point, Image ImageViewElement, bool pushOperation = false)
{
    double w = ImageViewElement.ActualWidth;
    double h = ImageViewElement.ActualHeight;

    double cx = w * 0.5;
    double cy = h * 0.5;
    double dx = point.X - cx;
    double dy = point.Y - cy;

    double contentX = (OffsetX + dx) / ScaleShader;
    double contentY = (OffsetY + dy) / ScaleShader;

    OffsetX = contentX * ScaleShader * zoomFactor - dx;
    OffsetY = contentY * ScaleShader * zoomFactor - dy;

    var m = new Matrix();
    m.Translate(-OffsetX, -OffsetY);
    RenderTransform = new TransformGroup { Children = { new MatrixTransform(m) } };

    ScaleShader *= zoomFactor;
}

When the ScaleShader becomes > 1 - these offsets OffsetX and OffsetY - I guess calculating in a wrong way.

Could you give me some hint on how this parameters should be calculated for any scaleShader values? (I cannot use only matrix transform/scale, because the image sizes are big, so we should use Shader but as I said, scale_center is always 0.5,05 and it cannot be changed because it is used in other parts of the software.

shader code

sampler2D inputSampler : register(S0);
sampler2D inputNNSampler : register(S1);
float scale : register(C0);
float2 scale_center : register(C1); // always (0.5, 0.5)
float scaling_mode : register(C2);

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float2 ray = uv - scale_center;
    uv = scale_center + ray / scale;

    if (uv.x < 0 || uv.y < 0 || uv.x > 1 || uv.y > 1)
        return 0;

    return scaling_mode > 0
        ? tex2D(inputNNSampler, uv)
        : tex2D(inputSampler, uv);
}
4
  • There is some ambiguity in what you mean by the transformation center. In WPF, the transformation center is set in the RenderTransformOrigin property. At the same time, in the ScaleTransform transformation, there is also a center set by the CenterX / Y properties. Which of these centers do you mean? Also, in ScaleTransform, after setting ScaleX/Y and CenterX/Y, you can get the transformation matrix from the Value property. Have you checked it? Perhaps this is the matrix you need for your shader. Commented Jul 14 at 9:45
  • Zooming in and out with WPF can be frustrating. Maybe this post can give you some ideas: stackoverflow.com/questions/79667806/… Commented Jul 30 at 15:07
  • @EldHasp Thanks for the suggestion! I see what you mean — RenderTransformOrigin and CenterX / CenterY in ScaleTransform define the transformation center in WPF. However, in my case, I'm not using WPF transforms to define the zoom behavior. The actual scaling is done in a pixel shader (ShaderEffect) that operates on UV coordinates. I want the zoom to happen around the mouse cursor, so that the pixel under the cursor stays fixed during zoom. Because of that, I need to manually compute the offset for the RenderTransform to compensate for the shift introduced by scaling. Commented Jul 31 at 23:50
  • @DraganRadovac Thanks, that's exactly right. The code I posted works the way I want — but only until the offset gets close to the image’s ActualWidth or ActualHeight (at least that’s how it seems). After that, the offset logic probably needs to change, since the image starts drifting from the cursor. Seems like there’s some nonlinear behavior involved, though I haven’t figured it out yet. P.S. I always knew A4, A3 sizes etc., but never noticed the aspect ratio is always √2 — kind of cool! Commented Aug 1 at 0:04

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.