【问题标题】:Determine if color bitmap is black and white判断彩色位图是否为黑白
【发布时间】:2010-11-04 15:58:49
【问题描述】:

我有一个从 API 接收的 HBitmap,我用它来转换 PDF 文档中的页面。生成的位图是 24 位彩色位图。我正在尝试使用制作成 pdf 的黑白扫描图像来确定 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 以确定使用的压缩时使用。

【问题讨论】:

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


    【解决方案1】:

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

    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(); 也可以工作。

    【讨论】:

      【解决方案2】:

      如果你知道如何得到每个像素的 R、G 和 B,那么 BW 图片应该有 R == G == B。

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

      value = 0.3 R + 0.59 G + 0.11 B
      

      用值填充 R、G 和 B,然后就可以了。

      【讨论】:

      • 为什么是这些数字(0.3、0.59、0.11)?另外,如果RGB图像是灰度的,我想确定它是否“接近”到BW。
      • 顺便说一句,列出您从哪里获得该亮度公式可能会很有用,因为我建议使用相同的方法,但在 Wikipedia 上找到了不同的公式。
      • scantips.com/lumin.html,我以为你想要灰度,它是用 RGB 编码的。我的错。
      【解决方案3】:

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

      首先,您可以找到“距离”函数。例如。距离 = R*R+G*G+B*B。然后选择定义多黑或多白的阈值。同样,您可以说“黑色是当 R

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

      【讨论】:

      • 我喜欢 80% 的想法。很简单。我也对其他一些想法感兴趣。
      【解决方案4】:

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

      根据Wikipedia,真正的灰色是那些红色=绿色=蓝色的颜色,即RGB颜色空间对角线上的那些颜色。由于您还需要接近灰色的颜色,因此我们将颜色定义为 threshold t neargray,如果它位于对角线的半径 t 管状邻域内,则 t >= 0。因此,要确定一个 RGB 颜色 x 是否是阈值 t neargray,只需计算 x 与其orthogonal projection 在对角线上的距离 r。如果 r

      【讨论】:

      • 我不认为汤姆想知道图像是否是灰度(或单色),我想他想知道它是否是黑白的,即可以有效地存储为 1 位色深.
      猜你喜欢
      • 2013-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-03
      • 2012-05-01
      • 2011-10-19
      相关资源
      最近更新 更多