Lazarus Lang
12/23/2004 12:14:00 PM
"Craig Parsons" <craig.parsons@hicpx.com> wrote in message
news:41b4011b$0$9327$ed2619ec@ptn-nntp-reader02.plus.net...
> I have a scanned image which is circular, and contains a trace in the
> middle of it (for those of you familar with trucks it is a tachograph
> chart!).
>
> I want to "flatten" it out, into a straight line. I can't seem to
find
> any controls which might be able to do this for me.
>
> Does anyone have any ideas, or will I have to write some code to do it
> pixel by pixel??
Yup, pixel by pixel. I couldn't help myself and quickly wrote it.
If I feed this a bitmap with a circle at the center, it returns a bitmap
with
a straight line so I guess it works. (No guarantees though !) :
public static Bitmap UnCircularWarp(Bitmap cb) 'cb stands for circular
bitmap
{
int width = Math.Min(cb.Width, cb.Height);
Bitmap bTemp = new Bitmap((width << 1) + 1, (width >> 1) + 1,
cb.PixelFormat);
double r = width / 2.0f;
for (int x = 0; x < bTemp.Width; ++x)
{
// as X goes from 0 to bTemp.width, alpha goes from PI to -PI
double alpha = Math.PI - Math.PI * 2.0d * (double)x / (double)bTemp.Width;
double cosA = Math.Cos(alpha);
double sinA = Math.Sin(alpha);
for (int y = bTemp.Height - 1; y >= 0; y--)
{
bTemp.SetPixel(
x,
y,
cb.GetPixel(
(int)(Math.Floor(r + (double)y * cosA)), ' circular transform to
determine pos. in circular bitmap
(int)(Math.Floor(r - (double)y * sinA)) ' circular transform to
determine pos. in circular bitmap
)
);
}
}
return bTemp;
}
Basically this creates a bitmap, half the height of the original bitmap (and
twice the width to make
sure that we have enough pixels to show the result.) Then it walks across
the destination (i.e.
unwarped bitmap) and calculates which position this corresponds to in the
cirular (i.e. original)
bitmap. The formula for the inverse image coordinate transform is simply a
circular mapping (i.e.
x = centerX + radius*cos(alhpa)
y = centerY + radius*sin(alpha)
adapted for screen coordinates (where 0,0 lies at the top left instead of
the bottom left)
Keep in mind that this is *hugely* inefficient. SetPixel is not really a
great way to do image warping.
Ideally you'd want to write this in C(++) for speed.
Have fun.
L2