2010-07-17 3 views
5

Я пытаюсь удалить все белые или прозрачные пиксели из изображения, оставив фактическое изображение (обрезанное). Я пробовал несколько решений, но никто не работает. Любые предложения или я собираюсь провести ночь, используя код обрезки изображения?C# - Crop Transparent/White space

+0

Так что есть другие люди, которые мечтают непрерывно писать ту же строку кода снова и снова? Я думал, что я единственный :-) –

+1

это помогло бы сообществу, если бы вы описали хотя бы один из ваших подходов и объяснили, как он не работает. –

ответ

3
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.

+1

Спасибо, что достал меня на полпути. Единственная проблема заключается в том, что я также хочу изменить размер изображения, если оно больше заданного размера. Там больше кода, чем будет помещаться в поле комментариев, но исходное изображение занимает примерно половину последнего изображения. Код находится по адресу http://pastebin.com/He3S8aCH – Echilon

+0

Я перенес две переменные: P. Проблема исправлена, ожидайте, что сообщение в блоге скоро (свяжется с ним здесь). – Echilon

+0

Думаю, я тоже испортил. Биты, которые говорят «color.R! = 0» и т. Д., Должны фактически сказать «color.R! = 255», так как белый пиксель будет иметь значения R, G и B 255 для каждого (RGB 0,0, 0 - черный). Если исходная версия работала для вас, то она, вероятно, только обрезала прозрачные (и черные) пиксели. – MusiGenesis

2

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

9

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

// 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); 
    } 
+0

Отличное решение! Я удалил '|| pixelColor.A <255', чтобы он работал. – krlzlx

0

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

Джоуи