专注于分享
分享好资源

C#图片处理,如何把图片上方空白处剪除

算法是扫描每一行,看看每个像素是否与指定的颜色都一样。都一样则换到下一行再看,否则就从该行起剪裁。

算法是剪裁行,如果剪裁列空白的话可以先把图片旋转90度再按行的方法处理。

颜色容差是必要的,因为如果你是用jeg之类的有损压缩过的图片的话可能会存在肉眼不觉得的失真,但计算机认为这是不同的颜色。

因为用到了指针,在测试的时候需要修改项目属性,允许不安全的代码。

完整代码如下

#region 剪裁掉边框
        
        /// <summary>
        /// 判断指定行内像素是否与指定颜色都相同
        /// </summary>
        /// <param name="setColor">指定色</param>
        /// <param name="bmp">原始图</param>
        /// <param name="lineIndex">行号</param>
        /// <param name="tolerance">容差</param>
        /// <returns>是/否</returns>
        private bool AllPixelsAreSameColor(Color setColor, Bitmap bmp, int lineIndex, int tolerance)
        {
            bool rtn = false;

            int w = bmp.Width;
            int h = bmp.Height;

            //取一行
            BitmapData data = bmp.LockBits(new Rectangle(0, lineIndex, w, 1), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

            unsafe
            {
                byte* p = (byte*)data.Scan0;

                for (int x = 0; x < w; x++)
                {
                    // 检验指定位置的像素值
                    Color curColor = Color.FromArgb(p[2],p[1],p[0]);

                    if (ColorIsSimilar(setColor, curColor, tolerance))
                    {
                        rtn = true;                            
                    }
                    else
                    {
                        rtn = false;
                        break;
                    }

                    p += 3;
                } // end of x

            }

            bmp.UnlockBits(data);

            return rtn;

        }

        /// <summary>
        /// 颜色是否近似
        /// </summary>
        /// <param name="c0">颜色0</param>
        /// <param name="c1">颜色1</param>
        /// <param name="delta">容差</param>
        /// <returns>是/否</returns>
        private bool ColorIsSimilar(Color c0, Color c1, int delta)
        {
            int r0, r1, g0, g1, b0, b1;

            r0 = c0.R;
            r1 = c1.R;

            g0 = c0.G;
            g1 = c1.G;

            b0 = c0.B;
            b1 = c1.B;

            if ((r0 - r1) * (r0 - r1) + (g0 - g1) * (g0 - g1) + (b0 - b1) * (b0 - b1) <= delta * delta)
            {
                return true;
            }
            else
            {
                return false;
            }

        }

        /// <summary>
        /// 剪裁
        /// </summary>
        /// <param name="b">原始Bitmap</param>
        /// <param name="StartX">开始坐标X</param>
        /// <param name="StartY">开始坐标Y</param>
        /// <param name="iWidth">宽度</param>
        /// <param name="iHeight">高度</param>
        /// <returns>剪裁后的Bitmap</returns>
        private Bitmap KiCut(Bitmap b, int startX, int startY, int iWidth, int iHeight)
        {
            if (b == null)
            {
                return null;
            }

            int w = b.Width;
            int h = b.Height;

            if (startX >= w || startY >= h)
            {
                return null;
            }

            if (startX + iWidth > w)
            {
                iWidth = w - startX;
            }

            if (startY + iHeight > h)
            {
                iHeight = h - startY;
            }

            Graphics g = null;

            try
            {
                Bitmap bmpOut = new Bitmap(iWidth, iHeight, PixelFormat.Format24bppRgb);

                g = Graphics.FromImage(bmpOut);
                g.DrawImage(b, new Rectangle(0, 0, iWidth, iHeight), new Rectangle(startX, startY, iWidth, iHeight), GraphicsUnit.Pixel);

                return bmpOut;
            }
            catch
            {
                return null;
            }
            finally
            {
                if (g != null) g.Dispose();
            }

            
        }
        

        /// <summary>
        /// 切除周围的指定颜色
        /// </summary>
        /// <param name="bmp">原始图</param>
        /// <param name="c">指定色</param>
        /// <param name="tolerance">颜色容差</param>
        /// <returns>切除后的图片</returns>
        public Bitmap CutAround(Bitmap bmp, Color c, int tolerance)
        {
            if (bmp == null) return null;

            bool CutFlag = false;
            int i = 0;

            int w = bmp.Width;
            int h = bmp.Height;

            // 扫描每一行
            for (i = 0; i < h; i++)
            {
                // 如果发现此行并非同一个颜色则退出
                if (!AllPixelsAreSameColor(c, bmp, i, tolerance))
                {
                    CutFlag = true;
                    break;
                }
            }

            // 剪裁
            if (CutFlag) bmp = KiCut(bmp, 0, i, w, h - i);

            return bmp;
        }

        #endregion

 

赞(0)

评论 抢沙发

验证码: 7 + 9 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址