确定颜色位图是否为黑色和白色

时间:2010-11-04 15:58:50

标签: visual-c++ bitmap c++-cli gdi+ foxit

我有一个HBitmap我从一个用于转换PDF文档中的页面的API中收到的。生成的位图是24位彩色位图。我试图确定,使用制作成pdfs的黑白扫描图像,在Foxit生成的位图上是黑白的。 Foxit是PDF API。这是一些代码! (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;
    }
}

一旦我有了这个HBitmap并确定了它的颜色,我会将HBitmap转换为独立于设备的位图,我可以使用我们的内部工具包来回写各种文档格式。

问题

Foxit产生的HBitmap似乎永远不会是完全黑色或白色。有没有一种算法可以用来查看它是否“足够接近”并转换它?将位图保存回pdf时使用位图的像素格式来确定使用的压缩。

4 个答案:

答案 0 :(得分:6)

当然,只需计算亮度并测试它是否真的接近零或一。

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;
}

使用the luminance formula from Wikipedia

或者,Y = c.GetBrightness();也可以。

答案 1 :(得分:4)

如果你知道如何为每个像素获得R,G和B,那么BW图片应该有R == G == B.

如果不是,并且您希望它是灰度,请使用此公式计算新的RGB值:

value = 0.3 R + 0.59 G + 0.11 B

用值填充R,G和B,然后你去。

答案 2 :(得分:1)

你的意思是它使用深灰色(即基本上是黑色)或非常浅灰色(即基本上是白色)的颜色;或者你的意思是大多数(但不是全部)像素是黑色还是白色?

首先,您可以找到“距离”功能。例如。 dist = R * R + G * G + B * B.然后选择定义黑色或白色的阈值。类似地,你可以说“黑色是当R&lt; a&amp;&amp; G&lt; a&amp;&amp; B&lt; a”,其中a是你的门槛。

对于像素,您可以计算满足阈值的所有像素,并确定是否超过80%(比如说)达到阈值,然后是黑色或白色。

答案 3 :(得分:1)

虽然已经给出了答案,但它们似乎涉及一些神奇的数字。这是一个通用的,更可调的方法,以防你因某些奇怪的原因必须使用RGB(我刚刚意识到它对于HSV / HSL来说当然是微不足道的):

根据Wikipedia,真正的灰色是红色=绿色=蓝色的颜色,即RGB颜色空间对角线上的那些颜色。由于您还需要近灰色,如果t> = 0,我们将颜色定义为阈值t neargray ,如果它位于对角线的半径t管状邻域中。因此,为了确定RGB颜色x是否接近阈值t,只需计算x与其orthogonal projection之间的距离r到对角线上。如果r <= t,则x为“足够灰”。根据自己的喜好调整。