使用GDI+将24 bpp转换为4 bpp

9 浏览
0 Comments

使用GDI+将24 bpp转换为4 bpp

我的程序目前将4 bpp(每像素位数)的TIFF作为位图输入,将其转换为图形,添加一些文本字符串,然后再将其保存为TIFF文件。默认情况下,输出的Bitmap.Save() TIFF文件似乎是24 bpp(无论输入是什么),并且比原始TIFF文件大得多。

是否可以保持与输入相同的4 bpp调色板编码的输出,如果不可以,如何将我的位图像素格式从24 bpp转换为4 bpp-indexed?

我在Bob Powell: Locking Bits 上看到了将24 bpp转换为1 bpp的示例,但是无法弄清楚如何将其应用于4 bpp。

0
0 Comments

问题:将24 bpp转换为4 bpp的问题出现的原因是需要将一个原始的24 bpp位图转换为4 bpp位图,以减少内存占用和提高处理速度。

解决方法:使用GDI+的功能将24 bpp位图转换为4 bpp位图。具体步骤如下:

1. 将原始位图转换为GDI hbitmap。

2. 创建一个GDI单色hbitmap。

3. 使用GDI的"BitBlt"函数将原始hbitmap复制到单色位图中。

4. 将单色hbitmap转换为位图。

具体实现代码如下:

Public Class BitmapEncoder
    Public Shared Function ConvertBitmapToSpecified(ByVal b As System.Drawing.Bitmap, ByVal bpp As Integer) As System.Drawing.Bitmap
        '根据目标bpp的值进行判断和处理
        Select Case bpp
            Case 1
            Case 4
            Case 8
            Case Else
                Throw New ArgumentException("bpp must be 1, 4 or 8")
        End Select
        '将原始位图转换为GDI hbitmap
        Dim w As Integer = b.Width, h As Integer = b.Height
        Dim hbm As IntPtr = b.GetHbitmap()
        '创建单色位图的BITMAPINFO结构
        Dim bmi As New BITMAPINFO()
        bmi.biSize = 40
        bmi.biWidth = w
        bmi.biHeight = h
        bmi.biPlanes = 1
        bmi.biBitCount = CShort(bpp)
        bmi.biCompression = BI_RGB
        bmi.biSizeImage = CUInt((((w + 7) And &HFFFFFFF8) * h / 8))
        bmi.biXPelsPerMeter = 1000000
        bmi.biYPelsPerMeter = 1000000
        Dim ncols As UInteger = CUInt(1) << bpp
        bmi.biClrUsed = ncols
        bmi.biClrImportant = ncols
        bmi.cols = New UInteger(255) {}
        '创建单色位图的hbitmap
        Dim bits0 As IntPtr
        Dim hbm0 As IntPtr = CreateDIBSection(IntPtr.Zero, bmi, DIB_RGB_COLORS, bits0, IntPtr.Zero, 0)
        '使用GDI的BitBlt函数将原始hbitmap复制到单色位图中
        Dim sdc As IntPtr = GetDC(IntPtr.Zero)
        Dim hdc As IntPtr = CreateCompatibleDC(sdc)
        SelectObject(hdc, hbm)
        Dim hdc0 As IntPtr = CreateCompatibleDC(sdc)
        SelectObject(hdc0, hbm0)
        BitBlt(hdc0, 0, 0, w, h, hdc, 0, 0, SRCCOPY)
        '将单色hbitmap转换为位图
        Dim b0 As System.Drawing.Bitmap = System.Drawing.Bitmap.FromHbitmap(hbm0)
        '清理资源
        DeleteDC(hdc)
        DeleteDC(hdc0)
        ReleaseDC(IntPtr.Zero, sdc)
        DeleteObject(hbm)
        DeleteObject(hbm0)
        Return b0
    End Function
    '其他函数和结构体定义
    '...
End Class

使用方法:

'加载原始图像

Using B As New Bitmap("c:\test.tiff")

'对图像进行处理

'...

'将图像转换为4bpp

Using I = BitmapEncoder.ConvertBitmapToSpecified(B, 4)

'保存到磁盘

I.Save("c:\test2.tiff")

End Using

End Using

需要注意的是,这里保存的是PNG格式的图像,而不是TIF格式的。无论如何,这正是我所需要的解决方案。

0