【问题标题】:Having issue converting 32 bit images to bitonal black and white将 32 位图像转换为双色调黑白时出现问题
【发布时间】:2013-09-23 16:00:13
【问题描述】:

我有以下代码例程...

Public Shared Sub ConvertToBitonal(ByRef Source As System.Windows.Media.Imaging.WriteableBitmap)
    If Source.Format = System.Windows.Media.PixelFormats.BlackWhite Then
        Exit Sub
    End If

    Dim BytesPerPixel As Integer = (Source.Format.BitsPerPixel + 7) / 8
    Dim Stride As Integer = Source.PixelWidth * BytesPerPixel
    Dim NumBytes As Long = Source.PixelHeight * Stride
    Dim pixels As Byte() = New Byte(NumBytes - 1) {}

    Source.CopyPixels(pixels, Stride, 0)

    For cnt As Integer = 0 To pixels.Length - 1 Step BytesPerPixel
        Dim blue As Byte = pixels(cnt + 0)
        Dim green As Byte = pixels(cnt + 1)
        Dim red As Byte = pixels(cnt + 2)
        Dim intensity As Integer = CType(red, Integer) + CType(green, Integer) + CType(blue, Integer)
        Dim targetColor As Byte

        If intensity > 400 Then
            targetColor = 255
        Else
            targetColor = 0
        End If

        pixels(cnt + 0) = targetColor
        pixels(cnt + 1) = targetColor
        pixels(cnt + 2) = targetColor
        pixels(cnt + 3) = targetColor
    Next

    Source.WritePixels(New System.Windows.Int32Rect(0, 0, Source.PixelWidth, Source.PixelHeight), pixels, Stride, 0)
End Sub

当源图像是每像素 24 位的种类时,输出完全符合我的要求,但是当源图像是 32 位时,颜色不是纯色的,并且我在整个图像中出现垂直线。谁能告诉我如何修改例程以使 32 位图像像他们的 24 位计数器一样出来?

这是我正在谈论的内容的屏幕截图......(显然我还没有足够的代表来发布图片,所以这里是一个链接

【问题讨论】:

    标签: .net wpf vb.net image-processing imaging


    【解决方案1】:

    您可能必须先创建图像的 24bpp 副本。你试过吗?

    我很久以前做过类似的事情(很久以前无法回忆细节),这篇文章很有帮助:Bitonal conversion issues。 MSDN论坛上也有一些信息。

    编辑:seen this entry?

    【讨论】:

    • Re: Posted URLs... 是的,我熟悉那两篇文章。我发布的这段代码来自我最初在 GDI+ 中编写的文档成像系统查看器。您详细介绍的帖子也指的是GDI的做事方式。然而,随着存储变得更便宜并且相机增加了百万像素,我们的成像系统(和 GDI+)已经遇到了它可以处理的图像大小的限制......这导致我现在......我目前正在重写系统用于可以处理更大图像的 WPF。
    • 回复:首先创建一个 24 bbp 的副本。这也是我的第一个想法......不过,这种方法对我来说的问题是,当我使用 FormatConvertedBitmap 来更改图像时,缓存会发生一些时髦的事情,导致图像有时会变成 1x1 像素图像(即使图像要大得多)。
    • 回答:如果有人遇到这种情况,我必须做的就是将其转换为每像素 24 位。图像变成 1x1 像素的原因是我的保存例程中的内存不足,该例程保存在从第 1 页到 N 的循环中。似乎使用 WPF 位图源及其派生类的技巧是你不能代码块中的作用域变量,并期望垃圾收集能够拾取它们 - 即使您显式调用垃圾收集。
    • 继续:相反,声明适用于整个例程的变量(在我的情况下,在循环之外)并重用它们。一遍又一遍地重复使用相同的变量是我似乎可以释放内存的唯一方法。
    【解决方案2】:

    我挖掘了代码并发现了问题:

    Dim BytesPerPixel As Integer = (Source.Format.BitsPerPixel + 7) / 8
    

    删除+ 7

    也改变这个:

        pixels(cnt + 0) = targetColor
    
        pixels(cnt + 1) = targetColor
    
        pixels(cnt + 2) = targetColor
    
        pixels(cnt + 3) = targetColor
    

    到包含该步骤的 FOR 循环.....即:

            Dim x%
    
            For x = cnt To cnt + BytesPerPixel - 1
    
                pixels(x) = targetColor
    
            Next
    

    如果步长 > 4,则不会设置该值,并且会为您提供此条。

    【讨论】:

    • BytesPerPixel 计算源自完整公式,其中 bpp 乘以图像宽度,然后 +7 然后除以 8。对于 bpp 低于 8 的图像,这是必要的, 将部分使用的数据四舍五入到下一个完整字节。但如果不涉及宽度,代码似乎相当无用,因为它假定 4bpp 图像的像素宽度为 1,如果该值随后用于计算实际字节宽度,则这是不正确的。
    • 也就是说,对于 bpp 完全可被 8 整除的图像(大多数 >=8bpp 是),+7 将完全没有影响,因为 int 总是向下舍入,所以没有必要删除它。而且您的其他编辑也只是代码优化(甚至没有优化程序效率),而不是修复...
    猜你喜欢
    • 2013-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多