如果有一个透明的png图像,譬如下图这个图片除了中间有两个彩色的圆外,其余部分都是透明。如何在程序中自动剪裁成一个最小的长方形,这个长方形里面包含这两个彩色的圆,其余部分剪裁掉。同时得到剪裁后长方形的长与宽,以及得到这个长方形的左上角相当于原图的坐标。

解决方案 »

  1.   

    如果不考虑旋转,那么最小矩形的4个顶点就是图形中有有效像素的点集合中x y的最小值最大值。
    如果考虑旋转,稍微复杂点,首先求出所有点x y的平均值,这是重心。以此为基准,求出这些点到重心的距离取得最大值,以这个点和重心的连线为基准将图像旋转,再按照前述的方法计算。
      

  2.   

    你这个要求就是PS种的修整功能。 其实就是简单的扫描。给你我在imageshop中的代码参考: Case PixelFormat32bppARGB
            ExitFlag = False
            If Top = True Then          '¶¥²¿
                For Y = 0 To m_Height - 1
                    If ExitFlag = True Then Exit For
                    Speed = m_Stride * Y
                    For X = 0 To m_Width - 1
                        If ImageData(Speed) <> Blue Or ImageData(Speed + 1) <> Green Or ImageData(Speed + 2) <> Red Or ImageData(Speed + 3) <> Alpha Then
                            TopPos = Y
                            ExitFlag = True
                            Exit For
                        End If
                        Speed = Speed + 4
                    Next
                Next
            End If        ExitFlag = False
            If Left = True Then      '×ó²¿
                For X = 0 To m_Width - 1
                    If ExitFlag = True Then Exit For
                    Speed = X * 4
                    For Y = 0 To m_Height - 1
                        If ImageData(Speed) <> Blue Or ImageData(Speed + 1) <> Green Or ImageData(Speed + 2) <> Red Or ImageData(Speed + 3) <> Alpha Then
                            LeftPos = X
                            ExitFlag = True
                            Exit For
                        End If
                        Speed = Speed + m_Stride
                    Next
                Next
            End If
            
            ExitFlag = False
            If Bottom = True Then      'µ×²¿
                For Y = m_Height - 1 To 0 Step -1
                    If ExitFlag = True Then Exit For
                    Speed = m_Stride * Y
                    For X = 0 To m_Width - 1
                        If ImageData(Speed) <> Blue Or ImageData(Speed + 1) <> Green Or ImageData(Speed + 2) <> Red Or ImageData(Speed + 3) <> Alpha Then
                            BottomPos = Y
                            ExitFlag = True
                            Exit For
                        End If
                        Speed = Speed + 4
                    Next
                Next
            End If
                
            ExitFlag = False
            If Right = True Then     'ÓÒ²¿
                For X = m_Width - 1 To 0 Step -1
                    If ExitFlag = True Then Exit For
                    Speed = X * 4
                    For Y = 0 To m_Height - 1
                        If ImageData(Speed) <> Blue Or ImageData(Speed + 1) <> Green Or ImageData(Speed + 2) <> Red Or ImageData(Speed + 3) <> Alpha Then
                            RightPos = X
                            ExitFlag = True
                            Exit For
                        End If
                        Speed = Speed + m_Stride
                    Next
                Next        End If
    以上就得到了要修整的区域的坐标,下面就是要复制图像数据的程序了。
      

  3.   


    在你这里就是指alpha通道不是透明,颜色不是0xFFFFFF的。
      

  4.   

    连续好几个            For Y = 0 To m_Height - 1
                    For X = 0 To m_Width - 1
    足矣“吓死人”啦。对于任意点,取最大的X值、最小的X值、最大的Y值、最小的Y值就行了。不要“更技术”的任何方法。
      

  5.   

    哦,重新看了一下#3楼的代码,被它的ExitFlag给吓到了。(难道VB.NET代码都是这个不好看?)不过它的方式应该是对的。从左边向右扫描,试图得到最小的X。然后从右边向左扫描......
      

  6.   

    Quote: 引用 6 楼 sp1234 的回复:

    连续好几个C# code?12            For Y = 0 To m_Height - 1                For X = 0 To m_Width - 1足矣“吓死人”啦。为什么会吓死人?这不是很正常的两层循环吗?
    你可以看看 laviewpbt 写的 imageshop,还是很不错的
      

  7.   


    /// <summary>
            /// 去除白边
            /// </summary>
            /// <param name="bm"></param>
            /// <returns></returns>
            public static Bitmap ClearWhite(Bitmap bm)
            {
                int y_l = 0;//左边
                int y_r = 0;//右边
                int i_h = 0;//上边
                int i_d = 0;//下边
                #region 计算----
                for (int i = 0; i < bm.Width; i++)
                {
                    for(int y=0;y<bm.Height;y++)
                    {
                        if (bm.GetPixel(i, y).R != 255 || bm.GetPixel(i, y).B != 255 || bm.GetPixel(i, y).G != 255)
                        {
                            y_l = i;
                            goto yl;
                        }
                    }
                }
                yl:
                for (int i = 0; i < bm.Width; i++)
                {
                    for (int y = 0; y < bm.Height; y++)
                    {
                        if (bm.GetPixel(bm.Width - i - 1, y).R != 255 || bm.GetPixel(bm.Width - i - 1, y).B != 255 || bm.GetPixel(bm.Width - i - 1, y).G != 255)
                        {
                            y_r = i;
                            goto yr;
                        }
                    }
                }
                yr:
                for (int i = 0; i < bm.Height; i++)
                {
                    for (int y = 0; y < bm.Width; y++)
                    {
                        if (bm.GetPixel(y, i).R != 255 || bm.GetPixel(y, i).B != 255 || bm.GetPixel(y, i).G != 255)
                        {
                            i_h = i;
                            goto ih;
                        }
                    }
                }
                ih:
                for (int i = 0; i < bm.Height; i++)
                {
                    for (int y = 0; y < bm.Width; y++)
                    {
                        if (bm.GetPixel(y, bm.Height - i - 1).R != 255 || bm.GetPixel(y, bm.Height - i - 1).B != 255 || bm.GetPixel(y, bm.Height - i - 1).G != 255)
                        {
                             i_d = i;
                             goto id;
                        }
                    }
                }
            id:
                #endregion            //创建此大小的图片
                Bitmap bmp = new Bitmap(bm.Width - y_l - y_r, bm.Height - i_h - i_d);
                Graphics g = Graphics.FromImage(bmp);
                //(new Point(y_l, i_h), new Point(0, 0), new Size(bm.Width - y_l - y_r, bm.Height - i_h - i_d));
                Rectangle sourceRectangle = new Rectangle(y_l, i_h, bm.Width - y_l - y_r, bm.Height - i_h - i_d);
                Rectangle resultRectangle = new Rectangle(0, 0, bm.Width - y_l - y_r, bm.Height - i_h - i_d);
                g.DrawImage(bm, resultRectangle, sourceRectangle, GraphicsUnit.Pixel);
                g.Dispose();
                return bmp;
            }以前写的。各位别笑 - -
    我有方法你自己改改
      

  8.   

    If ImageData(Speed) <> Blue Or ImageData(Speed + 1) <> Green Or ImageData(Speed + 2) <> Red Or ImageData(Speed + 3) <> Alpha这个Blue,Green Red,Alpha是怎么定义的。
    是否Speed$(0xf)检测更高效?
      

  9.   

    上面打错了,应该是:是否Speed&(0xf)检测更高效?