开发者

Image scaling geometry

This is very programming related but a somewhat non-programming question. I am performing image scaling in a web based application and I need to maintain my image relative to a fixed location even though it scales anchored by its top, left corner. Hope the graphic make this possible.

Image scaling geometry

The idea is that C is a fixed location that I want to maintain as my scaling origin rather than B which which is the current css behavior. C may or may not be within the actual image. So as the image scale, B needs to move relative to C. Example: if the image was scaled 50%, then B would move 1/2 the distance to C. If the image grew to 200% of its size, then B would move twice the distance away from C.

Ultimately looking for a formula for x & y for B given the location of C and a scaling factor for the im开发者_如何学JAVAage. Not sure the size of the image needs to be part of this but I have it if needed.

Thanks for any help!

Things I know:

  1. I know the width and height of the image rectangle.
  2. I know the offset of B from A.
  3. I know the offset of C from A.
  4. I know the scale factor in percent of the image.


Effectively, you want to treat C as the origin, and just "move" B by the scaling amount. By treating it as a vector from C to B, and scaling it by the amount in question, you can do this fairly easily.

newBx = Cx - (Cx - Bx) * scale;
newBy = Cy - (Cy - By) * scale;

For example, with a scale of 0.5 (50%), this becomes:

newBx = 100 - (100 - 50) * 0.5 
      = 100 - 25
      = 75                 // 1/2 the distance to C
newBy = 100 - (100 - 25) * 0.5
      = 100 - 37.5
      = 62.5               // 1/2 the distance to C

With a scale of 2 (200%):

newBx = 100 - (100 - 50) * 2 
      = 100 - 100
      = 0                  // 2x the distance to C
newBy = 100 - (100 - 25) * 2
      = 100 - 150
      = -50                // 2x the distance to C


First you need to calculate the distance from B to C, then you just change that to scale, and that is where the new B is relative to C:

newB = C - (C - B) * scale

As you want the coordinates, it's the same function for x and y:

newBx = Cx - (Cx - Bx) * scale
newBy = Cy - (Cy - By) * scale

(The scale value used is not percentage but a size multiplier. An increase in size by 50% gives a scale of 1.5.)


So you want point C in the image which is currently at (C_x, C_y) to remain at the same position after scaling the image by a factor of s?

New position of C, say, C_new = (s*C_x,s*C_y).

And you want to move the image so that C_new = C.

Which means you'll have to shift B = (B_x,B_y) by (s*C_x-C_x,s*C_y-C_y), or the new origin of the image, say B_new is:

B_new = (B_x + s*C_x-C_x,  B_y + s*C_y-C_y)

So now you can display the scaled image at B_new --- and C should remain fixed.


If I understand the problem:

X(b) = X(c) - Width*(1/3)    
Y(b) = Y(c) - Height*(3/4)

The formula seems simple enough, but your sample image can't get any larger than 133x200 (scale = 133%) before it overruns Y=0 (which I assume is your northern limit).

If you want to stop it from moving past Y=0 or X=0, and push-out further to the south and east once it reaches either limit, one approach might be:

IIF(Height > 133, Y(b) = 0, Y(b) = Y(c) - Height*(3/4))
IIF(Width > 450, X(b) = 0, X(b) = X(c) - Width*(1/3))

I think scale should be converted to height and width, instead of using scale as a variable in these formulas, since your original image could be any size (assuming they're not always going to be 100x150 per your sample)

  • dave


here's a C# snippet that is tested to work:

void Main()
{
    Application.Run(new form1());
}

public class form1 : Form
{
    static Point C = new Point(100,100);
    static Point origLocB = new Point(50,25);
    static Size origSizeB = new Size(150,100);

    Panel Rec = new Panel() 
    {
        Left = origLocB.X, 
        Top = origLocB.Y, 
        Width = origSizeB.Width, 
        Height = origSizeB.Height,
        BorderStyle = BorderStyle.FixedSingle,
    };

    NumericUpDown nud = new NumericUpDown()
    {
        Value = 1M,
        Increment = .01M,
        DecimalPlaces = 2,
        Dock = DockStyle.Bottom,
    };

    public form1()
    {
        nud.ValueChanged += NumericUpDown_ValueChanged;
        Controls.Add(nud);
        Controls.Add(Rec);
    }

    public void NumericUpDown_ValueChanged(object sender, EventArgs e)
    {
        Rec.Location = new Point(((int)((origLocB.X - C.X) * nud.Value + C.X)),
                                ((int)((origLocB.Y - C.Y) * nud.Value + C.Y)));
        Rec.Size = new Size((int)(origSizeB.Width*nud.Value),
                            (int)(origSizeB.Height*nud.Value));
    }
}

it really just echo's @Reed's Answer

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜