Search code examples
visual-c++bitmapc++-cligdi+foxit

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.


Solution

  • 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.