开发者

Where to get pseudo code algorithm for projecting a RGB parallelogram into an RGB triangle

What would be pseudo code algorithm fo projecting a parallelogram (2d array of (RGB) points) into a triangle (2d array of (RGB) points) (in my particular case a Rectangle into a Right Triangle with same side size (isosceles) and in my case Hypotenuse is same size that has biggest side of a Rectangle) qualyty may be lost. So how to perform such thing in pseudocode?

So generally we had for example 300x200

Where to get pseudo code algorithm for projecting a RGB parallelogram into an RGB triangle

We eant to distort it into 150 height and 200 width triangle

with fireworks CS5 - not cor开发者_如何学编程rect result for me

Where to get pseudo code algorithm for projecting a RGB parallelogram into an RGB triangle

With photoshop CS5 correct result

Where to get pseudo code algorithm for projecting a RGB parallelogram into an RGB triangle

So I wonder what would be pseudocode for transformations photoshop does?


I'm not sure if I am misinterpreting your question, however here are my thoughts. I am assuming that the projection will be such that the hypotenuse of the triangle is oriented in the same direction as the longest side of the rectangle, since you said they will be the same size. Some crude pictures (not to scale):

Rectangle H=4, W=10

---------
|       |
|       |
---------

Triangle Hyp=10, S1=8, S2=6

      .
   .   |
.      |
--------

So my suggestion is to do the mapping such that "blocks" of the rectangle are equated to points with the triangle, and each triangle point is an RGB average of the associated rectangle blocks, noting that the blocks may overlap depending on the scale of the original objects.

More concrete, back to the above example first the ratios, the height ratio will be fixed, the rectangle is height 4, the triangle is height 6, so for each pixel vertically in the triangle consider 6/4, or 1.5 in the rectangle. Now there are two options to deal with the ".5", you could either consider rounding up, or down and using only whole blocks, or you could use weights for fractional sections. Since the latter case is less trivial we will look into it further.

As we move vertically any fractional portion will be converted to a fractional weight of that row's pixel so if we are averaging vertically and our pixels are 128 and 137 (only looking at one component for simplicity) then our average would be

(128+(0.5*137))/1.5 = (128+68.5)/1.5 = 196.5/1.5 = 131

Now, since we are looking fractionally we need to keep track of the fractional portion we haven't used, so if the next pixel above is 100 we would want to look at

((137*0.5)+100)/1.5 = (68.5+100)/1.5 = 168.5/1.5 = 112.3

Now we follow a similar strategy moving line by line vertically up the triangle adjusting the ratio as the width of the triangle decreases, so for the base where hypotenuse=rectangle this would trivially be 1. Farther up you may have a ratio such as 1.23 and can do the calculations as above.

Finally some rough pseudocode:

map(rectangle, triangle) {

  decimal yRatio = triangle.height / rectangle.height
  decimal lastY = 0;//we need decimal indeices for fractional averages

  for each line in dest height (yIndex, 0 based) {
    //here you could even find the average width of the rectangle
    //over the block height, but we won't bother
    decimal xRatio = triangle[yIndex].width / rectangle[floor(yIndex*yRatio)].width
    decimal lastX = 0;    //again a decimal for fractional averages

    for each pixel in dest line width (xIndex, 0 based) {

        decimal pixelAverage = 0;
        decimal tempYRatio = yRatio;
        decimal destY = yRatio * yIndex;

        //Here we calculate the source pixel block average
        while(tempYRatio > 0) {
          //the portion of this row of pixels we use is the minimum
          //of the distance to the next integer, and what we need
          decimal yFraction = minimum(tempYRatio, nextInt(destY) - destY);

          decimal tempXRatio = xRatio;
          decimal destX = xRatio * xIndex;
          while(tempXRatio > 0) {
            decimal xFraction = minimum(tempXRatio, nextInt(destX) - destX);
            //now add the weighted pixel to the average
            average += rectangle[floor(destY)][floor(destX)]*xFraction*yFraction;

            tempXRatio -= xFraction;  //reduce the block size
            destX += xFraction;       //and shift the source index
          }

          tempYRatio -= yFraction;  //reduce the block size
          destY += yFraction;       //and shift the source index
        }

        destination[yIndex][xIndex] = average / (xRatio*yRatio);
    }
  }
}
//a helper function to find the next integer value
integer nextInt(decimal d) {
  integer ret = ceiling(d);
  return d == ret ? d+1 : ret;
}

This is off the top of my head, so I can't guarantee it is completely correct, but it should be a good start at the very least performing the averages as appropriate with each of the RGB components of the individual pixels.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜