मूल विचार शीर्ष, छोड़ दिया छवि के दाईं और नीचे सीमा को खोजने के लिए छवि के हर पिक्सेल की जांच करने के लिए है। इसे कुशलता से करने के लिए, GetPixel
विधि का उपयोग न करें, जो कि बहुत धीमी है। इसके बजाय LockBits
का उपयोग करें।
यहाँ कार्यान्वयन मैं के साथ आया है:
static Bitmap TrimBitmap(Bitmap source)
{
Rectangle srcRect = default(Rectangle);
BitmapData data = null;
try
{
data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte[] buffer = new byte[data.Height * data.Stride];
Marshal.Copy(data.Scan0, buffer, 0, buffer.Length);
int xMin = int.MaxValue;
int xMax = 0;
int yMin = int.MaxValue;
int yMax = 0;
for (int y = 0; y < data.Height; y++)
{
for (int x = 0; x < data.Width; x++)
{
byte alpha = buffer[y * data.Stride + 4 * x + 3];
if (alpha != 0)
{
if (x < xMin) xMin = x;
if (x > xMax) xMax = x;
if (y < yMin) yMin = y;
if (y > yMax) yMax = y;
}
}
}
if (xMax < xMin || yMax < yMin)
{
// Image is empty...
return null;
}
srcRect = Rectangle.FromLTRB(xMin, yMin, xMax, yMax);
}
finally
{
if (data != null)
source.UnlockBits(data);
}
Bitmap dest = new Bitmap(srcRect.Width, srcRect.Height);
Rectangle destRect = new Rectangle(0, 0, srcRect.Width, srcRect.Height);
using (Graphics graphics = Graphics.FromImage(dest))
{
graphics.DrawImage(source, destRect, srcRect, GraphicsUnit.Pixel);
}
return dest;
}
यह शायद अनुकूलित किया जा सकता है, लेकिन मैं एक GDI + विशेषज्ञ नहीं हूँ, तो यह सबसे अच्छा मैं आगे अनुसंधान के बिना कर सकते हैं ...
संपादित करें: righ के लिए छोड़ दिया
- स्कैन: वास्तव में, वहाँ यह अनुकूलन करने के लिए, छवि के कुछ भागों को स्कैन नहीं द्वारा एक आसान तरीका है टी जब तक आपको एक गैर पारदर्शी पिक्सेल नहीं मिल जाता है; स्टोर (एक्स, वाई) में (xMin, yMin)
- जब तक आप एक गैर पारदर्शी पिक्सेल (केवल x> = xMin के लिए) नहीं पाते हैं तब तक ऊपर तक स्कैन करें; y yin
- में स्टोर वाई को तब तक बाएं स्कैन करें जब तक कि आपको एक गैर-पारदर्शी पिक्सेल न मिले (केवल y> = ymin के लिए); एक्सएमएक्स
- स्टोर में x को एक गैर पारदर्शी पिक्सेल (केवल xMin < = x < = xMax) के लिए शीर्ष तक स्कैन करें; yMax
EDIT2 में दुकान y: यहाँ ऊपर दृष्टिकोण के एक कार्यान्वयन है:
static Bitmap TrimBitmap(Bitmap source)
{
Rectangle srcRect = default(Rectangle);
BitmapData data = null;
try
{
data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte[] buffer = new byte[data.Height * data.Stride];
Marshal.Copy(data.Scan0, buffer, 0, buffer.Length);
int xMin = int.MaxValue,
xMax = int.MinValue,
yMin = int.MaxValue,
yMax = int.MinValue;
bool foundPixel = false;
// Find xMin
for (int x = 0; x < data.Width; x++)
{
bool stop = false;
for (int y = 0; y < data.Height; y++)
{
byte alpha = buffer[y * data.Stride + 4 * x + 3];
if (alpha != 0)
{
xMin = x;
stop = true;
foundPixel = true;
break;
}
}
if (stop)
break;
}
// Image is empty...
if (!foundPixel)
return null;
// Find yMin
for (int y = 0; y < data.Height; y++)
{
bool stop = false;
for (int x = xMin; x < data.Width; x++)
{
byte alpha = buffer[y * data.Stride + 4 * x + 3];
if (alpha != 0)
{
yMin = y;
stop = true;
break;
}
}
if (stop)
break;
}
// Find xMax
for (int x = data.Width - 1; x >= xMin; x--)
{
bool stop = false;
for (int y = yMin; y < data.Height; y++)
{
byte alpha = buffer[y * data.Stride + 4 * x + 3];
if (alpha != 0)
{
xMax = x;
stop = true;
break;
}
}
if (stop)
break;
}
// Find yMax
for (int y = data.Height - 1; y >= yMin; y--)
{
bool stop = false;
for (int x = xMin; x <= xMax; x++)
{
byte alpha = buffer[y * data.Stride + 4 * x + 3];
if (alpha != 0)
{
yMax = y;
stop = true;
break;
}
}
if (stop)
break;
}
srcRect = Rectangle.FromLTRB(xMin, yMin, xMax, yMax);
}
finally
{
if (data != null)
source.UnlockBits(data);
}
Bitmap dest = new Bitmap(srcRect.Width, srcRect.Height);
Rectangle destRect = new Rectangle(0, 0, srcRect.Width, srcRect.Height);
using (Graphics graphics = Graphics.FromImage(dest))
{
graphics.DrawImage(source, destRect, srcRect, GraphicsUnit.Pixel);
}
return dest;
}
एक महत्वपूर्ण लाभ वहाँ नहीं होगा अगर अपारदर्शी हिस्सा निश्चित रूप से छोटा है, के बाद से यह अभी भी अधिकांश पिक्सेल स्कैन करेगा। लेकिन यदि यह बड़ा है, तो गैर पारदर्शी भाग के आसपास केवल आयताकार स्कैन किए जाएंगे।
कटऑफ सीधे है? यदि हां, तो एल-> आर और टी-> बी से पिक्सल पढ़ना बहुत तेज़ काम करेगा। –
यदि यह वर्ग है, तो आप संभवत: अधिक समय और बाइनरी को सभी 4 पक्षों पर केंद्र से बाहर खोज सकते हैं (कम से कम पिक्सेल पूछताछ पर काट रहे हैं) –
क्या छोटी, एम्बेडेड छवि में इसके भीतर पारदर्शी पिक्सेल भी हो सकते हैं? –