Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I render a square bitmap to an arbitrary four-sided polygon using GDI?

I need to paint a square image, mapped or transformed to an unknown-at-compile-time four-sided polygon. How can I do this?

Longer explanation

The specific problem is rendering a map tile with a non-rectangular map projection. Suppose I have the following tile:

Square tile

and I know the four corner points need to be here:

Four distorted corners

Given that, I would like to get the following output:

Distorted, image-mapped polygon

The square tile may be:

  • Rotated; and/or
  • Be narrower at one end than at the other.

I think the second item means this requires a non-affine transformation.

Random extra notes

Four-sided? It is plausible that to be completely correct, the tile should be mapped to a polygon with more than four points, but for our purposes and at the scale it is drawn, a square -> other four-cornered-polygon transformation should be enough.

Why preferably GDI only? All rendering so far is done using GDI, and I want to keep the code (a) fast and (b) requiring as few extra libraries as possible. I am aware of some support for transformations in GDI and have been experimenting with them today, but even after experimenting with them I'm not sure if they're flexible enough for this purpose. If they are, I haven't managed to figure it out, and so I'd really appreciate some sample code.

GDI+ is also ok since we use it elsewhere, but I know it can be slow, and speed is important here.

One other alternative is anything Delphi- / C++Builder-specific; this program is written mostly in C++ using the VCL, and the graphics in question are currently painted to a TCanvas with a mix of TCanvas methods and raw WinAPI/GDI calls.

Overlaying images: One final caveat is that one colour in the tile may be for color-key transparency: that is, all the white (say) squares in the above tile should be transparent when drawn over whatever is underneath. Currently, tiles are drawn to square or axis-aligned rectangular targets using TransparentBlt.

I'm sorry for all the extra caveats that make this question more complicated than 'what algorithm should I use?' But I will happily accept answers with only algorithmic information too.

like image 550
David Avatar asked Mar 07 '12 20:03

David


2 Answers

You might also want to have a look at Graphics32. The screen shot bewlow shows how the transfrom demo in GR32 looks like

like image 131
iamjoosy Avatar answered Oct 27 '22 04:10

iamjoosy


Take a look at 3D Lab Vector graphics. (Specially "Football field" in the demo).


Another cool resource is AggPas with full source included (download)

AggPas is Open Source and free of charge 2D vector graphics library. It is an Object Pascal native port of the Anti-Grain Geometry library - AGG, originally written by Maxim Shemanarev in C++. AggPas doesn't depend on any graphic API or technology. Basically, you can think of AggPas as of a rendering engine that produces pixel images in memory from some vectorial data.

Here is how the perspective demo looks like:

enter image description here

After transformation:

enter image description here

like image 6
kobik Avatar answered Oct 27 '22 05:10

kobik