代码之家  ›  专栏  ›  技术社区  ›  Echilon Mafarnakus

C-裁剪透明/空白

  •  5
  • Echilon Mafarnakus  · 技术社区  · 14 年前

    我试图从图像中删除所有白色或透明像素,保留实际图像(裁剪)。我试过一些解决办法,但似乎都不管用。有什么建议吗?还是我要整晚写图像裁剪代码?

    5 回复  |  直到 7 年前
        1
  •  3
  •   MusiGenesis    14 年前
    public Bitmap CropBitmap(Bitmap original)
    {
        // determine new left
        int newLeft = -1;
        for (int x = 0; x < original.Width; x++)
        {
            for (int y = 0; y < original.Height; y++)
            {
                Color color = original.GetPixel(x, y);
                if ((color.R != 255) || (color.G != 255) || (color.B != 255) || 
                    (color.A != 0))
                {
                    // this pixel is either not white or not fully transparent
                    newLeft = x;
                    break;
                }
            }
            if (newLeft != -1)
            {
                break;
            }
    
            // repeat logic for new right, top and bottom
    
        }
    
        Bitmap ret = new Bitmap(newRight - newLeft, newTop - newBottom);
        using (Graphics g = Graphics.FromImage(ret)
        {
            // copy from the original onto the new, using the new coordinates as
            // source coordinates for the original
            g.DrawImage(...);
        }
    
        return ret
    }
    

    请注意,此功能将像灰尘一样缓慢。 GetPixel() 速度太慢了 Width Height A的性质 Bitmap 循环内部的速度也很慢。 LockBits 这是正确的方法——StackOverflow上有很多例子。

        2
  •  10
  •   Chris Taylor    14 年前

    因此,您要做的是找到顶部、最左边的非白色/透明像素和底部、最右边的非白色/透明像素。这两个坐标会给你一个矩形,然后你可以提取。

      // Load the bitmap
      Bitmap originalBitmap = Bitmap.FromFile("d:\\temp\\test.bmp") as Bitmap;
    
      // Find the min/max non-white/transparent pixels
      Point min = new Point(int.MaxValue, int.MaxValue);
      Point max = new Point(int.MinValue, int.MinValue);
    
      for (int x = 0; x < originalBitmap.Width; ++x)
      {
        for (int y = 0; y < originalBitmap.Height; ++y)
        {
          Color pixelColor = originalBitmap.GetPixel(x, y);
          if (!(pixelColor.R == 255 && pixelColor.G == 255 && pixelColor.B == 255)
            || pixelColor.A < 255)
          {
            if (x < min.X) min.X = x;
            if (y < min.Y) min.Y = y;
    
            if (x > max.X) max.X = x;
            if (y > max.Y) max.Y = y;
          }
        }
      }
    
      // Create a new bitmap from the crop rectangle
      Rectangle cropRectangle = new Rectangle(min.X, min.Y, max.X - min.X, max.Y - min.Y);
      Bitmap newBitmap = new Bitmap(cropRectangle.Width, cropRectangle.Height);
      using (Graphics g = Graphics.FromImage(newBitmap))
      {
        g.DrawImage(originalBitmap, 0, 0, cropRectangle, GraphicsUnit.Pixel);
      }
    
        3
  •  2
  •   Toan Nguyen    14 年前

    在WPF中,我们有一个可写位图类。这就是你要找的吗?如果是这样的话,请看一下 http://blogs.msdn.com/b/jgalasyn/archive/2008/04/17/using-writeablebitmap-to-display-a-procedural-texture.aspx

        4
  •  2
  •   Gobra    14 年前

    每像素检查应该可以做到这一点。扫描每一行以从顶部和底部查找空行,扫描每一行以查找左侧和右侧约束(这可以通过行或列一次完成)。找到约束后-将图像的一部分复制到另一个缓冲区。

        5
  •  0
  •   Joey Morgan    7 年前

    我找到了一种方法,可以在大约10分钟内批量修剪几千个.jpg文件,但我并没有在代码中这样做。我使用了snag it编辑器的转换功能。我不知道这是否是你的一个选择,如果你需要做这个修剪一次或你的需求正在进行,但对于软件的价格,这不是很多,我认为这是一个体面的解决方案。 (我不为技术史密斯工作或不代表技术史密斯工作。)

    乔伊