views:

35

answers:

2

standard scaling using the center of an image as the pivot point and is uniform in all dimensions. I'd like to figure out a way to scale an image from an arbitrary pivot point such that points closer to the pivot point scale less than points away from that point.

+1  A: 

Well, I don't know what framework/library you're using but you can think of it as:

  • translation to make your pivot point the center point
  • standard scaling
  • opposite transalation to make the center point the original pivot point

Translation and scaling are isomorphismes so you can represent them as matrix. Each transformation is a matrix and you can multiply them for find the combined transformation matrix. So:

  • T = transformation
  • S = scalling
  • T' = opposite transformation

If you apply T.x being x a point vector it gives you the new coordinates. The same for S.x.

So if you want to do that operations you have to do: T'. (S. (T.x))

I think you can associate operations so it's the same as (T'.S.T).x

If you are using a framework apply three operations (or combine operations and apply). If you are using crude math... go the matrix way :)

PS: If you are doing this by hand. I know that if you are scaling you will want to find the coordinates of the original point given a transformed point. So you can iterate over the resulting points (each of the pixels) and see what coordinates (or point in between) from the original image you have to use. In that case what you need is the inverse matrix. So instead of using S you want to use S^(-1). If you know that you want to apply T'.S.T you can find this resulting matrix and next find (T'.S.T)^(-1). Then you have your inverse matrix to find original points given the resulting points.

helios
will this make points further from the pivot scale more than points closer to the pivot?
will scale like the fixed point is the pivot point you chosen (the point of coordinates T')
helios
A: 

This is an oversimplification, but should help you get started. For one, since standard resampling is uniform, there isn't really a concept of a pivot-point. If anything, they usually just start from a corner, as it's easier to run the for loops that way.

Generally the algorithm is something like this pseudo-code

function resample (srcImg, dstSize) {
    dstImg = makeImage(dstSize)
    for (r = 0; r < dstSize.height; ++r) {
        for (c = 0; r < dstSize.width; ++c) {
            // getResampleLoc returns float coordinate
            resampleLoc = getResampleLoc(c, r, dstImg.size, srcImg.size)
            color = getColor(srcImg, resampleLoc)
            dstImg.setColor(c, r, color)
        }
    }
    return dstImage
} 

For uniform resampling, getResampleLoc is just a simple scale of x and y from the dstImg size to the srcImg size. It returns float coordinates, which are passed to getColor. The implementation of getColor is what determines the various resampling algorithms. Basically, it blends the pixels surrounding the coordinate in some ratio. In reality, there are optimizations that can be done to make information generated inside of getColor shared between calls, but don't worry about that.

For you, you would need something like:

function resample (srcImg, dstSize, pivotPt) {
    dstImg = makeImage(dstSize)
    for (r = 0; r < dstSize.height; ++r) {
        for (c = 0; r < dstSize.width; ++c) {
            // getResampleLoc returns float coordinate
            resampleLoc = getResampleLoc(c, r, dstImg.size, srcImg.size, pivotPt) 
            color = getColor(srcImg, resampleLoc)
            dstImg.setColor(c, r, color)
        }
    }
    return dstImage
} 

And then you just need to implement getResampleLoc to take pivotPt into account. Probably the simplest thing is to log-scale the distance to the edge.

Lou Franco
that's a great answer thanks. I would like to clarify that I'm only scaling point positions and not pixel information. So imagine a web of point positions and I would like to scale them so that points closer to the pivot point scale less than points away.
Even easier then. You just need getResampleLoc and then iterate over the coordinate pairs instead of having two for loops. Calculate the polar vector from your pivot point, scale it non-linearly (e.g. square it), convert back to Cartesian.
Lou Franco