Esempio n. 1
0
        /// <summary>
        /// 横向删除线
        /// </summary>
        /// <param name="image">需要处理的图像</param>
        /// <param name="span">跨度(百分比小数)</param>
        /// <param name="continuousDegree">连续度(像素)</param>
        /// <param name="backColor">背景色</param>
        public unsafe static void XStrikethrough(Bitmap image, float span, int continuousDegree, System.Drawing.Color backColor)
        {
            int backColorArgb = ColorHelper.ToArgb(backColor.R, backColor.G, backColor.B);


            int        w = image.Width; int h = image.Height;
            BitmapData data = image.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            byte *p      = (byte *)data.Scan0;
            byte *pOri   = p;
            int   offset = data.Stride - w * 3;

            ImagePointToIndexHandler pointToIndexHandler = (p1, p2) => {
                if (p1 < 0 || p2 < 0 || p1 >= w || p2 >= h)
                {
                    return(-1);
                }
                return(p1 * 3 + p2 * w * 3 + p2 * offset);
            };

            System.Collections.Generic.Dictionary <int, XStrikethroughLine> lines = new System.Collections.Generic.Dictionary <int, XStrikethroughLine>();
            for (int x = 0; x < w; x++)
            {
                for (int y = 0; y < h; y++)
                {
                    int index = pointToIndexHandler(x, y);
                    p = pOri + index;
                    int a = ColorHelper.ToArgb(p[0], p[1], p[2]);
                    if (a == backColorArgb)
                    {
                        continue;
                    }
                    XStrikethroughLine line = null;
                    if (x > 0)
                    {
                        var o = LinqHelper.FirstOrDefault(
                            LinqHelper.ThenBy(
                                LinqHelper.OrderBy(
                                    LinqHelper.Where(
                                        LinqHelper.Select(
                                            lines.Values,
                                            p1 => new { p1, c = p1.Continuous(x, y, continuousDegree) }),
                                        p1 => p1.c != int.MinValue),
                                    p1 => p1.c),
                                p1 => p1.p1.Y)
                            );
                        if (o != null)
                        {
                            line = o.p1;
                        }
                    }
                    XStrikethroughLinePoint point = new XStrikethroughLinePoint()
                    {
                        X     = x,
                        Y     = y,
                        Index = index
                    };
                    if (y > 0)
                    {
                        int   topPIndex = pointToIndexHandler(x, y - 1);
                        byte *topP      = pOri + topPIndex;
                        point.TopPoint = new ColorScanStridePoint()
                        {
                            X     = x,
                            Y     = y - 1,
                            Index = topPIndex,
                            R     = topP[0],
                            G     = topP[1],
                            B     = topP[2],
                            Color = ColorHelper.ToArgb(topP[0], topP[1], topP[2]),
                        };
                    }
                    if (y < h - 1)
                    {
                        int   bottomPIndex = pointToIndexHandler(x, y + 1);
                        byte *bottomP      = pOri + bottomPIndex;
                        point.BottomPoint = new ColorScanStridePoint()
                        {
                            X     = x,
                            Y     = y + 1,
                            Index = bottomPIndex,
                            R     = bottomP[0],
                            G     = bottomP[1],
                            B     = bottomP[2],
                            Color = ColorHelper.ToArgb(bottomP[0], bottomP[1], bottomP[2]),
                        };
                    }
                    if (line == null)
                    {
                        line = new XStrikethroughLine()
                        {
                            X      = x,
                            Y      = y,
                            Color  = a,
                            R      = p[0],
                            G      = p[1],
                            B      = p[2],
                            Width  = 1,
                            Height = 1,
                            Right  = x + 1,
                            Bottom = y + 1,
                            Index  = index,
                            ImagePointToIndexHandler = pointToIndexHandler,
                        };
                        line.Points.Add(index, point);
                        lines.Add(index, line);
                    }
                    else
                    {
                        if (x > line.X)
                        {
                            line.Width = x - line.X + 1;
                            line.Right = x;
                        }
                        if (y > line.Bottom)
                        {
                            line.Height = y - line.Y + 1;
                            line.Bottom = y;
                        }
                        line.Points.Add(index, point);
                    }
                }
            }
            System.Collections.Generic.IEnumerable <XStrikethroughLine> q =
                LinqHelper.Select(
                    LinqHelper.ThenBy(
                        LinqHelper.OrderByDescending(
                            LinqHelper.Where(
                                LinqHelper.Select(
                                    lines.Values,
                                    p1 => new { p1, c = ((float)p1.Width) / w }),
                                p1 => p1.c >= span),
                            p1 => p1.c),
                        p1 => p1.p1.X),
                    p1 => p1.p1);
            foreach (var item in q)
            {
                foreach (XStrikethroughLinePoint point in item.Points.Values)
                {
                    p = pOri + point.Index;
                    XStrikethrough_SetColor(p, pOri, point.X, point.Y, backColorArgb, pointToIndexHandler);
                    //ColorScanStridePoint colorPoint = point.TopPoint ?? point.BottomPoint;
                    ////p[0] = 255;
                    ////p[1] = 0; p[2] = 0;
                    //p[0] = colorPoint.R;
                    //p[1] = colorPoint.G;
                    //p[2] = colorPoint.B;
                    ////p[0] = p[1] = p[2] = 255;
                }
            }

            image.UnlockBits(data);
        }
Esempio n. 2
0
        static unsafe void XStrikethrough_SetColor(byte *p, byte *pOri, int x, int y, int backColorArgb, ImagePointToIndexHandler pointToIndexHandler)
        {
            int pArgb = ColorHelper.ToArgb(p[0], p[1], p[2]);
            int top   = pointToIndexHandler(x, y - 1);

            if (top != -1)
            {
                byte *p2 = pOri + top;
                int   a  = ColorHelper.ToArgb(p2[0], p2[1], p2[2]);
                if (a != backColorArgb && a != pArgb)
                {
                    p[0] = p2[0];
                    p[1] = p2[1];
                    p[2] = p2[2];
                    return;
                }
            }



            int bottom = pointToIndexHandler(x, y + 1);

            if (bottom != -1)
            {
                byte *p2 = pOri + bottom;
                int   a  = ColorHelper.ToArgb(p2[0], p2[1], p2[2]);
                if (a != backColorArgb && a != pArgb)
                {
                    p[0] = p2[0];
                    p[1] = p2[1];
                    p[2] = p2[2];
                    return;
                }
            }
            int  left    = pointToIndexHandler(x - 1, y);
            bool isEmpty = true;

            if (left != -1)
            {
                byte *p2 = pOri + left;
                int   a  = ColorHelper.ToArgb(p2[0], p2[1], p2[2]);
                if (a != backColorArgb && a != pArgb)
                {
                    isEmpty = false;
                    //p[0] = p2[0];
                    //p[1] = p2[1];
                    //p[2] = p2[2];
                    return;
                }
            }
            if (isEmpty)
            {
                p[0] = p[1] = p[2] = 255;
            }
        }