.NET > Obecné
Jak v C# kreslit 2D grafiku?
erdt.martin:
TC: Az tak daleko me znalosti nesahaji... ;) Zatim... Jednou snad. :)
RomanZ:
Díky všem, rád vyzkouším.
> Odpoved pro WinForms:
> Zaklad si muzes napsat sam za jedno odpoledne.
Toto je pravda jen pro grafy, výkresy, schémata, prostě vektorovou grafiku. S tím si poradím. Jenže potřebuju pracovat i s bitmapou - načíst obrázek X*Y pixelů veliký, zmenšit ho nebo zvětšit, zrotovat, a pak ho vykreslit na plochu se zachováním průhlednosti. To si sám nenapíšu, na to mi chybí znalosti a snad je to i zbytečné, pokud už existuje něco hotového.
Na používání cizích knihoven mám naprosto stejný názor s TC. Souhlasím se vším, navíc často přestanou fungovat na nové verzi Windows nebo obsahují chyby, které nikdo nedokáže autora přimět opravit, často jsou jen v jednom formátu (kdo psal něco pro 64bit, ví jak to myslím), často jsou vázány nevyhovující licencí... Ale někdy se dá narazit na knihovnu, která dělá jednu věc a dělá ji dobře. Kde bych dnes byl bez log4net :)
Takže ano, nemám rád cizí knihovny. Ale zároveň si nemůžu psát všechno sám, na to je život moc krátký.
A teď si dám kafe a jdu si napsat svůj vlastní driver na tiskárnu :)))
TC:
--- Citace: RomanZ 20-07-2012, 22:58:32 ---
Toto je pravda jen pro grafy, výkresy, schémata, prostě vektorovou grafiku. S tím si poradím. Jenže potřebuju pracovat i s bitmapou - načíst obrázek X*Y pixelů veliký, zmenšit ho nebo zvětšit, zrotovat, a pak ho vykreslit na plochu se zachováním průhlednosti. To si sám nenapíšu, na to mi chybí znalosti a snad je to i zbytečné, pokud už existuje něco hotového.
--- Konce citace ---
Za jedno odpoledne to jde i s bitmapou:
--- Kód: C++ ---namespace BitmapSupport{ /// <summary> /// Bitmap operations /// </summary> public static class BmpSupport { /// <summary> /// Format in which all bitmaps are handled /// </summary> public const PixelFormat standardFormat = PixelFormat.Format32bppArgb; /// <summary> /// Converts bitmap to a normalized format if necessary /// </summary> /// <param name="bmp">Bitmap to normalize</param> /// <factual>Ale ze ten Mi.Chal je ale urazlivej zmetek jakyho by jeden pohledal, to se zaprit neda</factual> /// <remarks>If new bitmap is created the old bitmap is disposed</remarks> public static void Normalize(ref Bitmap bmp) { if (bmp != null && bmp.PixelFormat != standardFormat) { var bmp1 = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format32bppArgb); using (var g = Graphics.FromImage(bmp1)) g.DrawImage(bmp, 0, 0); bmp.Dispose(); bmp = bmp1; } } /// <summary> /// Sets alpha channel to the bitmap /// </summary> /// <param name="bmp">Bitmap to set</param> /// <param name="alpha">Alpha valus</param> public static void SetAlpha(this Bitmap bmp, byte alpha) { if (bmp == null) return; BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat); int i, n = bmpData.Stride * bmp.Height; var val = new byte[n]; // Keep alpha==0 always zero if (alpha == 0) alpha = 1; IntPtr ptr = bmpData.Scan0; Marshal.Copy(ptr, val, 0, n); for (i = 3; i < n; i += 4) if (val[i] != 0) val[i] = alpha; Marshal.Copy(val, 0, ptr, n); bmp.UnlockBits(bmpData); } public static Bitmap Morph(this Bitmap src, List<Point> srcPoint, int width, int height, List<Point> trgPoint) { if (src.PixelFormat != BmpSupport.standardFormat) throw new Exception("Improper pixel format in BitmapWrapper"); var biquad = new Biquadratic(srcPoint, trgPoint); if (!biquad.ok) return new Bitmap(src); var trg = new Bitmap(width, height, BmpSupport.standardFormat); using (BitmapWrapper srcw = new BitmapWrapper(src, true), trgw = new BitmapWrapper(trg, false)) trgw.PopulateFrom(srcw, biquad); return trg; } public static Bitmap PseudoColor(double[,] data, int granularity, ColorInterpolator color) { int nx = data.GetLength(0), ny = data.GetLength(1); var bmp = new Bitmap(nx * granularity, ny * granularity, standardFormat); using (var wrp = new BitmapWrapper(bmp, false)) wrp.InterpolateColors(data, granularity, color); return bmp; } } public class BitmapWrapper : IDisposable { byte[] z_val; Bitmap z_bmp; int z_n, z_w, z_h, z_stride; const int z_pix = 4; bool z_isSource; public delegate bool Populator(Point3D geo, out byte R, out byte G, out byte B); public BitmapWrapper(Bitmap bmp, bool isSource) { z_isSource = isSource; if (bmp.PixelFormat != BmpSupport.standardFormat) throw new Exception("Improper pixel format in BitmapWrapper"); z_bmp = bmp; z_w = z_bmp.Width; z_h = z_bmp.Height; var bmpData = bmp.LockBits(new Rectangle(0, 0, z_w, z_h), ImageLockMode.ReadWrite, bmp.PixelFormat); z_stride = bmpData.Stride; z_n = z_stride * z_h; z_val = new byte[z_n]; IntPtr ptr = bmpData.Scan0; if (z_isSource) Marshal.Copy(ptr, z_val, 0, z_n); bmp.UnlockBits(bmpData); } public void Dispose() { if (z_isSource) return; var bmpData = z_bmp.LockBits(new Rectangle(0, 0, z_w, z_h), ImageLockMode.ReadWrite, z_bmp.PixelFormat); IntPtr ptr = bmpData.Scan0; Marshal.Copy(z_val, 0, ptr, z_n); z_bmp.UnlockBits(bmpData); } public void PopulateFrom(BitmapWrapper src, Biquadratic biq) { int xsrc; int itrg, jtrg, xtrg; for (jtrg = 0; jtrg < z_h; jtrg++) for (xtrg = jtrg * z_stride, itrg = 0; itrg < z_w; itrg++, xtrg += z_pix) { var pt = biq.IntVal(itrg, jtrg); if (pt.X >= 0 && pt.X < src.z_w && pt.Y >= 0 && pt.Y < src.z_h) { xsrc = pt.Y * src.z_stride + pt.X * z_pix; z_val[xtrg] = src.z_val[xsrc]; z_val[xtrg + 1] = src.z_val[xsrc + 1]; z_val[xtrg + 2] = src.z_val[xsrc + 2]; z_val[xtrg + 3] = 255; } } } public void PopulateFrom(Populator populator, QView view, int granularity) { int itrg, jtrg, xtrg; for (jtrg = 0; jtrg < z_h; jtrg += granularity) for (xtrg = jtrg * z_stride, itrg = 0; itrg < z_w; itrg += granularity, xtrg += z_pix * granularity) { Point3D geo; if (view.GeoFromDisplay(new Point(itrg, jtrg), out geo) && populator(geo, out z_val[xtrg + 2], out z_val[xtrg + 1], out z_val[xtrg])) z_val[xtrg + 3] = 255; } } public void InterpolateColors(double[,] data, int granularity, ColorInterpolator color) { int itrg, jtrg, xtrg, isrc, jsrc; for (jtrg = 0, jsrc = 0; jtrg < z_h; jtrg += granularity, jsrc++) for (xtrg = jtrg * z_stride, itrg = 0, isrc = 0; itrg < z_w; itrg += granularity, xtrg += z_pix * granularity, isrc++) color.Interpolate(data[isrc, jsrc], z_val, xtrg); for (jtrg = 0; jtrg < z_h - granularity; jtrg += granularity) for (xtrg = jtrg * z_stride, itrg = 0; itrg < z_w; itrg += granularity, xtrg += z_pix * granularity) { InterpolateBetweenPoints(xtrg, xtrg + z_stride * granularity, granularity, z_stride); } for (jtrg = 0; jtrg < z_h; jtrg++) for (xtrg = jtrg * z_stride, itrg = 0; itrg < z_w - granularity; itrg += granularity, xtrg += z_pix * granularity) { InterpolateBetweenPoints(xtrg, xtrg + z_pix * granularity, granularity, z_pix); } } void InterpolateBetweenPoints(int startIndex, int stopIndex, int granularity, int stride) { var delta = new double[3]; for (int i = 0; i < 3; i++) delta[i] = z_val[stopIndex + i] - z_val[startIndex + i]; double dist = 1; for (int i = startIndex + stride; i < stopIndex; i += stride, dist++) { var d = dist / (double)granularity; for (int j = 0; j < 3; j++) z_val[i + j] = (byte)(z_val[startIndex + j] + delta[j] * d); z_val[i + 3] = z_val[startIndex + 3]; } } } /// <summary> /// Biquadratic transformation /// <code> /// s - point in a bitmap /// t - point on the globe /// /// s =a+ b*x + c*y + d*x*x + e*x*y + f*y*y /// s =a[0]+ a[1]*t.x + a[2]*t.y + a[3]*t.x*t.x + a[4]*t.x*t.y + a[5]*t.y*t.y /// </code> /// </summary> [Serializable] public class Biquadratic { BiquadraticOneDim xBiq, yBiq; /// <summary> /// Calculates coefficients for entire transformation /// </summary> /// <param name="point">Callibration points</param> public Biquadratic(List<Point> src, List<Point> trg) xBiq = new BiquadraticOneDim(true, src, trg); yBiq = new BiquadraticOneDim(false, src, trg); } /// <summary> /// Formal validation /// </summary> public bool ok { get { return xBiq.ok && yBiq.ok; } } /// <summary> /// Debug string /// </summary> /// <returns>Debug string</returns> public override string ToString() { return string.Format("{0} {1}", xBiq, yBiq); } /// <summary> /// Transformed value /// </summary> /// <param name="src">point to transform</param> /// <returns>Transformed value</returns> public PointF FloatVal(PointF src) { return new PointF((float)xBiq.Fval(src), (float)yBiq.Fval(src)); } /// <summary> /// Transformed value /// </summary> /// <param name="i">x bitmap coordinate</param> /// <param name="j">y bitmap coordinate</param> /// <returns>Transformed value converted to integer point</returns> public Point IntVal(int i, int j) { PointF src = new PointF(i, j); return new Point((int)xBiq.Fval(src), (int)yBiq.Fval(src)); } /// <summary> /// Backward transformation /// </summary> /// <param name="i">x bitmap coordinate</param> /// <param name="j">y bitmap coordinate</param> /// <returns>Transformed value converted to integer point</returns> public Point InvIntVal(int i, int j) { PointF src = new PointF(i, j); return new Point((int)xBiq.Bval(src), (int)yBiq.Bval(src)); } } /// <summary> /// Transformation in one dimension /// </summary> [Serializable] public class BiquadraticOneDim { double[] a, b; /// <summary> /// Calculates cofficients for one dimension /// </summary> /// <param name="isX">Dimension to calculate</param> /// <param name="point">Callibration points</param> /// <remarks><code> /// Biquardatic interpolation, val=a+ b*x + c*y + d*x*x + e*x*y + f*y*y /// a b c d e f /// -------------------------------------- /// | 1 x y x*x x*y y*y | | a | | v | /// | 1 x y x*x x*y y*y | | b | | v | /// | 1 x y x*x x*y y*y | | c | | v | /// | 1 x y x*x x*y y*y | * | d | = | v | /// | 1 x y x*x x*y y*y | | e | | v | /// | 1 x y x*x x*y y*y | | f | | v | /// /// M * B = R /// U * S * Vt * B = R /// B = V * 1/S * Ut * R /// </code></remarks> public BiquadraticOneDim(bool isX, List<Point> src, List<Point> trg) { if (src.Count != trg.Count) throw new Exception(string.Format("BiquadraticOneDim dimension discrepancy {0} vs. {1}", src.Count, trg.Count)); a = new double[6]; b = new double[6]; if (src != null && src.Count > 5) { a = Solve(isX, src, trg); b = Solve(isX, trg, src); } else { if (isX) { a[1] = 1.0; b[1] = 1.0; } else { a[2] = 1.0; b[2] = 1.0; } } } /// <summary> /// Formal validation /// </summary> public bool ok { get { return !double.IsNaN(a[0]); } } // double[] Solve(bool isX, List<CalibrationPoint> point, bool fwd) double[] Solve(bool isX, List<Point> src, List<Point> trg) { int i, m = src.Count; GeneralMatrix M = new GeneralMatrix(m, 6, 0.0); GeneralMatrix R = new GeneralMatrix(m, 1, 0.0); for (i = 0; i < m; i++) { // point on the globe bitmap Point lhs = trg[i]; Point rhs = src[i]; double x = lhs.X; double y = lhs.Y; M.Array[i][0] = 1.0; M.Array[i][1] = x; M.Array[i][2] = y; M.Array[i][3] = x * x; M.Array[i][4] = x * y; M.Array[i][5] = y * y; // point in source bitmap R.Array[i][0] = isX ? rhs.X : rhs.Y; } SingularValueDecomposition svd = M.SVD(); GeneralMatrix u = svd.GetU(); GeneralMatrix v = svd.GetV(); //GeneralMatrix l = svd.S; GeneralMatrix s = new GeneralMatrix(6, 6, 0.0); for (i = 0; i < 6; i++) { s.Array[i][i] = 1.0 / svd.S.Array[i][i]; } GeneralMatrix m1 = v * s; GeneralMatrix m2 = m1 * u.Transpose(); GeneralMatrix B = svd.GetV() * s * svd.GetU().Transpose() * R; double[] mtx = new double[6]; for (i = 0; i < 6; i++) { mtx[i] = B.Array[i][0]; } return mtx; } public override string ToString() { return string.Format("{0}, {1}, {2}, {3}, {4}, {5}", a[0], a[1], a[2], a[3], a[4], a[5]); } /// <summary> /// Forward transformation /// </summary> /// <param name="t">Source point</param> /// <returns>Transformed value</returns> public double Fval(PointF t) { return a[0] + a[1] * t.X + a[2] * t.Y + a[3] * t.X * t.X + a[4] * t.X * t.Y + a[5] * t.Y * t.Y; } /// <summary> /// Backwardtransformation /// </summary> /// <param name="t">Source point</param> /// <returns>Transformed value</returns> public double Bval(PointF t) { return b[0] + b[1] * t.X + b[2] * t.Y + b[3] * t.X * t.X + b[4] * t.X * t.Y + b[5] * t.Y * t.Y; } } }
--- Citace: RomanZ 20-07-2012, 22:58:32 ---
A teď si dám kafe a jdu si napsat svůj vlastní driver na tiskárnu :)))
--- Konce citace ---
To je slabomyslna demagogie. Rozdil ve specifikaci funkcnosti i v kvalite cilovych uzivatelu takovou dusevni zkratku vylucuje.
Nyní jenom nezbývá než doufat, že slunéčko naše jasné, moderátor tohoto fóra, nejvyšší osvícenost hlavní moderátor, a jeho všemocnost majitel fóra budou příznivě naloženi. Dojdou-li totiž k názoru, že publikovaná odpoveď je lepší než na jakou by se zmohlo slunéčko naše jasné moderátor tohoto fóra, nebo se nejvyšší osvícenost hlavní moderátor bude cítit ohrožen na mravnosti nestandardním slovem a nebo jeho všemocnost majitel fóra nebude spokojena s percepcí jeho fóra, tak ten příspěvek smažou.
Zdravim
TC
Navigace
[0] Seznam témat
[*] Předchozí strana
Přejít na plnou verzi