C # - Растениеводство Прозрачный / Пробел - PullRequest
5 голосов
/ 17 июля 2010

Я пытаюсь удалить все белые или прозрачные пиксели с изображения, оставляя фактическое изображение (обрезанное).Я пробовал несколько решений, но ни одно из них не работает.Любые предложения или я собираюсь провести ночь написания кода обрезки изображения?

Ответы [ 5 ]

10 голосов
/ 17 июля 2010

Итак, вы хотите найти верхний левый самый небелый / прозрачный пиксель и нижний правый самый белый / прозрачный пиксель. Эти две координаты дадут вам прямоугольник, который вы затем сможете извлечь.

  // 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 голосов
/ 17 июля 2010
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 свойствам Bitmap внутри цикла также медленный. LockBits было бы правильным способом сделать это - здесь есть множество примеров в StackOverflow.

2 голосов
/ 17 июля 2010

Проверка на пиксель должна помочь. Просканируйте каждую строку, чтобы найти пустую строку сверху и снизу, отсканируйте каждую строку, чтобы найти ограничения слева и справа (это можно сделать за один проход с помощью строк или столбцов). Когда ограничение найдено - скопируйте часть изображения в другой буфер.

2 голосов
/ 17 июля 2010

В WPF у нас есть класс WriteableBitmap.Это то, что вы ищете?Если это так, пожалуйста, посмотрите на http://blogs.msdn.com/b/jgalasyn/archive/2008/04/17/using-writeablebitmap-to-display-a-procedural-texture.aspx

0 голосов
/ 28 августа 2017

Я нашел способ пакетной обрезки нескольких тысяч файлов .jpg за 10 минут, но я не делал этого в коде.Я использовал функцию преобразования в редакторе Snag-It.Я не знаю, подходит ли вам этот вариант, если вам нужно выполнить обрезку один раз или ваша потребность в постоянном использовании, но по цене программного обеспечения, которая невелика, я посчитал это достойным обходным решением.(Я не работаю и не представляю Техсмит.)

Джои

...