VB 5/6-Tipp 0687: Grafik mittels GDI+ als PNG speichern
von Frank Schüler
Beschreibung
Dieser Tipp zeigt, wie man unter Verwendung von GDI+ Grafiken als PNG abspeichern kann.
Schwierigkeitsgrad: | Verwendete API-Aufrufe: GdipCreateBitmapFromFile, GdipCreateBitmapFromHBITMAP, GdipCreateHBITMAPFromBitmap, GdipDisposeImage, GdipGetImageEncoders, GdipGetImageEncodersSize, GdipSaveImageToFile, GdiplusShutdown, GdiplusStartup, OleCreatePictureIndirect, lstrcpyW, lstrlenW | Download: |
'Dieser Quellcode stammt von http://www.activevb.de 'und kann frei verwendet werden. Für eventuelle Schäden 'wird nicht gehaftet. 'Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum. 'Ansonsten viel Spaß und Erfolg mit diesem Source! '---------- Anfang Projektdatei GDIPlusSavePNG.vbp ---------- ' Die Komponente 'Microsoft Common Dialog Control 6.0 (SP3) (comdlg32.ocx)' wird benötigt. '--- Anfang Formular "frmGDIPlusSavePNG" alias frmGDIPlusSavePNG.frm --- ' Steuerelement: Schaltfläche "cmdSaveAsPng" ' Steuerelement: Bildfeld-Steuerelement "Picture1" ' Steuerelement: Standarddialog-Steuerelement "CommonDialog1" ' Steuerelement: Schaltfläche "cmdLoadPicture" Option Explicit ' ----==== GDI+ Konstanten ====---- Private Const GdiPlusVersion As Long = 1 Private Const mimePNG As String = "image/png" ' ----==== Sonstige Typen ====---- Private Type GUID Data1 As Long Data2 As Integer Data3 As Integer Data4(0 To 7) As Byte End Type Private Type IID Data1 As Long Data2 As Integer Data3 As Integer Data4(0 To 7) As Byte End Type Private Type PICTDESC cbSizeOfStruct As Long picType As Long hgdiObj As Long hPalOrXYExt As Long End Type ' ----==== GDI+ Typen ====---- Private Type ImageCodecInfo Clsid As GUID FormatID As GUID CodecNamePtr As Long DllNamePtr As Long FormatDescriptionPtr As Long FilenameExtensionPtr As Long MimeTypePtr As Long Flags As Long Version As Long SigCount As Long SigSize As Long SigPatternPtr As Long SigMaskPtr As Long End Type Private Type GdiplusStartupOutput NotificationHook As Long NotificationUnhook As Long End Type Private Type GDIPlusStartupInput GdiPlusVersion As Long DebugEventCallback As Long SuppressBackgroundThread As Long SuppressExternalCodecs As Long End Type ' ----==== GDI+ Enumerationen ====---- ' GDI+ Status Private Enum Status OK = 0 GenericError = 1 InvalidParameter = 2 OutOfMemory = 3 ObjectBusy = 4 InsufficientBuffer = 5 NotImplemented = 6 Win32Error = 7 WrongState = 8 Aborted = 9 FileNotFound = 10 ValueOverflow = 11 AccessDenied = 12 UnknownImageFormat = 13 FontFamilyNotFound = 14 FontStyleNotFound = 15 NotTrueTypeFont = 16 UnsupportedGdiplusVersion = 17 GdiplusNotInitialized = 18 PropertyNotFound = 19 PropertyNotSupported = 20 ProfileNotFound = 21 End Enum ' ----==== GDI+ API Deklarationen ====---- Private Declare Function GdipCreateBitmapFromFile Lib "gdiplus" _ (ByVal FileName As Long, ByRef Bitmap As Long) As Status Private Declare Function GdipCreateBitmapFromHBITMAP Lib "gdiplus" _ (ByVal hbm As Long, ByVal hpal As Long, _ ByRef Bitmap As Long) As Status Private Declare Function GdipCreateHBITMAPFromBitmap Lib "gdiplus" _ (ByVal Bitmap As Long, ByRef hbmReturn As Long, _ ByVal background As Long) As Status Private Declare Function GdipDisposeImage Lib "gdiplus" _ (ByVal image As Long) As Status Private Declare Function GdipGetImageEncoders Lib "gdiplus" _ (ByVal numEncoders As Long, ByVal Size As Long, _ ByRef Encoders As Any) As Status Private Declare Function GdipGetImageEncodersSize Lib "gdiplus" _ (ByRef numEncoders As Long, ByRef Size As Long) As Status Private Declare Function GdiplusShutdown Lib "gdiplus" _ (ByVal token As Long) As Status Private Declare Function GdiplusStartup Lib "gdiplus" _ (ByRef token As Long, ByRef lpInput As GDIPlusStartupInput, _ Optional ByRef lpOutput As Any) As Status Private Declare Function GdipSaveImageToFile Lib "gdiplus" _ (ByVal image As Long, ByVal FileName As Long, _ ByRef clsidEncoder As GUID, _ ByRef encoderParams As Any) As Status ' ----==== OLE API Deklarationen ====---- Private Declare Sub OleCreatePictureIndirect Lib "oleaut32.dll" _ (lpPictDesc As PICTDESC, riid As IID, _ ByVal fOwn As Boolean, lplpvObj As Object) ' ----==== Kernel API Deklarationen ====---- Private Declare Function lstrcpyW Lib "kernel32" _ (lpString1 As Any, lpString2 As Any) As Long Private Declare Function lstrlenW Lib "kernel32" _ (lpString As Any) As Long ' ----==== Variablen ====---- Dim GdipToken As Long Dim GdipInitialized As Boolean '------------------------------------------------------ ' Funktion : Execute ' Beschreibung : Gibt im Fehlerfall die entsprechende ' GDI+ Fehlermeldung aus ' Übergabewert : GDI+ Status ' Rückgabewert : GDI+ Status '------------------------------------------------------ Private Function Execute(ByVal lReturn As Status) As Status Dim lCurErr As Status If lReturn = Status.OK Then lCurErr = Status.OK Else lCurErr = lReturn MsgBox GdiErrorString(lReturn) & " GDI+ Error:" _ & lReturn, vbOKOnly, "GDI Error" End If Execute = lCurErr End Function '------------------------------------------------------ ' Funktion : GdiErrorString ' Beschreibung : Umwandlung der GDI+ Statuscodes in Stringcodes ' Übergabewert : GDI+ Status ' Rückgabewert : Fehlercode als String '------------------------------------------------------ Private Function GdiErrorString(ByVal lError As Status) As String Dim s As String Select Case lError Case GenericError: s = "Generic Error." Case InvalidParameter: s = "Invalid Parameter." Case OutOfMemory: s = "Out Of Memory." Case ObjectBusy: s = "Object Busy." Case InsufficientBuffer: s = "Insufficient Buffer." Case NotImplemented: s = "Not Implemented." Case Win32Error: s = "Win32 Error." Case WrongState: s = "Wrong State." Case Aborted: s = "Aborted." Case FileNotFound: s = "File Not Found." Case ValueOverflow: s = "Value Overflow." Case AccessDenied: s = "Access Denied." Case UnknownImageFormat: s = "Unknown Image Format." Case FontFamilyNotFound: s = "FontFamily Not Found." Case FontStyleNotFound: s = "FontStyle Not Found." Case NotTrueTypeFont: s = "Not TrueType Font." Case UnsupportedGdiplusVersion: s = "Unsupported Gdiplus Version." Case GdiplusNotInitialized: s = "Gdiplus Not Initialized." Case PropertyNotFound: s = "Property Not Found." Case PropertyNotSupported: s = "Property Not Supported." Case Else: s = "Unknown GDI+ Error." End Select GdiErrorString = s End Function '------------------------------------------------------ ' Funktion : GetEncoderClsid ' Beschreibung : Ermittelt die Clsid des Encoders ' Übergabewert : mimeType = mimeType des Encoders ' pClsid = CLSID des Encoders (in/out) ' Rückgabewert : True = Ermitteln erfolgreich ' False = Ermitteln fehlgeschlagen '------------------------------------------------------ Private Function GetEncoderClsid(mimeType As String, _ pClsid As GUID) As Boolean Dim num As Long Dim Size As Long Dim pImageCodecInfo() As ImageCodecInfo Dim j As Long Dim buffer As String Call GdipGetImageEncodersSize(num, Size) If (Size = 0) Then ' fehlgeschlagen GetEncoderClsid = False Exit Function End If ReDim pImageCodecInfo(0 To Size \ Len(pImageCodecInfo(0)) - 1) Call GdipGetImageEncoders(num, Size, pImageCodecInfo(0)) For j = 0 To num - 1 buffer = _ Space$(lstrlenW(ByVal pImageCodecInfo(j).MimeTypePtr)) Call lstrcpyW(ByVal StrPtr(buffer), _ ByVal pImageCodecInfo(j).MimeTypePtr) If (StrComp(buffer, mimeType, vbTextCompare) = 0) Then pClsid = pImageCodecInfo(j).Clsid Erase pImageCodecInfo ' erfolgreich GetEncoderClsid = True Exit Function End If Next j Erase pImageCodecInfo ' fehlgeschlagen GetEncoderClsid = False End Function '------------------------------------------------------ ' Funktion : HandleToPicture ' Beschreibung : Umwandeln eines Bitmap Handle ' in ein StdPicture Objekt ' Übergabewert : hGDIHandle = Bitmap Handle ' ObjectType = Bitmaptyp ' Rückgabewert : StdPicture Objekt '------------------------------------------------------ Private Function HandleToPicture(ByVal hGDIHandle As Long, _ ByVal ObjectType As PictureTypeConstants, _ Optional ByVal hpal As Long = 0) As StdPicture Dim tPictDesc As PICTDESC Dim IID_IPicture As IID Dim oPicture As IPicture ' Initialisiert die PICTDESC Structur With tPictDesc .cbSizeOfStruct = Len(tPictDesc) .picType = ObjectType .hgdiObj = hGDIHandle .hPalOrXYExt = hpal End With ' Initialisiert das IPicture Interface ID With IID_IPicture .Data1 = &H7BF80981 .Data2 = &HBF32 .Data3 = &H101A .Data4(0) = &H8B .Data4(1) = &HBB .Data4(3) = &HAA .Data4(5) = &H30 .Data4(6) = &HC .Data4(7) = &HAB End With ' Erzeugen des Objekts OleCreatePictureIndirect tPictDesc, IID_IPicture, _ True, oPicture ' Rückgabe des Pictureobjekts Set HandleToPicture = oPicture End Function '------------------------------------------------------ ' Funktion : LoadPicturePlus ' Beschreibung : Lädt ein Bilddatei per GDI+ ' Übergabewert : Pfad\Dateiname der Bilddatei ' Rückgabewert : StdPicture Objekt '------------------------------------------------------ Public Function LoadPicturePlus( _ ByVal sFileName As String) As StdPicture Dim lBitmap As Long Dim hBitmap As Long ' Öffnet die Bilddatei in lBitmap If Execute(GdipCreateBitmapFromFile(StrPtr(sFileName), _ lBitmap)) = OK Then ' Handle der Bitmap ermitteln lBitmap -> hBitmap If Execute(GdipCreateHBITMAPFromBitmap(lBitmap, _ hBitmap, 0)) = OK Then ' Erzeugen des StdPicture Objekts von hBitmap Set LoadPicturePlus = HandleToPicture(hBitmap, _ vbPicTypeBitmap) End If ' Lösche lBitmap Call Execute(GdipDisposeImage(lBitmap)) End If End Function '------------------------------------------------------ ' Funktion : SavePictureAsPNG ' Beschreibung : Speichert ein StdPicture Objekt ' per GDI+ als PNG ' Übergabewert : Pic = StdPicture Objekt ' FileName = Pfad\Dateiname.png ' Rückgabewert : True = speichern erfolgreich ' False = speichern fehlgeschlagen '------------------------------------------------------ Private Function SavePictureAsPNG(ByVal Pic As StdPicture, _ ByVal sFileName As String) As Boolean Dim lBitmap As Long Dim tPicEncoder As GUID ' Erzeugt eine GDI+ Bitmap vom ' StdPicture Handle -> lBitmap If Execute(GdipCreateBitmapFromHBITMAP( _ Pic.Handle, 0, lBitmap)) = OK Then ' Ermitteln der CLSID vom mimeType Encoder If GetEncoderClsid(mimePNG, tPicEncoder) = True Then ' Speichert lBitmap als PNG If Execute(GdipSaveImageToFile(lBitmap, _ StrPtr(sFileName), tPicEncoder, ByVal 0)) = OK Then ' speichern erfolgreich SavePictureAsPNG = True Else ' speichern nicht erfolgreich SavePictureAsPNG = False End If Else ' speichern nicht erfolgreich SavePictureAsPNG = False MsgBox "Konnte keinen passenden Encoder ermitteln.", _ vbOKOnly, "Encoder Error" End If ' Lösche lBitmap Call Execute(GdipDisposeImage(lBitmap)) End If End Function '------------------------------------------------------ ' Funktion : StartUpGDIPlus ' Beschreibung : Initialisiert GDI+ Instanz ' Übergabewert : GDI+ Version ' Rückgabewert : GDI+ Status '------------------------------------------------------ Private Function StartUpGDIPlus(ByVal GdipVersion As Long) As Status ' Initialisieren der GDI+ Instanz Dim tGdipStartupInput As GDIPlusStartupInput Dim tGdipStartupOutput As GdiplusStartupOutput tGdipStartupInput.GdiPlusVersion = GdipVersion StartUpGDIPlus = GdiplusStartup(GdipToken, _ tGdipStartupInput, tGdipStartupOutput) End Function '------------------------------------------------------ ' Funktion : ShutDownGDIPlus ' Beschreibung : Beendet die GDI+ Instanz ' Rückgabewert : GDI+ Status '------------------------------------------------------ Private Function ShutDownGDIPlus() As Status ' Beendet GDI+ Instanz ShutDownGDIPlus = GdiplusShutdown(GdipToken) End Function '------------------------------------------------------ ' Beschreibung : Bilddatei laden '------------------------------------------------------ Private Sub cmdLoadPicture_Click() ' Fehlerbehandlung On Error Goto errorhandler ' ist GDI+ Initialisiert If GdipInitialized = True Then ' Dialogparameter setzen With CommonDialog1 .Filter = "Images Files (*.bmp;*.gif;*.jpg;*.png;*.tif)" _ & "|*.bmp;*.gif;*.jpg;*.png;*.tif" .CancelError = True .ShowOpen End With ' Bild per GDI+ laden und anzeigen Picture1.Picture = _ LoadPicturePlus(CommonDialog1.FileName) ' Button aktivieren, wenn ein Bild geladen ist If Not Picture1.Picture Is Nothing _ Then cmdSaveAsPng.Enabled = True End If Exit Sub errorhandler: End Sub '------------------------------------------------------ ' Beschreibung : Bilddatei speichern '------------------------------------------------------ Private Sub cmdSaveAsPng_Click() ' Fehlerbehandlung On Error Goto errorhandler ' ist GDI+ Initialisiert If GdipInitialized = True Then ' Dialogparameter setzen With CommonDialog1 .Filter = "Images Files (*.png)|*.png" .FileName = "*.png" .CancelError = True .Flags = cdlOFNOverwritePrompt .ShowSave End With ' Bild als PNG-Datei speichern If SavePictureAsPNG(Picture1, _ CommonDialog1.FileName) = False Then ' im Fehlerfall, Meldung ausgeben MsgBox "Speichern ist fehlgeschlagen.", _ vbOKOnly, "Error" End If End If Exit Sub errorhandler: End Sub '------------------------------------------------------ ' Beschreibung : Form laden '------------------------------------------------------ Private Sub Form_Load() GdipInitialized = False ' GDI+ initialisieren If Execute(StartUpGDIPlus(GdiPlusVersion)) = OK Then GdipInitialized = True Else MsgBox "GDI+ not inizialized.", vbOKOnly, "GDI Error" End If ' Button deaktivieren cmdSaveAsPng.Enabled = False End Sub '------------------------------------------------------ ' Beschreibung : Form entladen '------------------------------------------------------ Private Sub Form_Unload(Cancel As Integer) ' ist GDI+ Initialisiert If GdipInitialized = True Then ' GDI+ beenden Call Execute(ShutDownGDIPlus) End If End Sub '--- Ende Formular "frmGDIPlusSavePNG" alias frmGDIPlusSavePNG.frm --- '----------- Ende Projektdatei GDIPlusSavePNG.vbp -----------
Tipp-Kompatibilität:
Windows/VB-Version | Win32s | Win95 | Win98 | WinME | WinNT4 | Win2000 | WinXP |
VB4 | |||||||
VB5 | |||||||
VB6 |
Ihre Meinung
Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.