As in the comments, I am not sure about a many-sided polygon. However, to transform one quadrilateral to another, you can use a projective transform. This maps a quad made of four points to another quad of four points. (I originally found out about this when I asked this SO question.)
You:
- Use the Transform method
- Pass in a target and source bitmap
- Pass in a projective transformation object, initialised with the destination points
- Pass in a rasterizer, which controls how the output pixel is made from the one or more input pixels
The rasterizer at least is optional, but you will get higher-quality output by specifying a high quality (slower) rasterizer chain other than the default. There are other optional parameters too.
They key is the TProjectiveTransformation
object. Unfortunately, the Graphics32 documentation seems to be missing an entry for the Transform method
, so I can't link to that. However, here is some untested example code, based on some code of mine. It transforms a rectangular source image to a convex quadrilateral on the target image:
var
poProjTransformation : TProjectiveTransformation;
poRasterizer : TRegularRasterizer;
oTargetRect: TRect;
begin
// Snip some stuff, e.g. that
// poSourceBMP and poTargetBMP are TBitmap32-s.
poProjTransformation := TProjectiveTransformation.Create();
poRasterizer := TRegularRasterizer.Create();
// Set up the projective transformation with:
// the source rectangle
poProjTransformation.SrcRect = FloatRect(TRect(...));
// and the destination quad
// Point 0 is the top-left point of the destination
poProjTransformation.X0 = oTopLeftPoint.X();
poProjTransformation.Y0 = oTopLeftPoint.Y();
// Continue this for the other three points that make up the quad
// 1 is top-right
// 2 is bottom-right
// 3 is bottom-left
// Or rather, the points that correspond to the (e.g.) top-left input point; in the
// output the point might not have the same relative position!
// Note that for a TProjectiveTransformation at least, the output quad must be convex
// And transform!
oTargetRect := TTRect(0, 0, poTarget.Width, poTarget.Height)
Transform(poTargetBMP, poSourceBMP, poProjTransformation, poRasterizer, oTargetRect);
// Don't forget to free the transformation and rasterizer (keep them around though if
// you're going to be doing this lots of times, e.g. on many images at once)
poProjTransformation.Free;
poRasterizer.Free;
The rasterizer is an important parameter for image quality - the above code will give you something that works but isn't pretty, because it will use nearest-neighbour sampling. You can build a chain of objects to give better results, such as using a TSuperSampler
with the TRegularRasterizer
. You can read about samplers and rasterizers and how to combine them here.
There are also about five different overloads for the Transform
method, and it's worth skim-reading them in the interface of the GR32_Transforms.pas
file so you know what versions you can use.