将类转换为类库并实例化

时间:2018-11-01 03:50:21

标签: c# .net vb.net

我有一个很久以前在VB.net上写过的课。我想在C#中使用该类,因此为了节省时间,我想我只是将其转换为类库。我在执行此操作时有些困惑。实例化原始类时,将使用System.Drawing.Save()方法保存图像文件。参见下文imageConv.Save(filePath)

Imports System.Drawing
...
...
''' <summary>
'''     Convert the image to a smaller more manageable 4-bit png
''' </summary>
Private Shared Function ConvertImage(filepath As String) As String
    Using image As New Bitmap(filepath)
        'Do Stuff
        'Convert it to 4BPP
        Using imageConv = BitmapEncoder.Convert(image, 4)
            'Update the filepath for saving
            filepath = Path.GetTempPath & "image.png"
            'Save to disk
            imageConv.Save(filepath)
        End Using
    End Using
    ConvertImage = filepath
End Function

现在,当我将类复制到类库项目中,在C#项目中添加引用并实例化该类时,我将无法再使用Save方法。

    private static void compressBitmap(ImageData imgData)
    {
        using (Bitmap imageRaw = new Bitmap(imgData.bmpFilePath))
        { 
            using (ConvertBitmap imageCompressed = new ConvertBitmap())
            {
                imageCompressed.Convert(imageRaw, 4);
                //imageCompressed.Save(imgData.bmpFilePath);
            }
        }
    }

我在这里想念什么?我知道我需要实例化ConvertBitmap imageCompressed = new ConvertBitmap.Convert(imageRaw, 4)),但是它说类型'ConvertBitmap'中不存在'Convert'。确实可以。这是一个公共功能。

Imports System.Drawing
Imports System.Runtime.InteropServices
Imports Microsoft.Win32.SafeHandles
''' <summary>
'''     Copies a bitmap into a 1bpp/4bpp/8bpp bitmap of the same dimensions, fast
''' </summary>
Public Class ConvertBitmap : Implements IDisposable
    ' Flag: Has Dispose already been called?
    Dim disposed As Boolean = False
    ' Instantiate a SafeHandle instance.
    Dim handle As SafeHandle = New SafeFileHandle(IntPtr.Zero, True)

''' <summary>
''' Public implementation of Dispose pattern callable by consumers.
''' </summary>
Public Sub Dispose() _
          Implements IDisposable.Dispose
    Dispose(True)
    GC.SuppressFinalize(Me)
End Sub

''' <summary>
''' Protected implementation of Dispose pattern.
''' </summary>
''' <param name="disposing"></param>
Protected Overridable Sub Dispose(disposing As Boolean)
    If disposed Then Return

    If disposing Then
        handle.Dispose()
        ' Free any other managed objects here.
        '
    End If

    disposed = True
End Sub

''' <param name="b">original bitmap</param>
''' <param name="bpp">1 or 8, target bpp</param>
''' <returns>a 1bpp copy of the bitmap</returns>
Public Function Convert(b As Bitmap, bpp As Integer) As Bitmap
    Select Case bpp
        Case 1
        Case 4
        Case 8
        Case Else
            Throw New ArgumentException("bpp must be 1, 4 or 8")
    End Select

    ' Plan: built into Windows GDI is the ability to convert
    ' bitmaps from one format to another. Most of the time, this
    ' job is actually done by the graphics hardware accelerator card
    ' and so is extremely fast. The rest of the time, the job is done by
    ' very fast native code.
    ' We will call into this GDI functionality from C#. Our plan:
    ' (1) Convert our Bitmap into a GDI hbitmap (ie. copy unmanaged->managed)
    ' (2) Create a GDI monochrome hbitmap
    ' (3) Use GDI "BitBlt" function to copy from hbitmap into monochrome (as above)
    ' (4) Convert the monochrone hbitmap into a Bitmap (ie. copy unmanaged->managed)

    Dim w As Integer = b.Width, h As Integer = b.Height
    Dim hbm As IntPtr = b.GetHbitmap()
    ' this is step (1)
    '
    ' Step (2): create the monochrome bitmap.
    ' "BITMAPINFO" is an interop-struct which we define below.
    ' In GDI terms, it's a BITMAPHEADERINFO followed by an array of two RGBQUADs
    Dim bmi As New Bitmapinfo()
    bmi.biSize = 40
    ' the size of the BITMAPHEADERINFO struct
    bmi.biWidth = w
    bmi.biHeight = h
    bmi.biPlanes = 1
    ' "planes" are confusing. We always use just 1. Read MSDN for more info.
    bmi.biBitCount = CShort(bpp)
    ' ie. 1bpp or 8bpp
    bmi.biCompression = _biRgb
    ' ie. the pixels in our RGBQUAD table are stored as RGBs, not palette indexes
    bmi.biSizeImage = CUInt((((w + 7) And &HFFFFFFF8) * h / 8))
    bmi.biXPelsPerMeter = 1000000
    ' not really important
    bmi.biYPelsPerMeter = 1000000
    ' not really important
    ' Now for the colour table.
    Dim ncols As UInteger = CUInt(1) << bpp
    ' 2 colours for 1bpp; 256 colours for 8bpp
    bmi.biClrUsed = ncols
    bmi.biClrImportant = ncols
    bmi.cols = New UInteger(255) {}
    ' The structure always has fixed size 256, even if we end up using fewer colours
    If bpp = 1 Then
        bmi.cols(0) = Makergb(0, 0, 0)
        bmi.cols(1) = Makergb(255, 255, 255)
    ElseIf bpp = 4 Then
        bmi.biClrUsed = 16
        bmi.biClrImportant = 16
        Dim colv1 = New Integer(15) {8, 24, 38, 56, 72, 88, 104, 120, 136, 152, 168, 184, 210, 216, 232, 248}

        For i = 0 To 15
            bmi.cols(i) = Makergb(colv1(i), colv1(i), colv1(i))
        Next
    ElseIf bpp = 8 Then
        For i = 0 To ncols - 1
            bmi.cols(i) = Makergb(i, i, i)
        Next
    End If
    ' For 8bpp we've created an palette with just greyscale colours.
    ' You can set up any palette you want here. Here are some possibilities:
    ' greyscale: for (int i=0; i<256; i++) bmi.cols[i]=MAKERGB(i,i,i);
    ' rainbow: bmi.biClrUsed=216; bmi.biClrImportant=216; int[] colv=new int[6]{0,51,102,153,204,255};
    '          for (int i=0; i<216; i++) bmi.cols[i]=MAKERGB(colv[i/36],colv[(i/6)%6],colv[i%6]);
    ' optimal: a difficult topic: http://en.wikipedia.org/wiki/Color_quantization
    '
    ' Now create the indexed bitmap "hbm0"
    Dim bits0 As IntPtr
    ' not used for our purposes. It returns a pointer to the raw bits that make up the bitmap.
    Dim hbm0 As IntPtr = CreateDIBSection(IntPtr.Zero, bmi, _dibRgbColors, bits0, IntPtr.Zero, 0)
    '
    ' Step (3): use GDI's BitBlt function to copy from original hbitmap into monocrhome bitmap
    ' GDI programming is kind of confusing... nb. The GDI equivalent of "Graphics" is called a "DC".
    Dim sdc As IntPtr = GetDC(IntPtr.Zero)
    ' First we obtain the DC for the screen
    ' Next, create a DC for the original hbitmap
    Dim hdc As IntPtr = CreateCompatibleDC(sdc)
    SelectObject(hdc, hbm)
    ' and create a DC for the monochrome hbitmap
    Dim hdc0 As IntPtr = CreateCompatibleDC(sdc)
    SelectObject(hdc0, hbm0)
    ' Now we can do the BitBlt:
    BitBlt(hdc0, 0, 0, w, h, hdc,
           0, 0, _srccopy)
    ' Step (4): convert this monochrome hbitmap back into a Bitmap:
    Dim b0 As Bitmap = Bitmap.FromHbitmap(hbm0)
    '
    ' Finally some cleanup.
    DeleteDC(hdc)
    DeleteDC(hdc0)
    ReleaseDC(IntPtr.Zero, sdc)
    DeleteObject(hbm)
    DeleteObject(hbm0)
    '
    Return b0
End Function

Private Shared _srccopy As Integer = &HCC0020
Private Shared _biRgb As UInteger = 0
Private Shared _dibRgbColors As UInteger = 0

<DllImport("gdi32.dll")>
Private Shared Function DeleteObject(hObject As IntPtr) As Boolean
End Function

<DllImport("user32.dll")>
Private Shared Function GetDC(hwnd As IntPtr) As IntPtr
End Function

<DllImport("gdi32.dll")>
Private Shared Function CreateCompatibleDC(hdc As IntPtr) As IntPtr
End Function

<DllImport("user32.dll")>
Private Shared Function ReleaseDC(hwnd As IntPtr, hdc As IntPtr) As Integer
End Function

<DllImport("gdi32.dll")>
Private Shared Function DeleteDC(hdc As IntPtr) As Integer
End Function

<DllImport("gdi32.dll")>
Private Shared Function SelectObject(hdc As IntPtr, hgdiobj As IntPtr) As IntPtr
End Function

<DllImport("gdi32.dll")>
Private Shared Function BitBlt(hdcDst As IntPtr, xDst As Integer, yDst As Integer, w As Integer, h As Integer,
                               hdcSrc As IntPtr,
                               xSrc As Integer, ySrc As Integer, rop As Integer) As Integer
End Function

<DllImport("gdi32.dll")>
Private Shared Function CreateDIBSection(hdc As IntPtr, ByRef bmi As Bitmapinfo, usage As UInteger,
                                         ByRef bits As IntPtr, hSection As IntPtr, dwOffset As UInteger) As IntPtr
End Function

<StructLayout(LayoutKind.Sequential)>
Private Structure Bitmapinfo
    Public biSize As UInteger
    Public biWidth As Integer, biHeight As Integer
    Public biPlanes As Short, biBitCount As Short
    Public biCompression As UInteger, biSizeImage As UInteger
    Public biXPelsPerMeter As Integer, biYPelsPerMeter As Integer
    Public biClrUsed As UInteger, biClrImportant As UInteger
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=256)> Public cols As UInteger()
End Structure

Private Shared Function Makergb(r As Integer, g As Integer, b As Integer) As UInteger
    Return CUInt((b And 255)) Or CUInt(((r And 255) << 8)) Or CUInt(((g And 255) << 16))
End Function

Public Sub New()
End Sub

End Class

1 个答案:

答案 0 :(得分:2)

收到此错误消息的原因:

  

类型“ ConvertBitmap”中不存在“转换”。

这行代码没有按照您的想象做:

ConvertBitmap imageCompressed = new ConvertBitmap.Convert(imageRaw, 4))

该代码正在寻找在Convert类内声明的名为ConvertBitmap(不是方法)的类型,该类型具有一个采用Bitmapint的构造函数作为参数。显然没有这种类型。

您实际需要做的是创建一个ConvertBitmap对象,调用其Convert方法以获得一个Bitmap对象,然后在该对象上调用Save

private static void compressBitmap(ImageData imgData)
{
    using (Bitmap imageRaw = new Bitmap(imgData.bmpFilePath))
    { 
        using (ConvertBitmap imageCompressed = new ConvertBitmap())
        {
            imageCompressed.Convert(imageRaw, 4).Save(imgData.bmpFilePath);
        }
    }
}