Reputation: 9013
I need to have a quick way to check whether image of monochromatic or not. I mean I need to verify that the image contains just a single color (black, white, red square...) instead of containing multiple colors.
Of course, I can compare all pixels of image with first, but it can be slow. Any another way to check it?
Upvotes: 1
Views: 664
Reputation: 22271
It depends on your definition of slow. I am finding that it takes about 12 ms to scan a 1MP image if all pixels need to be evaluated, and significantly shorter (nanoseconds in most cases, since the first and second pixels are different) on a random sampling of images.
Test code (Core i5 on W8.1 x64, compiled with /unsafe /platform:x64
on .Net 4.5):
private unsafe bool CheckBitmapIsMonotonic(Bitmap newBitmap)
{
var data = newBitmap.LockBits(new Rectangle(Point.Empty, newBitmap.Size),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
try
{
byte* pixelData = (byte*)data.Scan0.ToPointer();
uint firstPixelData = *((uint*)pixelData);
for (int row = 0; row < data.Height; row++)
{
uint* cRowPointer = (uint*)(pixelData + data.Stride * row);
for (int column = 0; column < data.Width; column++)
{
var rgbPixelValue = cRowPointer[column];
if (firstPixelData != rgbPixelValue)
{
return false;
}
}
}
return true;
}
finally
{
newBitmap.UnlockBits(data);
}
}
This is just a first pass. You may be able to squeeze some extra performance by moving to ulong
rather than uint
and compare two pixels at once, and if you can avoid the conversion to ARGB
, all the better.
Upvotes: 3
Reputation: 1803
This highly depends on the image formats you would like to support (PNG, BMP, etc).
For instance, if the image uses a color palette (some types of PNG do), you could check if the palette has only one color entry. (see System.Drawing.Image.Palette).
But in general, you will probably have to check every pixel to make sure.
Upvotes: 1