Пример #1
0
        unsafe static bool CheckNearestPixel(float x, float y, BitmapIterator iter, Predicate <int> isFound)
        {
            if (x < 0 || y < 0)
            {
                return(false);
            }
            if (x >= iter.Bmp.Width || y >= iter.Bmp.Height)
            {
                return(false);
            }
            int val = ((int *)iter.PixelData)[(int)x + (int)y * iter.Bmp.Width];

            if (isFound == null)
            {
                if (val != 0)
                {
                    return(true);
                }
            }
            else
            {
                if (isFound(val))
                {
                    return(true);
                }
            }
            return(false);
        }
Пример #2
0
        // ptとdirが表す直線状を、ptから双方向に操作したときに最初に見つかるピクセル
        // iterは32ビット長を仮定
        unsafe static PointF GetNearestPixel(BitmapIterator iter, PointF pt, PointF dir, Rectangle bounds, Predicate <int> isFound = null)
        {
            if (iter.PixelSize != 4)
            {
                return(new PointF(-1, -1));
            }

            float len = FMath.Distance(dir, PointF.Empty);

            if (len <= 1e-4)
            {
                return(new PointF(-1, -1));
            }
            float dx = dir.X / len;
            float dy = dir.Y / len;

            int cnt = 0;

            while (true)
            {
                float x1 = pt.X + dx * cnt;
                float y1 = pt.Y + dy * cnt;
                float x2 = pt.X - dx * cnt;
                float y2 = pt.Y - dy * cnt;

                bool out1 = !bounds.Contains((int)x1, (int)y1);
                bool out2 = !bounds.Contains((int)x2, (int)y2);

                if (out1 && out2)
                {
                    return(new PointF(-1, -1));
                }

                if (!out1 && CheckNearestPixel(x1, y1, iter, isFound))
                {
                    return(new PointF(x1, y1));
                }

                if (!out2 && CheckNearestPixel(x2, y2, iter, isFound))
                {
                    return(new PointF(x2, y2));
                }

                cnt++;
            }
        }
Пример #3
0
        unsafe Bitmap CreatGradBitmap(int w, int h)
        {
            var bmp = new Bitmap(200, 200, PixelFormat.Format32bppArgb);

            using (var iter = new BitmapIterator(bmp, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb))
            {
                for (int y = 0; y < h; y++)
                {
                    for (int x = 0; x < w; x++)
                    {
                        iter.Data[iter.Stride * y + 4 * x + 0] = 255;
                        iter.Data[iter.Stride * y + 4 * x + 1] = (byte)(255f * x / w);
                        iter.Data[iter.Stride * y + 4 * x + 2] = (byte)(255f * y / h);
                        iter.Data[iter.Stride * y + 4 * x + 3] = 255;
                    }
                }
            }
            return(bmp);
        }
Пример #4
0
        // テクスチャマッピングをする
        unsafe public Bitmap ToBitmap(Bitmap texture)
        {
            int maxx = (int)meshPointList.Select(p => p.X).Max() + 1;
            int maxy = (int)meshPointList.Select(p => p.Y).Max() + 1;

            if (maxx <= 0 || maxy <= 0)
            {
                return(null);
            }
            Bitmap bmp = new Bitmap(maxx, maxy, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.Clear(Color.Transparent);
            }

            if (bmp != null)
            {
                using (var inIter = new BitmapIterator(texture, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
                    using (var outIter = new BitmapIterator(bmp, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
                    {
                        for (int i = 0; i < meshList.Count; i++)
                        {
                            var tri = meshList[i];

                            PointF pt0 = meshPointList[tri.idx0];
                            PointF pt1 = meshPointList[tri.idx1];
                            PointF pt2 = meshPointList[tri.idx2];

                            PointF cd0 = texcoordList[tri.idx0];
                            PointF cd1 = texcoordList[tri.idx1];
                            PointF cd2 = texcoordList[tri.idx2];

                            List <PointF> pts = new List <PointF>()
                            {
                                pt0, pt1, pt2,
                            };

                            pts = pts.OrderBy(p => p.Y).ToList();

                            // ラスタライズ
                            float v1_dx  = pt1.X - pt0.X;
                            float v1_dy  = pt1.Y - pt0.Y;
                            float v2_dx  = pt2.X - pt0.X;
                            float v2_dy  = pt2.Y - pt0.Y;
                            float v1_len = (float)Math.Sqrt(v1_dx * v1_dx + v1_dy * v1_dy);
                            if (v1_len <= 1e-4)
                            {
                                continue;
                            }
                            float v2_len = (float)Math.Sqrt(v2_dx * v2_dx + v2_dy * v2_dy);
                            if (v2_len <= 1e-4)
                            {
                                continue;
                            }

                            float v1_x = v1_dx / v1_len;
                            float v1_y = v1_dy / v1_len;
                            float v2_x = v2_dx / v2_len;
                            float v2_y = v2_dy / v2_len;

                            float ds = 1 / v1_len;
                            float dt = 1 / v2_len;

                            for (float t = 0; t <= 1; t += dt)
                            {
                                for (float s = 0; t + s <= 1; s += ds)
                                {
                                    float x  = pt0.X + v1_dx * s + v2_dx * t;
                                    float y  = pt0.Y + v1_dy * s + v2_dy * t;
                                    float cx = cd0.X * (1 - s - t) + cd1.X * s + cd2.X * t;
                                    float cy = cd0.Y * (1 - s - t) + cd1.Y * s + cd2.Y * t;

                                    int offset_out = (int)x * 4 + (int)y * outIter.Stride;
                                    int offset_in  = (int)cx * 4 + (int)cy * inIter.Stride;

                                    outIter.Data[offset_out + 0] = inIter.Data[offset_in + 0];
                                    outIter.Data[offset_out + 1] = inIter.Data[offset_in + 1];
                                    outIter.Data[offset_out + 2] = inIter.Data[offset_in + 2];
                                    outIter.Data[offset_out + 3] = inIter.Data[offset_in + 3];
                                }
                            }
                        }
                    }
            }

            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.DrawLines(penB, GetPath().ToArray());
                foreach (var t in meshList)
                {
                    PointF pt0 = meshPointList[t.idx0];
                    PointF pt1 = meshPointList[t.idx1];
                    PointF pt2 = meshPointList[t.idx2];
                    g.DrawLines(pen, new PointF[] { pt0, pt1, pt2, pt0 });
                }
            }
            return(bmp);
        }
Пример #5
0
        unsafe public bool[] GetPixelsInPath(Bitmap pathBmp, out Rectangle pixelBound)
        {
            pixelBound = new Rectangle();

            bool[] isBoarder = new bool[pathBmp.Width * pathBmp.Height];

            using (var bbmp = new BitmapIterator(pathBmp, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb))
            {
                for (int y = 0; y < pathBmp.Height; y++)
                {
                    for (int x = 0; x < pathBmp.Width; x++)
                    {
                        bool onBoarder = bbmp.Data[bbmp.Stride * y + 4 * x + 1] >= 128;
                        if (onBoarder)
                        {
                            isBoarder[x + y * pathBmp.Width] = true;
                        }
                    }
                }
            }

            // FloodFill
            HashSet <int> pixels = new HashSet <int>();
            HashSet <int> checks = new HashSet <int>(pixels);

            checks.Add(0);
            while (checks.Count >= 1)
            {
                int idx = checks.First();
                pixels.Add(idx);
                checks.Remove(idx);

                int x;
                int y = Math.DivRem(idx, pathBmp.Width, out x);
                if (x - 1 >= 0)
                {
                    int i = (x - 1) + y * pathBmp.Width;
                    if (!isBoarder[i] && !pixels.Contains(i))
                    {
                        checks.Add(i);
                    }
                }
                if (x + 1 < pathBmp.Width)
                {
                    int i = (x + 1) + y * pathBmp.Width;
                    if (!isBoarder[i] && !pixels.Contains(i))
                    {
                        checks.Add(i);
                    }
                }
                if (y - 1 >= 0)
                {
                    int i = x + (y - 1) * pathBmp.Width;
                    if (!isBoarder[i] && !pixels.Contains(i))
                    {
                        checks.Add(i);
                    }
                }
                if (y + 1 < pathBmp.Height)
                {
                    int i = x + (y + 1) * pathBmp.Width;
                    if (!isBoarder[i] && !pixels.Contains(i))
                    {
                        checks.Add(i);
                    }
                }
            }

            int xx = int.MaxValue;
            int yy = int.MaxValue;
            int x1 = int.MinValue;
            int y1 = int.MinValue;

            List <int> xs = new List <int>();
            List <int> ys = new List <int>();

            for (int y = 0; y < pathBmp.Height; y++)
            {
                for (int x = 0; x < pathBmp.Width; x++)
                {
                    int i = x + y * pathBmp.Width;
                    if (pixels.Contains(i))
                    {
                        continue;
                    }
                    xx = Math.Min(xx, x);
                    yy = Math.Min(yy, y);
                    x1 = Math.Max(x1, x);
                    y1 = Math.Max(y1, y);
                    xs.Add(x);
                    ys.Add(y);
                }
            }
            pixelBound = new Rectangle(xx, yy, x1 - xx + 1, y1 - yy + 1);
            bool[] trimmedPixels = new bool[pixelBound.Width * pixelBound.Height];
            for (int i = 0; i < xs.Count; i++)
            {
                trimmedPixels[(xs[i] - pixelBound.X) + (ys[i] - pixelBound.Y) * pixelBound.Width] = true;
            }

            return(trimmedPixels);
        }
Пример #6
0
        unsafe public void UpdateBitmap(SegmentRoot root)
        {
            if (root != null)
            {
                this.root = root;
            }

            if (!Closed)
            {
                return;
            }

            if (root == null || root.bmp == null)
            {
                return;
            }

            if (bmp != null)
            {
                bmp.Dispose();
            }

            var expBound = GetExpandedBound(path);
            var pathBmp  = DrawPath(expBound);

            Rectangle pixelBound = new Rectangle();

            bool[] pixels = GetPixelsInPath(pathBmp, out pixelBound);

            offset = new Point(expBound.X + pixelBound.X, expBound.Y + pixelBound.Y);

            bmp = new Bitmap((int)pixelBound.Width, (int)pixelBound.Height, root.bmp.PixelFormat);

            using (var initer = new BitmapIterator(root.bmp, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb))
                using (var outiter = new BitmapIterator(bmp, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb))
                {
                    for (int y = 0; y < pixelBound.Height; y++)
                    {
                        for (int x = 0; x < pixelBound.Width; x++)
                        {
                            if (pixels[pixelBound.Width * y + x])
                            {
                                int xx = offset.X + x;
                                int yy = offset.Y + y;
                                if (xx < 0 || root.bmp.Width <= xx || yy < 0 || root.bmp.Height <= yy)
                                {
                                    continue;
                                }
                                if (x < 0 || bmp.Width <= x || y < 0 || bmp.Height <= y)
                                {
                                    continue;
                                }
                                int ii = initer.Stride * yy + 4 * xx;
                                int oi = outiter.Stride * y + 4 * x;
                                outiter.Data[oi + 0] = initer.Data[ii + 0];
                                outiter.Data[oi + 1] = initer.Data[ii + 1];
                                outiter.Data[oi + 2] = initer.Data[ii + 2];
                                outiter.Data[oi + 3] = initer.Data[ii + 3];
                            }
                        }
                    }
                }
        }
Пример #7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <param name="course">0以上.値が大きいほど荒くなる</param>
        /// <returns></returns>
        public static List <PointF> Subdivide(List <PointF> path, float course)
        {
            if (course <= 0)
            {
                return(null);
            }

            float x = float.MaxValue, y = float.MaxValue, x1 = float.MinValue, y1 = float.MinValue;

            foreach (var p in path)
            {
                x  = Math.Min(p.X, x);
                y  = Math.Min(p.Y, y);
                x1 = Math.Max(p.X, x1);
                y1 = Math.Max(p.Y, y1);
            }
            int w = (int)(x1 - x), h = (int)(y1 - y);

            x  = x - w;
            y  = y - h;
            w *= 3;
            h *= 3;

            Rectangle bounds = new Rectangle((int)x, (int)y, w, h);

            Pen pen = new Pen(Brushes.Red, 2);

            List <PointF> divPath = new List <PointF>();

            using (Bitmap line = new Bitmap((int)x + w, (int)y + h))
            {
                using (var g = Graphics.FromImage(line))
                {
                    g.Clear(Color.Transparent);
                    g.DrawCurve(pen, path.ToArray());
                }

                using (BitmapIterator iter = new BitmapIterator(line, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
                {
                    for (int i = 0; i < path.Count - 1; i++)
                    {
                        divPath.Add(path[i]);
                        List <PointF> seg = SubdivideSegment(path[i], path[i + 1], course);
                        if (seg == null)
                        {
                            continue;
                        }
                        float len = FMath.Distance(path[i], path[i + 1]);
                        if (len <= 1e-4)
                        {
                            continue;
                        }
                        float  dy  = (path[i].X - path[i + 1].X) / len;
                        float  dx  = (path[i + 1].Y - path[i].Y) / len;
                        PointF dir = new PointF(dx, dy);
                        foreach (var p in seg)
                        {
                            PointF pt = GetNearestPixel(iter, p, dir, bounds, null);
                            if (pt.X >= 0 && pt.Y >= 0)
                            {
                                divPath.Add(pt);
                            }
                        }
                    }
                }
            }

            divPath.Add(path.Last());

            return(divPath);
        }