📄 cgdiplus.cls
字号:
Exit Function
End If
Dim gdiToken As Long
If GlobalToken = 0 Then
If InitializeGDIplus(gdiToken, False) = False Then Exit Function
Else
gdiToken = GlobalToken
End If
Dim hImg As Long
Dim hGraphics As Long, hImgAttr As Long
Dim clrMatrix(0 To 4, 0 To 4) As Single
Dim mirrorROP As Long, mirrorOffsetX As Long, mirrorOffsetY As Long
' have GDI+ create a DIB from our host pointer, DIB will be mirrored vertically (upside down)
Call GdipCreateBitmapFromScan0(cHost.Width, cHost.Height, cHost.scanWidth, PixelFormat32bppPARGB, ByVal cHost.BitsPointer, hImg)
If Not hImg = 0& Then
If GdipCreateFromHDC(hDC, hGraphics) = 0& Then ' wrap GDI+ around our target DC
If Not hGraphics = 0& Then
' Interpolation quality?
If highQuality = True Then
Call GdipSetInterpolationMode(hGraphics, InterpolationModeHighQualityBicubic)
Else ' Note: There is a 3rd quality which falls between these: InterpolationModeHighQualityBilinear
Call GdipSetInterpolationMode(hGraphics, InterpolationModeNearestNeighbor)
End If
' calculate flags/offsets if we are mirroring and/or rotating
mirrorOffsetX = 1& ' positive angle rotation offset (X)
If destHeight < 0& Then
destHeight = -destHeight ' no flipping needed; bottom up dibs are flipped vertically naturally
mirrorOffsetY = -mirrorOffsetX ' reverse angle rotation offset
Else
mirrorROP = 6& ' flip vertically
mirrorOffsetY = mirrorOffsetX ' positive angle rotation offsets(Y)
End If
If destWidth < 0& Then
mirrorROP = mirrorROP Xor 4& ' flip horizontally (mirror horizontally)
destWidth = -destWidth
mirrorOffsetX = -mirrorOffsetX ' reverse angle rotation offset
End If
GdipImageRotateFlip hImg, mirrorROP ' flip image as needed
If Not ((grayScale = gsclNone) And (LightnessAdj = 0!)) Then
' grayscaling is in play
If GdipCreateImageAttributes(hImgAttr) = 0 Then
If Not grayScale = gsclNone Then
Call iparseGrayScaleRatios(grayScale, clrMatrix(0, 0), clrMatrix(0, 1), clrMatrix(0, 2))
clrMatrix(1, 0) = clrMatrix(0, 0)
clrMatrix(2, 0) = clrMatrix(0, 0)
clrMatrix(1, 1) = clrMatrix(0, 1)
clrMatrix(2, 1) = clrMatrix(0, 1)
clrMatrix(1, 2) = clrMatrix(0, 2)
clrMatrix(2, 2) = clrMatrix(0, 2)
Else
clrMatrix(0, 0) = 1
clrMatrix(1, 1) = 1
clrMatrix(2, 2) = 1
End If
clrMatrix(3, 3) = 1 ' global alpha value
clrMatrix(4, 4) = 1 ' required; cannot be anything else
If Not LightnessAdj = 0! Then
clrMatrix(0, 4) = LightnessAdj / 100 ' red added/subtracted brightness
clrMatrix(1, 4) = clrMatrix(0, 4) ' same for blue
clrMatrix(2, 4) = clrMatrix(0, 4) ' same for green
End If
If Not GdipSetImageAttributesColorMatrix(hImgAttr, ColorAdjustTypeBitmap, -1&, clrMatrix(0, 0), clrMatrix(0, 0), 0&) = 0& Then
GdipDisposeImageAttributes hImgAttr
hImgAttr = 0&
End If
End If
End If
If Angle = 0& And Alpha = 100& Then ' no blending and no rotation being used
RenderGDIplus = (GdipDrawImageRectRectI(hGraphics, hImg, destX, destY, destWidth, destHeight, SrcX, SrcY, srcWidth, srcHeight, UnitPixel, hImgAttr, 0&, 0&) = 0&)
Else ' we are blending and/or rotating
If hImgAttr = 0& Then ' else grayscaling also & hImagAttr already created
If GdipCreateImageAttributes(hImgAttr) = 0& Then ' create image attributes for blending/rotating
clrMatrix(0, 0) = 1
clrMatrix(1, 1) = 1
clrMatrix(2, 2) = 1
clrMatrix(4, 4) = 1 ' required; cannot be anything else
End If
If Not LightnessAdj = 0! Then
clrMatrix(0, 4) = LightnessAdj / 100! ' red added/subtracted brightness
clrMatrix(1, 4) = clrMatrix(0, 4) ' same for blue
clrMatrix(2, 4) = clrMatrix(0, 4) ' same for green
End If
End If
' Global Blending?
clrMatrix(3, 3) = CSng(Alpha / 100&) ' value between 0 & 1
If GdipSetImageAttributesColorMatrix(hImgAttr, ColorAdjustTypeBitmap, -1&, clrMatrix(0, 0), clrMatrix(0, 0), 0&) = 0& Then
If Angle = 0& Then ' not rotating
RenderGDIplus = (GdipDrawImageRectRectI(hGraphics, hImg, destX, destY, destWidth, destHeight, SrcX, SrcY, srcWidth, srcHeight, UnitPixel, hImgAttr, 0&, 0&) = 0&)
Else ' rotating & maybe blending too... different coordinates system used when rotating
If GdipRotateWorldTransform(hGraphics, Angle + 180, 0&) = 0& Then
GdipTranslateWorldTransform hGraphics, destX + (destWidth \ 2) * mirrorOffsetX, destY + (destHeight \ 2) * mirrorOffsetY, 1&
End If
RenderGDIplus = (GdipDrawImageRectRectI(hGraphics, hImg, destWidth \ 2, destHeight \ 2, -destWidth, -destHeight, SrcX, SrcY, srcWidth, srcHeight, UnitPixel, hImgAttr, 0&, 0&) = 0&)
End If
End If
End If
If Not hImgAttr = 0& Then GdipDisposeImageAttributes hImgAttr ' clean up
GdipDeleteGraphics hGraphics ' clean up
End If
End If
GdipDisposeImage hImg ' clean up
End If
If GlobalToken = 0 Then Call InitializeGDIplus(gdiToken, True) ' terminate GDI+
End Function
Friend Function GDIplusLoadPNG(FileName As String, pngStream() As Byte, cHost As c32bppDIB, Optional ByVal GlobalToken As Long) As Boolean
'Exit Function ' un-rem to test/force PNG loading without GDI+
' Purpose: Use GDI+ to load a PNG either by fileName or by array/stream
' FileName :: if vbNullString, then the pngStream() array will contain
' the PNG else FileName is full path & name of the PNG file
' Note: FileName and/or pngStream() have been validated before this routine is called
Dim gdiToken As Long
' 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 hImage As Long, hGraphics As Long
Dim tDC As Long, lRtn As Long
Dim rDimensions As RECTF, pStream As IUnknown
On Error GoTo ExitRoutine
If FileName = vbNullString Then ' we need an array vs file name
' hack of my own. Create an IUnknown Stream that has the same properties
' and minimum methods needed as the IStream interface which VB does not
' expose. Once the stream is created, we have GDI+ load from it
Set pStream = CreateStream(pngStream())
If Not pStream Is Nothing Then Call GdipLoadImageFromStream(pStream, hImage)
Else ' we use the passed file name; have GDI+ load the file
Call GdipLoadImageFromFile(StrConv(FileName, vbUnicode), hImage)
End If
If Not hImage = 0& Then
' get size of PNG
lRtn = GdipGetImageBounds(hImage, rDimensions, UnitPixel)
If lRtn = 0& Then
' build 32bpp
cHost.InitializeDIB CLng(rDimensions.nWidth), CLng(rDimensions.nHeight)
' wrap a GDI+ DC around our DIB's DC
tDC = cHost.LoadDIBinDC(True)
lRtn = GdipCreateFromHDC(tDC, hGraphics)
If lRtn = 0& Then
' now draw the PNG into our 32bpp. GDI+ is nice enough to pre-multiply
' the RGB values for us during the rendering
With rDimensions
GdipDrawImageRectRectI hGraphics, hImage, 0&, 0&, .nWidth, .nHeight, .nLeft, .nTop, .nWidth, .nHeight, UnitPixel, 0&, 0&, 0&
End With
GdipDeleteGraphics hGraphics ' remove the GDI+ DC wrapper
hGraphics = 0&
End If
cHost.LoadDIBinDC False ' unselect our DIB
End If
If lRtn = 0& Then ' return results
GDIplusLoadPNG = True
Call GdipGetImagePixelFormat(hImage, lRtn)
GdipDisposeImage hImage ' destroy the GDI+ image
cHost.Alpha = (lRtn = PixelFormat32bppARGB Or lRtn = PixelFormat32bppPARGB)
cHost.ImageType = imgPNG
Else
GdipDisposeImage hImage ' destroy the GDI+ image
cHost.DestroyDIB
End If
hImage = 0&
End If
ExitRoutine:
If Not gdiToken = 0& Then
If Not hGraphics = 0& Then GdipDeleteGraphics hGraphics
If Not hImage = 0& Then GdipDisposeImage hImage
If GlobalToken = 0 Then Call InitializeGDIplus(gdiToken, True) ' stop GDI+
End If
End Function
Private Function ArrayFromStream(Stream As IUnknown, arrayBytes() As Byte) As Boolean
' Purpose: Return the array contained in an IUnknown interface
Dim o_hMem As Long, o_lpMem As Long
Dim o_lngByteCount As Long
If Not Stream Is Nothing Then
If GetHGlobalFromStream(ByVal ObjPtr(Stream), o_hMem) = 0 Then
o_lngByteCount = GlobalSize(o_hMem)
If o_lngByteCount > 0 Then
o_lpMem = GlobalLock(o_hMem)
If o_lpMem <> 0 Then
ReDim arrayBytes(0 To o_lngByteCount - 1)
CopyMemory arrayBytes(0), ByVal o_lpMem, o_lngByteCount
GlobalUnlock o_hMem
ArrayFromStream = True
End If
End If
End If
End If
End Function
Private Function CreateStream(byteContent() As Byte, Optional byteOffset As Long = 0&) As stdole.IUnknown
' Purpose: Create an IStream-compatible IUnknown interface containing the
' passed byte aray. This IUnknown interface can be passed to GDI+ functions
' that expect an IStream interface -- neat hack
On Error GoTo HandleError
Dim o_lngLowerBound As Long
Dim o_lngByteCount As Long
Dim o_hMem As Long
Dim o_lpMem As Long
If iparseIsArrayEmpty(VarPtrArray(byteContent)) = 0& Then ' create a growing stream as needed
Call CreateStreamOnHGlobal(0, 1, CreateStream)
Else ' create a fixed stream
o_lngByteCount = UBound(byteContent) - byteOffset + 1
o_hMem = GlobalAlloc(&H2&, o_lngByteCount)
If o_hMem <> 0 Then
o_lpMem = GlobalLock(o_hMem)
If o_lpMem <> 0 Then
CopyMemory ByVal o_lpMem, byteContent(byteOffset), o_lngByteCount
Call GlobalUnlock(o_hMem)
Call CreateStreamOnHGlobal(o_hMem, 1, CreateStream)
End If
End If
End If
HandleError:
End Function
Friend Function InitializeGDIplus(gToken As Long, ShutDown As Boolean) As Boolean
' function starts/stops GDI+
On Error Resume Next
If ShutDown Then
If Not gToken = 0& Then GdiplusShutdown gToken
Else
Dim gdiSI As GdiplusStartupInput
gdiSI.GdiplusVersion = 1
If GdiplusStartup(gToken, gdiSI) = 0& Then
InitializeGDIplus = True
Else
gToken = 0&
End If
End If
If Err Then Err.Clear
End Function
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -