Suppose we have this 32bppRGBA image
As you can see, its a 1920x1080 image with only small red rectangle and i would like to cut only the non transpert pixels of this image(in our case only the small little block).
So i started scanning this image and getting the non transpert block bounds. This is what i have done so far:
private unsafe Bitmap CodeImage(Bitmap bmp)
{
Bitmap bmpRes = new Bitmap(bmp.Width, bmp.Height);
BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
IntPtr scan0 = bmData.Scan0;
int stride = bmData.Stride;
int nWidth = bmp.Width;
int nHeight = bmp.Height;
int minX = 10000 ;
int maxX = -10000;
int minY = 10000;
var maxY = -10000;
for (int y = 0; y < nHeight; y++)
{
byte* p = (byte*)scan0.ToPointer();
p += y * stride;
for (int x = 0; x < nWidth; x++)
{
if (p[3]!=0) //Check if pixel is not transpert;
{
if (x < minX)
minX = x;
if (y < minY)
minY = y;
if (x > maxX)
maxX = x;
if (y > maxY)
maxY = y;
}
p += 4;
}
}
bmp.UnlockBits(bmData);
Rectangle temp = new Rectangle(minX, minY,maxX, maxY);
// MessageBox.Show(minX.ToString() + "," + minY.ToString() + "," + maxX.ToString() + "," + maxY.ToString());
return bmp.Clone(temp,bmp.PixelFormat);
}
But im getting odd results...i think this is a simple typo i cant figure out.. or maybe it's somthing wrong with the logic of the code...
I would appreciate and incoming help!
I just answered this on his other post: Cut transparent parts image
public static Bitmap Trim(string fileName)
{
Bitmap bmp = null;
try
{
bmp = Bitmap.FromFile(fileName) as Bitmap;
if (bmp == null)
throw new ArgumentException("The file is not a valid image.");
if (bmp.PixelFormat != PixelFormat.Format32bppArgb)
throw new ArgumentException("The image file is in an invalid format (32bpp ARGB required)");
}
catch (Exception ex)
{
throw new ArgumentException("The file is not a valid image.", ex);
}
BitmapData bmpData = null;
int minX, minY, maxX, maxY;
minX = minY = int.MaxValue;
maxX = maxY = int.MinValue;
try
{
bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = bmpData.Stride * bmp.Height;
int[] pixelData = new int[bmp.Width * bmp.Height];
System.Runtime.InteropServices.Marshal.Copy(ptr, pixelData, 0, pixelData.Length);
for (int y = 0; y < bmp.Height; y++)
{
for (int x = 0; x < bmp.Width; x++)
{
Color pixel = Color.FromArgb(pixelData[x + (bmp.Width * y)]);
if (pixel.A != 0)
{
if (x < minX) minX = x;
if (x > maxX) maxX = x;
if (y < minY) minY = y;
if (y > maxY) maxY = y;
}
}
}
pixelData = null;
Rectangle cutRect = new Rectangle(minX, minY, maxX - minX, maxY - minY);
bmp.UnlockBits(bmpData);
return bmp.Clone(cutRect, bmp.PixelFormat);
}
finally
{
}
}
I think the biggest problem is the incorrect calculation of the rectangle. You have a min x/y and a max x/y, and you are using it as x, y, width, height. You need to calculate the width/height from the max x/y subtracted from the min values.
The other issue is that the pixel format is 32BPP ARGB, not RGBA, so the alpha channel comes first, not at index 3. The best thing to do is to create the Color
structure from the integer value and examine that, but the algorithm above only works on 32bpp ARGB values since color only has a FromARGB
function.