How can I transform XY coordinates and height/width on a scaled image to an original sized image?

前端 未结 2 954
情歌与酒
情歌与酒 2020-12-14 10:32

Related Question

I am trying to do the same thing as in the linked question, but with C#. I am showing a scaled image and am allowing a user to select an area to cro

相关标签:
2条回答
  • 2020-12-14 11:20

    You can get the percent locations for the scaled images and turn them back into coords for the unscaled image:

    pX1 = scaledX1/scaled_width
    pY1 = scaledY1/scaled_height
    
    unscaledX1 = ceiling(unscaled_width * pX1)
    unscaledY1 = ceiling(unscaled_height * pY1)
    
    0 讨论(0)
  • 2020-12-14 11:31

    Without a bit more detail, I'm guessing that you're actually suffering from rounding errors...
    - When you scale the (top,left) co-ordinate back to the original, you need to round down (towards the top left).
    - When you scale the (bottom,right) co-ordinate back to the original, you need to round up (towards the bottom right)

    Take a simple example of a 12x12 grid as the original, and a 4x4 grid as the scaled version.
    - (1,1):(2,2) on the scaled version = (3,3):(8,8)
    - 2x2 pixel = 25% of the area of the scaled version
    - 6x6 pixel = 25% of the area of the original version

    If one was to simply multiply by the same scaling factors, this would give (3,3):(6,6).


    OriginalTop = INT(ScaledTop * YScalingFactor);
    OriginalLeft = INT(ScaledLeft * XScalingFactor);

    OriginalBottom = INT((ScaledBottom + 1) * YScalingFactor) - 1;
    OriginalRight = INT((ScaledRight + 1) * XScalingFactor) - 1;


    EDIT:

    A better way of explaining what I'm trying to say would be to draw a picutre. And I suck at ASCII Art. So here's another try with words.

    A pixel isn't a point. It's a small rectangle in it's own right.

    When you use a pixel to represent the top left of a rectangle, you're including the area from the top-left most Point of the pixel.

    When you use a pixel to represent the Bottom Right of a rectangle, you're including the area all the way to the Bottom Right most Point of the pixel.


    Using the (12x12) => (4x4) example again, every scaled pixel represents a whole 3x3 set of pixels in the original. When talking about the top left, you pick the top left pixel of the 3x3 pixel group in the original. And when talking about the bottom right, you pick the bottom right of the 3x3 pixel group in the original.


    EDIT: Using just integers.

    NewTop    = ((   OldTop    ) * NewHeight / OldHeight);
    NewLeft   = ((   OldLeft   ) * NewWidth  / OldWidth );
    
    NewBottom = ((OldBottom + 1) * NewHeight / OldHeight) - 1;
    NewRight  = ((OldRight  + 1) * NewWidth  / OldWidth ) - 1;
    


    The only consideration is making sure that you don't overflow your data type after the multiplication. But with images, you won't, unless it's a hell of an image.

    0 讨论(0)
提交回复
热议问题