.NET > Obecné

Jak v C# kreslit 2D grafiku?

<< < (2/2)

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