I\'m wondering if there\'s a super-efficient way of confirming that an Image object references an entirely black image, so every pixel within the bitmap is ARGB(255, 0, 0, 0).
private bool AllOneColor(Bitmap bmp)
{
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
byte[] rgbValues = new byte[bmpData.Stride * bmpData.Height];
System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, rgbValues, 0, rgbValues.Length);
bmp.UnlockBits(bmpData);
return !rgbValues.Where((v, i) => i % bmpData.Stride < bmp.Width && v != rgbValues[0]).Any();
}
To be entirely sure of the image's blackness, you will have to check every pixel, and accessing the pixel data in an unsafe block is likely the fastest way to do it. Of course it's possible to optimize for the non-black case and try to find those earlier, but in the worst case you'll always have to check each and every pixel.
One trick that may do it as well is put an indicator pixel somewhere, which always has the same color, unless the image capture fails, in which case everything would be completely black I assume
If you knew more about the conditions under which the image would be non-black, it would be easier. For example, what do the edges or center of the image look like when it's non-black. Essentially, what you create is heuristic to guess at a non-black image and sample those areas that will give you the quickest read on it. If your heuristic indicates a all-black image, then you can either decide that it is all-black or do a full check of all pixels. That's heavily dependent on your images, though. If you have to be able to distinguish between an all-black image and one containing a single non-black pixel in a random location, you'll have to check them all.
Lock the bitmap into memory and scan it with bitwise operations. Don't use GetPixel
and the like; that's slow.
I'd recommend you to lock the bitmap in the memory using the LockBits method of the System.Drawing.Bitmap type. This method returns the BitmapData type, from which you can receive a pointer to the locked memory region. Then iterate through the memory, searching for the non-zero bytes (really, faster by scanning for the Int32 or even Int64 values, depending on the platform you use). Code will look like this:
// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bmpData =bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);
// Get the address of the first line.
IntPtr ptr = bmpData.Scan0;
// Declare an array to hold the bytes of the bitmap.
int bytes = bmpData.Stride * bmp.Height;
byte[] rgbValues = new byte[bytes];
// Copy the RGB values into the array.
Marshal.Copy(ptr, rgbValues, 0, bytes);
// Scanning for non-zero bytes
bool allBlack = true;
for (int index = 0; index < rgbValues.Length; index++)
if (rgbValues[index] != 0)
{
allBlack = false;
break;
}
// Unlock the bits.
bmp.UnlockBits(bmpData);
Consider using the unsafe code and direct memory access (using pointers) to improve performance.