一切福田,不離方寸,從心而覓,感無不通。

C#:GDI+图像扭曲

DrawImage 时按照目标形状给定矩形框大小即可,下面是MSDN上的代码:

Bitmap myBitmap = new Bitmap("Spiral.png");

Rectangle expansionRectangle = new Rectangle(135, 10,
myBitmap.Width, myBitmap.Height);

Rectangle compressionRectangle = new Rectangle(300, 10,
myBitmap.Width / 2, myBitmap.Height / 2);

myGraphics.DrawImage(myBitmap, 10, 10);
myGraphics.DrawImage(myBitmap, expansionRectangle);
myGraphics.DrawImage(myBitmap, compressionRectangle);

 

 

 

以上图形转换的代码如下,经测试通过,参考了CxImage的源码:

 

 

static int ComputePixel(float x, float y, out float x1, out float y1)
{
double r, nn;

if (x == 0 && y == 0)
{
x1 = x;
y1 = y;
return 1;
}

nn = Math.Sqrt(x * x + y * y);
r = (Math.Abs(x) > Math.Abs(y)) ? Math.Abs(nn / x) : Math.Abs(nn / y);

x1 = (float)(r * x);
y1 = (float)(r * y);

return 1;
}

static Color GetPixelColorInterpolated(ref Bitmap image, float x, float y)
{
int xi = (int)(x);
if (x < 0) xi--;
int yi = (int)(y);
if (y < 0) yi--;

if (xi < -1 || xi >= image.Width || yi < -1 || yi >= image.Height)
{
return GetPixelColorWithOverflow(ref image, -999, -999);
}

//get four neighbouring pixels
if ((xi + 1) < image.Width && xi >= 0 && (yi + 1) < image.Height && yi >= 0)
{
ushort wt1 = (ushort)((x – xi) * 256.0f), wt2 = (ushort)((y – yi) * 256.0f);
ushort wd = (ushort)(wt1 * wt2 >> 8);
ushort wb = (ushort)(wt1 – wd);
ushort wc = (ushort)(wt2 – wd);
ushort wa = (ushort)(256 – wt1 – wc);
ushort wrr, wgg, wbb;

Color clr = image.GetPixel(xi, yi);
wbb = (ushort)(wa * clr.B); wgg = (ushort)(wa * clr.G); wrr = (ushort)(wa * clr.R);

clr = image.GetPixel(xi + 1, yi);
wbb += (ushort)(wb * clr.B); wgg += (ushort)(wb * clr.G); wrr += (ushort)(wb * clr.R);

clr = image.GetPixel(xi, yi + 1);
wbb += (ushort)(wc * clr.B); wgg += (ushort)(wc * clr.G); wrr += (ushort)(wc * clr.R);

clr = image.GetPixel(xi + 1, yi + 1);
wbb += (ushort)(wd * clr.B); wgg += (ushort)(wd * clr.G); wrr += (ushort)(wd * clr.R);

return Color.FromArgb(255, wrr >> 8, wgg >> 8, wbb >> 8);
}
else
{
float t1 = x – xi, t2 = y – yi;
float d = t1 * t2;
float b = t1 – d;
float c = t2 – d;
float a = 1 – t1 – c;

Color rgb11, rgb21, rgb12, rgb22;
rgb11 = GetPixelColorWithOverflow(ref image, xi, yi);
rgb21 = GetPixelColorWithOverflow(ref image, xi + 1, yi);
rgb12 = GetPixelColorWithOverflow(ref image, xi, yi + 1);
rgb22 = GetPixelColorWithOverflow(ref image, xi + 1, yi + 1);

//calculate linear interpolation
return Color.FromArgb(255,
(byte)(a * rgb11.R + b * rgb21.R + c * rgb12.R + d * rgb22.R),
(byte)(a * rgb11.G + b * rgb21.G + c * rgb12.G + d * rgb22.G),
(byte)(a * rgb11.B + b * rgb21.B + c * rgb12.B + d * rgb22.B));
}
}

static Color GetPixelColorWithOverflow(ref Bitmap image, long x, long y)
{
if (!IsInside(ref image, x, y))
{
return Color.FromArgb(255, 255, 255, 255);
}

return image.GetPixel((int)x, (int)y);
}

static bool IsInside(ref Bitmap image, long x, long y)
{
return (0 <= y && y < image.Height && 0 <= x && x < image.Width);
}

private void transformEllipseToolStripMenuItem_Click(object sender, EventArgs e)
{
Bitmap image = new Bitmap("D:\\PSD\\info1.jpg");

int x, y;
float x1, y1;
float fx, fy, xmid, ymid, ar;
Bitmap image2 = new Bitmap(image);

xmid = (float)(image.Width / 2.0);
ymid = (float)(image.Height / 2.0);
ar = (float)(image.Height) / (float)(image.Width);
for (y = 0; y < image.Height; y++)
{
for (x = 0; x < image.Width; x++)
{
ComputePixel(ar * (x – xmid), y – ymid, out fx, out fy);
x1 = xmid + fx / ar;
y1 = ymid + fy;

image2.SetPixel(x, y, GetPixelColorInterpolated(ref image, x1, y1));
}
}

this.pictureBox1.Image = image2;
}

 

 

 

 

from:http://q.cnblogs.com/q/17088/