Я пытаюсь удалить все белые или прозрачные пиксели из изображения, оставив фактическое изображение (обрезанное). Я пробовал несколько решений, но никто не работает. Любые предложения или я собираюсь провести ночь, используя код обрезки изображения?C# - Crop Transparent/White space
ответ
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.
Спасибо, что достал меня на полпути. Единственная проблема заключается в том, что я также хочу изменить размер изображения, если оно больше заданного размера. Там больше кода, чем будет помещаться в поле комментариев, но исходное изображение занимает примерно половину последнего изображения. Код находится по адресу http://pastebin.com/He3S8aCH – Echilon
Я перенес две переменные: P. Проблема исправлена, ожидайте, что сообщение в блоге скоро (свяжется с ним здесь). – Echilon
Думаю, я тоже испортил. Биты, которые говорят «color.R! = 0» и т. Д., Должны фактически сказать «color.R! = 255», так как белый пиксель будет иметь значения R, G и B 255 для каждого (RGB 0,0, 0 - черный). Если исходная версия работала для вас, то она, вероятно, только обрезала прозрачные (и черные) пиксели. – MusiGenesis
В WPF у нас есть класс WriteableBitmap. Это то, что вы ищете? Если это так, пожалуйста, взгляните на http://blogs.msdn.com/b/jgalasyn/archive/2008/04/17/using-writeablebitmap-to-display-a-procedural-texture.aspx
Проверка на пиксель должна делать трюк. Сканируйте каждую строку, чтобы найти пустую строку сверху & внизу, сканируйте каждую строку, чтобы найти левые & правые ограничения (это можно сделать за один проход с помощью строк или столбцов). Когда обнаружено ограничение - скопируйте часть изображения в другой буфер.
Итак, что вы хотите сделать, это найти верхний, левый самый не белый/прозрачный пиксель и нижний, правый самый не белый/прозрачный пиксель. Эти две координаты дадут вам прямоугольник, который вы можете извлечь.
// 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);
}
Отличное решение! Я удалил '|| pixelColor.A <255', чтобы он работал. – krlzlx
Я нашел способ пакетной обрезки нескольких тысяч .jpg файлов за 10 минут, но я не делал этого в коде. Я использовал функцию Convert редактора Snag-It. Я не знаю, если это вариант для вас, если вам нужно сделать эту обрезку один раз, или ваши потребности продолжаются, но для цены на программное обеспечение, которое не так много, я счел это достойным обходным решением. (я не работаю или представляют TechSmith.)
Джоуи
Так что есть другие люди, которые мечтают непрерывно писать ту же строку кода снова и снова? Я думал, что я единственный :-) –
это помогло бы сообществу, если бы вы описали хотя бы один из ваших подходов и объяснили, как он не работает. –