导航

C#给图片打马赛克的两种方法和特点

Posted on 2011-04-15 14:52  yjss  阅读(1388)  评论(1编辑  收藏  举报

原理:就是将图片内容分割成一些小方块,方块内的像素完成相同,从而忽略图像的一些细节

方法:以下提供了两种方法,第一种方法不管方块大小整体效率相差不大,而第二种当方块越大速度越快,方块越小速度越慢

        //使用指针往指定区域打马赛克
        public Image MaSaiKe(Image sImage, int val, Rectangle rectangle)
        {
            Bitmap rBitmap = new Bitmap(sImage);
            if (rBitmap.Equals(null))
            {
                return null;
            }
            int stdR=0, stdG=0, stdB=0;
            BitmapData srcData = rBitmap.LockBits(rectangle,
            ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            unsafe
            {
                byte* point = (byte*)srcData.Scan0.ToPointer();
                for (int i = 0; i < srcData.Height; i++)
                {
                    for (int j = 0; j < srcData.Width; j++)
                    {
                        if (i % val == 0)
                        {
                            if (j % val == 0)
                            {
                                stdR = point[2];
                                stdG = point[1];
                                stdB = point[0];
                            }
                            else
                            {
                                point[0] = (byte)stdB;
                                point[1] = (byte)stdG;
                                point[2] = (byte)stdR;
                            }
                        }
                        else
                        {
                            byte* pTemp = point - srcData.Stride;
                            point[0] = (byte)pTemp[0];
                            point[1] = (byte)pTemp[1];
                            point[2] = (byte)pTemp[2];
                        }
                        point += 3;
                    }
                    point += srcData.Stride - srcData.Width * 3;
                }
                rBitmap.UnlockBits(srcData);
            }
            return rBitmap;
        }

        //使用指针给图片打马赛克
        public Image MaSaiKe(Image sImage, int val)
        {
            return MaSaiKe(sImage, val,
                   new Rectangle(0, 0, sImage.Width, sImage.Height));
        }

        //使用Graphics往指定区域打马赛克
        public Image MaSaiKeGraphics(Image sImage, int val, Rectangle rectangle)
        {
            Bitmap rBitmap = new Bitmap(sImage);
            if (rBitmap.Equals(null))
            {
                return null;
            }
            using (Graphics g = Graphics.FromImage(rBitmap))
            {
                int startX = rectangle.Left, startY = rectangle.Top;
                int fWindth = 0, fHeight = 0;
                long outvalue = 0;

                long rows = Math.DivRem(rectangle.Height, val, out outvalue);
                if (outvalue == 0) rows--;
                long columns = Math.DivRem(rectangle.Width, val, out outvalue);
                if (outvalue == 0) columns--;

                for (int y = 0; y <= rows; y++)
                {
                    startY = rectangle.Top + y * val;
                    if (startY + val > rectangle.Bottom) fHeight = rectangle.Bottom - startY; 
                    else fHeight = val;

                    for (int x = 0; x <= columns; x++)
                    {
                        startX = rectangle.Left + x * val;
                        if (startX + val > rectangle.Right) fWindth = rectangle.Right - startX;
                        else fWindth = val;

                        Rectangle fillRectangle = new Rectangle(startX, startY, fWindth, fHeight);
                        Color fillColor = rBitmap.GetPixel(startX, startY);
                        g.FillRectangle(new SolidBrush(fillColor), fillRectangle);
                    }
                }
            }
            return rBitmap;
        }

        //使用Graphics给图片打马赛克
        public Image MaSaiKeGraphics(Image sImage, int val)
        {
            return MaSaiKeGraphics(sImage, val,
                   new Rectangle(0, 0, sImage.Width, sImage.Height));
        }