views:

443

answers:

2

Hi All, I want an efficient algorithm to fill polygon with an Image, I want to fill an Image into Trapezoid. currently I am doing it in two steps
1) First Perform StretchBlt on Image,
2) Perform Column by Column vertical StretchBlt,

Is there any better method to implement this? Is there any Generic and Fast algorithm which can fill any polygon?

Thanks, Sunny

+1  A: 

I can't help you with the distortion part, but filling polygons is pretty simple, especially if they are convex.

For each Y scan line have a table indexed by Y, containing a minX and maxX.

For each edge, run a DDA line-drawing algorithm, and use it to fill in the table entries.

For each Y line, now you have a minX and maxX, so you can just fill that segment of the scan line.

The hard part is a mental trick - do not think of coordinates as specifying pixels. Think of coordinates as lying between the pixels. In other words, if you have a rectangle going from point 0,0 to point 2,2, it should light up 4 pixels, not 9. Most problems with polygon-filling revolve around this issue.

ADDED: OK, it sounds like what you're really asking is how to stretch the image to a non-rectangular shape (but trapezoidal). I would do it in terms of parameters s and t, going from 0 to 1. In other words, a location in the original rectangle is (x + w0*s, y + h0*t). Then define a function such that s and t also map to positions in the trapezoid, such as ((x+t*a) + w0*s*(t-1) + w1*s*t, y + h1*t). This defines a coordinate mapping between the two shapes. Then just scan x and y, converting to s and t, and mapping points from one to the other. You probably want to have a little smoothing filter rather than a direct copy.

ADDED to try to give a better explanation: I'm supposing both your rectangle and trapezoid have top and bottom edges parallel with the X axis. The lower-left corner of the rectangle is <x0,y0>, and the lower-left corner of the trapezoid is <x1,y1>. I assume the rectangle's width and height are <w,h>. For the trapezoid, I assume it has height h1, and that it's lower width is w0, while it's upper width is w1. I assume it's left edge "slants" by a distance a, so that the position of its upper-left corner is <x1+a, y1+h1>. Now suppose you iterate <x,y> over the rectangle. At each point, compute s = (x-x0)/w, and t = (y-y0)/h, which are both in the range 0 to 1. (I'll let you figure out how to do that without using floating point.) Then convert that to a coordinate in the trapezoid, as xt = ((x1 + t*a) + s*(w0*(1-t) + w1*t)), and yt = y1 + h1*t. Then <xt,yt> is the point in the trapezoid corresponding to <x,y> in the rectangle. Now I'll let you figure out how to do the copying :-) Good luck.

P.S. And please don't forget - coordinates fall between pixels, not on them.

Mike Dunlavey
Hi Mike, I know how to do Polygon Fill, Can u please explain me how can I do Image fill in Polygon.
Sunny
Hi Mike, Thanks for your reply, I have implemented trapezoid blt but I think ur method is looking optimized than mine. I can't understand your "coordinate mapping between the two shapes" funda. Can u explain it in better way or can you give me some reference to explore it more.
Sunny
+1  A: 

Would it be feasible to sidestep the problem and use OpenGL to do this for you? OpenGL can render to memory contexts and if you can take advantage of any hardware acceleration by doing this that'll completely dwarf any code tweaks you can make on the CPU (although on some older cards memory context rendering may not be able to take advantage of the hardware).

If you want to do this completely in software MESA may be an option.

Cruachan