/// <summary> /// 比率 s,t を求める /// </summary> /// <param name="p">形状変形パラメータ</param> /// <param name="s">[out]比率(横方向)</param> /// <param name="t">[out]比率(縦方向)</param> /// <returns>true:範囲内, false:範囲外</returns> private static bool ResolveEqu(TfParam p, out double s, out double t) { s = -1.0; t = -1.0; double sa = -1.0; double ta = -1.0; double sb = -1.0; double tb = -1.0; double p1 = (p.a * p.h - p.f * p.c); double p2 = (p.d * p.f - p.c * p.g + p.b * p.h - p.a * p.e); double p3 = (p.d * p.g - p.b * p.e); double tm; if (p1 == 0.0) { s = (p.d / p.b); t = (p.b * p.e - p.d * p.g) / (p.b * p.h + p.d * p.f); //return true; } else if (Resolve2Equ(p1, p2, p3, out ta, out tb)) { tm = (p.a * ta + p.b); if (tm != 0.0) { sa = (p.d - p.c * ta) / tm; } tm = (p.a * tb + p.b); if (tm != 0.0) { sb = (p.d - p.c * tb) / tm; } if ((0 <= sa && sa <= 1.0) && (0 <= ta && ta <= 1.0)) { s = sa; t = ta; } else if ((0 <= sb && sb <= 1.0) && (0 <= tb && tb <= 1.0)) { s = sb; t = tb; } } return(s != -1.0 && t != -1.0); }
/// <summary> /// 変形処理 /// </summary> /// <param name="srcImg">元画像</param> /// <param name="destImg">[out] 変形後画像</param> /// <param name="pt">変形後画像の頂点情報</param> /// <returns>true:成功, false:失敗</returns> public static bool Transform(Bitmap srcImg, out Bitmap destImg, List <Point> pt) { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Reset(); sw.Start(); destImg = null; BitmapByte srcByte = new BitmapByte(); BitmapByte destByte = new BitmapByte(); Color pxCol = Color.FromArgb(0, 0, 0, 0); Color bgCol = Color.FromArgb(0, 0, 0, 0); TfParam p = new TfParam(); int calcWidth, calcHeight; int destWidth, destHeight; double xa, ya, xb, yb, xc, yc, xd, yd; double s, t; // 対象画素の元画像に対する比率 (0 <= s,t <=1) double tx, ty; // 変形後の座標 try { destWidth = pt[0].X; destHeight = pt[0].Y;; for (int i = 1; i < pt.Count; i++) { if (destWidth < pt[i].X) { destWidth = pt[i].X; } if (destHeight < pt[i].Y) { destHeight = pt[i].Y; } } destWidth++; destHeight++; destImg = new Bitmap(destWidth, destHeight); destByte.LockBitmap(destImg, ImageLockMode.WriteOnly); srcByte.LockBitmap(srcImg, ImageLockMode.ReadOnly); calcWidth = srcByte.Width - 1; calcHeight = srcByte.Height - 1; // 頂点データは反時計回りだが、パラメータには時計回りでセットする xa = pt[0].X; ya = pt[0].Y; xb = pt[3].X; yb = pt[3].Y; xc = pt[2].X; yc = pt[2].Y; xd = pt[1].X; yd = pt[1].Y; p.a = (xc - xd - xb + xa); p.b = (xb - xa); p.c = (xd - xa); p.f = (yc - yd - yb + ya); p.g = (yb - ya); p.h = (yd - ya); for (int y = 0; y < destHeight; y++) { for (int x = 0; x < destWidth; x++) { p.d = (x - xa); p.e = (y - ya); if (ResolveEqu(p, out s, out t) == false) { SetPixelByte(destByte, x, y, bgCol); continue; } //if ((0 <= s && s <= 1.0) && (0 <= t && t <= 1.0)) //{ tx = s * calcWidth; ty = t * calcHeight; //} if (Interpolate(srcByte, tx, ty, ref pxCol)) { SetPixelByte(destByte, x, y, pxCol); } else { SetPixelByte(destByte, x, y, bgCol); } } } destByte.MarshalCopy(); } catch (Exception ex) { return(false); } finally { try { if (srcByte != null) { srcByte.UnlockBitmap(); } } finally { if (destByte != null) { destByte.UnlockBitmap(); } } sw.Stop(); Console.WriteLine("Transform time: {0}", sw.ElapsedMilliseconds); } return(true); }