📄 cgdiplus.cls
字号:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "cGDIPlus"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
' No APIs are declared public. This is to prevent possibly, differently
' declared APIs, or different versions of the same API, from conflciting
' with any APIs you declared in your project. Same rule for UDTs.
' Note: I did take some liberties in several API declarations throughout
Private Declare Function CLSIDFromString Lib "ole32" (ByVal lpszProgID As Long, pCLSID As Any) As Long
Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (ByRef Ptr() As Any) As Long
' following are used for saving dib to PNG (testing phase only)
Private Declare Function GdipImageRotateFlip Lib "gdiplus" (ByVal Image As Long, ByVal rfType As Long) As Long
Private Declare Function GdipCreateBitmapFromScan0 Lib "gdiplus" (ByVal Width As Long, ByVal Height As Long, ByVal stride As Long, ByVal PixelFormat As Long, scan0 As Any, BITMAP As Long) As Long
Private Declare Function GdipCreateBitmapFromGdiDib Lib "gdiplus" (gdiBitmapInfo As BITMAPINFO, gdiBitmapData As Any, BITMAP As Long) As Long
Private Declare Function lstrlenW Lib "kernel32" (ByVal psString As Any) As Long
Private Declare Function GdipGetImageEncodersSize Lib "gdiplus" (numEncoders As Long, Size As Long) As Long
Private Declare Function GdipGetImageEncoders Lib "gdiplus" (ByVal numEncoders As Long, ByVal Size As Long, Encoders As Any) As Long
Private Declare Function GdipSaveImageToFile Lib "gdiplus" (ByVal hImage As Long, ByVal sFilename As String, clsidEncoder As Any, encoderParams As Any) As Long
Private Declare Function GdipSaveImageToStream Lib "gdiplus" (ByVal Image As Long, ByVal Stream As IUnknown, clsidEncoder As Any, encoderParams As Any) As Long
Private Enum EncoderParameterValueType
[EncoderParameterValueTypeByte] = 1
[EncoderParameterValueTypeASCII] = 2
[EncoderParameterValueTypeShort] = 3
[EncoderParameterValueTypeLong] = 4
[EncoderParameterValueTypeRational] = 5
[EncoderParameterValueTypeLongRange] = 6
[EncoderParameterValueTypeUndefined] = 7
[EncoderParameterValueTypeRationalRange] = 8
End Enum
Private Type EncoderParameter
GUID(0 To 3) As Long
NumberOfValues As Long
Type As EncoderParameterValueType
Value As Long
End Type
'-- Encoder Parameters structure
Private Type EncoderParameters
Count As Long
Parameter As EncoderParameter
End Type
Private Type ImageCodecInfo
ClassID(0 To 3) As Long
FormatID(0 To 3) As Long
CodecName As Long
DllName As Long
FormatDescription As Long
FilenameExtension As Long
MimeType As Long
Flags As Long
Version As Long
SigCount As Long
SigSize As Long
SigPattern As Long
SigMask As Long
End Type
Private Declare Function GdipSetInterpolationMode Lib "gdiplus" (ByVal hGraphics As Long, ByVal Interpolation As Long) As Long
Private Declare Function GdipTranslateWorldTransform Lib "gdiplus" (ByVal graphics As Long, ByVal dX As Single, ByVal dY As Single, ByVal Order As Long) As Long
Private Declare Function GdipRotateWorldTransform Lib "gdiplus" (ByVal graphics As Long, ByVal Angle As Single, ByVal Order As Long) As Long
Private Declare Function GdipCreateImageAttributes Lib "gdiplus" (ByRef imgAttr As Long) As Long
Private Declare Function GdipSetImageAttributesColorMatrix Lib "gdiplus" (ByVal imgAttr As Long, ByVal clrAdjust As Long, ByVal clrAdjustEnabled As Long, ByRef clrMatrix As Any, ByRef grayMatrix As Any, ByVal clrMatrixFlags As Long) As Long
Private Declare Function GdipDisposeImageAttributes Lib "gdiplus" (ByVal imgAttr As Long) As Long
Private Const ColorAdjustTypeBitmap As Long = 1
Private Const PixelFormat32bppARGB As Long = &H26200A
Private Const PixelFormat32bppPARGB As Long = &HE200B
Private Const InterpolationModeNearestNeighbor As Long = &H5&
Private Const InterpolationModeHighQualityBicubic As Long = &H7&
Private Const InterpolationModeHighQualityBilinear As Long = &H6&
' Following are used only if PNG file is being processed by GDI+
Private Type GdiplusStartupInput
GdiplusVersion As Long
DebugEventCallback As Long
SuppressBackgroundThread As Long
SuppressExternalCodecs As Long
End Type
Private Declare Function GdiplusStartup Lib "gdiplus" (Token As Long, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
Private Declare Sub GdiplusShutdown Lib "gdiplus" (ByVal Token As Long)
Private Declare Function GdipLoadImageFromFile Lib "gdiplus" (ByVal FileName As String, hImage As Long) As Long
Private Declare Function GdipLoadImageFromStream Lib "gdiplus" (ByVal Stream As IUnknown, Image As Long) As Long
Private Declare Function GdipGetImageBounds Lib "gdiplus.dll" (ByVal nImage As Long, srcRect As RECTF, srcUnit As Long) As Long
Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal Image As Long) As Long
Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hDC As Long, hGraphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "gdiplus" (ByVal hGraphics As Long) As Long
Private Declare Function GdipDrawImageRectRectI Lib "gdiplus" (ByVal hGraphics As Long, ByVal hImage As Long, ByVal dstX As Long, ByVal dstY As Long, ByVal dstWidth As Long, ByVal dstHeight As Long, ByVal SrcX As Long, ByVal SrcY As Long, ByVal srcWidth As Long, ByVal srcHeight As Long, ByVal srcUnit As Long, Optional ByVal imageAttributes As Long = 0, Optional ByVal Callback As Long = 0, Optional ByVal CallbackData As Long = 0) As Long
Private Declare Function GdipGetImagePixelFormat Lib "gdiplus" (ByVal Image As Long, PixelFormat As Long) As Long
Private Const UnitPixel As Long = &H2&
Private Type RECTF
nLeft As Single
nTop As Single
nWidth As Single
nHeight As Single
End Type
' used for workaround of VB not exposing IStream interface
Private Declare Function CreateStreamOnHGlobal Lib "ole32" (ByVal hGlobal As Long, ByVal fDeleteOnRelease As Long, ppstm As Any) As Long
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal uFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GetHGlobalFromStream Lib "ole32" (ByVal ppstm As Long, hGlobal As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Sub FillMemory Lib "kernel32.dll" Alias "RtlFillMemory" (ByRef Destination As Any, ByVal Length As Long, ByVal Fill As Byte)
Private Type BITMAPINFOHEADER
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Private Type BITMAPINFO
bmiHeader As BITMAPINFOHEADER
bmiColors As Long
End Type
Public Function isGDIplusOk(Optional gdiToken As Long, Optional KeepToken As Boolean = False) As Boolean
' Function starts GDI+ and returns true if no errors occurred
' does the system even have GDI+ on it?
If iparseValidateDLL("gdiplus.dll", "GdiplusStartup") Then
' it does, so attempt to start GDI+
isGDIplusOk = InitializeGDIplus(gdiToken, False)
If Not KeepToken Then InitializeGDIplus gdiToken, True ' shut it down
End If
End Function
Public Function SaveToPNG(FileName As String, outStream() As Byte, cHost As c32bppDIB, Optional GlobalToken As Long) As Boolean
' Function uses GDI+ to create a PNG file or stream
' Parameters:
' FileName. If PNG is to be saved to file, provide the file name, otherwise PNG will be saved to array
' outStream(). If FileName is vbNullString, then PNG is saved to this array, zero-bound
' cHost. The c32bppDIB class containing the image to convert to PNG
Dim gdiToken As Long
If cHost.Handle = 0& Then Exit Function
' does the system have GDI+ on it?
If GlobalToken = 0 Then
If iparseValidateDLL("gdiplus.dll", "GdiplusStartup") = False Then Exit Function
If InitializeGDIplus(gdiToken, False) = False Then Exit Function
Else
gdiToken = GlobalToken
End If
Dim hImg As Long
Dim uEncCLSID(0 To 3) As Long
Dim IIStream As IUnknown
' Note: GdipCreateBitmapFromGdiDib does not handle 32bpp DIBs correctly
Call GdipCreateBitmapFromScan0(cHost.Width, cHost.Height, cHost.scanWidth, PixelFormat32bppPARGB, ByVal cHost.BitsPointer, hImg)
If Not hImg = 0& Then
On Error Resume Next
' retrieve information GDI+ will use for conversion
If Not pvGetEncoderClsID("image/png", uEncCLSID) = 0& Then
' dib is bottom up, scan0 does top down, so flip it
GdipImageRotateFlip hImg, 6& ' flip vertically
If FileName = vbNullString Then
' Saving to stream/array. Create a null stream (IUnknown object)
Erase outStream
Set IIStream = CreateStream(outStream)
' have GDI+ save the 32bpp image to the IUnknown in a PNG format
If GdipSaveImageToStream(hImg, IIStream, uEncCLSID(0&), ByVal 0&) = 0& Then
' now we need to get that array to pass back to client
ArrayFromStream IIStream, outStream()
SaveToPNG = True
End If
Else ' saving to file
' Note: If you are calling this from outside the c32bppDIB class, the file
' must not exist; otherwise, the function fails.
SaveToPNG = (GdipSaveImageToFile(hImg, StrConv(FileName, vbUnicode), uEncCLSID(0&), ByVal 0&) = 0&)
End If
End If
GdipDisposeImage hImg ' clean up
End If
' shut down GDI+
If GlobalToken = 0 Then Call InitializeGDIplus(gdiToken, True)
End Function
Private Function pvPtrToStrW(ByVal lpsz As Long) As String
' supporting routine for SaveToPNG; converts String Pointer to String
Dim sOut As String
Dim lLen As Long
lLen = lstrlenW(lpsz)
If (lLen > 0&) Then
sOut = StrConv(String$(lLen, vbNullChar), vbUnicode)
Call CopyMemory(ByVal sOut, ByVal lpsz, lLen * 2&)
pvPtrToStrW = StrConv(sOut, vbFromUnicode)
End If
End Function
Private Function pvGetEncoderClsID(strMimeType As String, ClassID() As Long) As Long
' supporting routine for SaveToPNG
Dim Num As Long
Dim Size As Long
Dim lIdx As Long
Dim ICI() As ImageCodecInfo
Dim Buffer() As Byte
pvGetEncoderClsID = -1 ' Failure flag
'-- Get the encoder array size
Call GdipGetImageEncodersSize(Num, Size)
If (Size = 0&) Then Exit Function ' Failed!
'-- Allocate room for the arrays dynamically
ReDim ICI(1 To Num) As ImageCodecInfo
ReDim Buffer(1 To Size) As Byte
'-- Get the array and string data
Call GdipGetImageEncoders(Num, Size, Buffer(1))
'-- Copy the class headers
Call CopyMemory(ICI(1), Buffer(1), (Len(ICI(1)) * Num))
'-- Loop through all the codecs
For lIdx = 1& To Num
'-- Must convert the pointer into a usable string
If (StrComp(pvPtrToStrW(ICI(lIdx).MimeType), strMimeType, vbTextCompare) = 0) Then
CopyMemory ClassID(0), ICI(lIdx).ClassID(0), 16& ' Save the Class ID
pvGetEncoderClsID = lIdx ' Return the index number for success
Exit For
End If
Next lIdx
'-- Free the memory
Erase ICI
Erase Buffer
End Function
Friend Function RenderGDIplus(cHost As c32bppDIB, ByVal hDC As Long, _
ByVal Angle As Single, ByVal Alpha As Long, _
ByVal destX As Long, ByVal destY As Long, _
ByVal destWidth As Long, ByVal destHeight As Long, _
ByVal SrcX As Long, ByVal SrcY As Long, _
ByVal srcWidth As Long, ByVal srcHeight As Long, _
ByVal highQuality As Boolean, _
ByVal grayScale As eGrayScaleFormulas, _
ByVal GlobalToken As Long, _
Optional ByVal LightnessAdj As Single = 0!) As Boolean
' Function renders a 32bpp to passed DC.
' GDI+ can literally do most anything with an image; just gotta know how to set it up
' Parameters
' c32bppDIB. Class containing image to render
' hDC. The destination DC to render to
' Angle. A value between -360 and 360 used for rotation. 0 is no rotation
' Alpha. A value between 0 and 100 used for global tranparency. 100 is fully opaque
' destX,Y. The top,left corner of the DC to render the image to
' destWidth,Height. The target size of the rendered image
' srcX,Y. The top,left corner of the image to be rendered
' srcWidth,Height. The size of the source to be rendered
' highQuality. If true, then BiCubic interpolation will be used, else NearestNeighbor will be used
' grayScale. One of the eGrayScaleFormulas
' GlobalToken. When provided it is a valid GDI token
' LigthnessAdj. Percentage (-100 to 100) of more/less lightness for the image
If Alpha = 0& Then
RenderGDIplus = True ' full transparent, nothing to render
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -