Determine if color bitmap is black and white
I have a HBitmap I am recieving from an API i am using to convert pages in PDF documents. The resulting bitmap is 24 bit color bitmap. I am trying to determine, using black and white scanned images that were made into pdfs, are black and white on the resulting bitmap from Foxit. Foxit is the PDF API. Here is some Code! (c++/cli)
// Get HBITMAP using Foxit's RenderPage function
// to convert to dib later
IntPtr hbitmap = FlattenPageToHBitmap(filename, page);
if (hbitmap == IntPtr::Zero)
return IntPtr::Zero;
Bitmap^ b = Bitmap::FromHbitmap(hbitmap);
bool isColor = false;
for (int y = 0; y < b->Height; y++)
{
for (int x = 0; x < b->Width; x++)
{
Color^ c = b->GetPixel(x, y);
unsigned int bits = (int)c->ToArgb();
bits = bits << 8;
bits = bits >> 8; //should get rid of A in ARGB
bool white = (bits == 0xFFFFFF);
bool black = (bits == 0);
if (!black && !white)
{
isColor = true;
break;
}
}
if (isColor)
break;
}
}
once I have this HBitmap and have determined its colors, I will convert the HBitmap to a Device-Independent Bitmap which I can use our in-house toolkit to write back to various document formats.
The 开发者_运维问答Problem
The resulting HBitmap from Foxit never seems to be fully black or white. Is there an algorithm I can use to see if its "close enough" and convert it? the pixel format of the bitmap is used when saving it back out to a pdf to determine the compression used.
Sure, just calculate luminance and test if it's really near zero or one.
Color c = b->GetPixel(x, y); // no ^ because Color is a value type
float Y = (0.2126*c.R + 0.7152*c.G + 0.0722*c.B) / 255;
bool white = (Y > .95);
bool black = (Y < .05);
if (!black && !white)
{
isColor = true;
break;
}
Using the luminance formula from Wikipedia.
Or, Y = c.GetBrightness();
could also work.
If you know how to get R, G and B for every pixel, then BW picture should have R == G == B.
If it isn't and you want it to be grayscale, use this formula to calculate new RGB values:
value = 0.3 R + 0.59 G + 0.11 B
Fill R, G and B with value and there you go.
Do you mean it uses colors which are very dark gray (ie. essentially black) or very light gray (ie. essentially white); or do you mean most (but not all) of the pixels are black or white?
For the first, you could find a "distance" function. Eg. dist = R*R+G*G+B*B. Then choose thresholds that define how black or how white. similarly, you could say "black is when R < a && G < a && B < a" where a is your threshold.
As for pixels, you could count up all pixels that meet the threshold, and decide if more than 80% (say) meet the threshold then it is black or white.
Although there are already answers given, they seem to involve some magic numbers. Here's a general, more adjustable approach in case you for some strange reason have to use RGB (I just realized that it's of course trivial with HSV/HSL):
According to Wikipedia, true gray colors are those for which redness = greenness = blueness, i.e. those colors on the diagonal of the RGB color-space. Since you also want near-gray colors, we'll define a color as threshold t neargray for a t >= 0 if it lies in a radius t tubular neighborhood of the diagonal. Thus, to determine if an RGB-color x is threshold t neargray, simply calculate the distance r between x and its orthogonal projection onto the diagonal. If r <= t, x is "gray enough". Adjust t to your liking.
精彩评论