
[Windows] 2DDrawing Befehle mit AntiAliasing durch GDI+
-
- Beiträge: 6291
- Registriert: 29.08.2004 08:37
- Computerausstattung: Hoffentlich bald keine mehr
- Kontaktdaten:
Re: [Windows] 2DDrawing Befehle mit AntiAliasing durch GDI+
Cool, vielen Dank
.

Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
- Falko
- Admin
- Beiträge: 3535
- Registriert: 29.08.2004 11:27
- Computerausstattung: PC: MSI-Z590-GC; 32GB-DDR4, ICore9; 2TB M2 + 2x3TB-SATA2 HDD; Intel ICore9 @ 3600MHZ (Win11 Pro. 64-Bit),
Acer Aspire E15 (Win11 Home X64). Purebasic LTS 6.11b1
HP255G8 Notebook @AMD Ryzen 5 5500U with Radeon Graphics 2.10 GHz 3.4GHz, 32GB_RAM, 3TB_SSD (Win11 Pro 64-Bit) - Kontaktdaten:
Re: [Windows] 2DDrawing Befehle mit AntiAliasing durch GDI+
dito no.2DarkDragon hat geschrieben:Cool, vielen Dank.

:::: WIN 10 :: PB 5.73 :: (x64) ::::
Re: [Windows] 2DDrawing Befehle mit AntiAliasing durch GDI+
@Danilo: Vielen Dank für Deine wertvolle Arbeit! Das sind ja wahnsinns Möglichkeiten. Ich habe GDI bisher
völlig unterschätzt...
völlig unterschätzt...
"Papa, ich laufe schneller - dann ist es nicht so weit."
Re: [Windows] 2DDrawing Befehle mit AntiAliasing durch GDI+
Ich muss leider noch mal nachhken.
Bei mir funktioneirt gDrawText() irgendwie garnicht, oder nur sehr schlecht:
Bei mir werden Texte mit einer Schriftgröße zwischen 9 und 17 garnicht bzw. in einer falschen farbe dagestellt:
10 ist sogar breiter als 11

Hier mein Code:
Hat noch jemand diesen Fehler?
Habe die unveränderte Include genutzt.
Kannst du Danilo oder jemand anderes mir sagen, wie ich das beheben kann?
Bei mir funktioneirt gDrawText() irgendwie garnicht, oder nur sehr schlecht:
Bei mir werden Texte mit einer Schriftgröße zwischen 9 und 17 garnicht bzw. in einer falschen farbe dagestellt:
10 ist sogar breiter als 11


Hier mein Code:
Code: Alles auswählen
Enumeration
#Window : #Gadget : #Image
EndEnumeration
XIncludeFile "gDrawing.pbi"
gInit()
CreateImage(#Image, 256, 512, 32|#PB_Image_Transparent)
StartDrawing(ImageOutput(#Image))
DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Transparent)
For Size = 1 To 24
DrawText(10, Size*Size*0.8, Str(Size), $FF000000)
Next
Box(50, 0, 100, 512, $FFF0A050)
StopDrawing()
gStartDrawing(ImageOutput(#Image))
For Size = 1 To 24
gSetFont("Arial", Size)
gDrawText(60, Size*Size*0.8, "Hallo", $FF000000)
Next
gStopDrawing()
OpenWindow(#Window, 0, 0, ImageWidth(#Image), ImageHeight(#Image), "Image", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
ImageGadget(#Gadget, 0, 0, ImageWidth(#Image), ImageHeight(#Image), ImageID(#Image))
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Habe die unveränderte Include genutzt.
Kannst du Danilo oder jemand anderes mir sagen, wie ich das beheben kann?
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Re: [Windows] 2DDrawing Befehle mit AntiAliasing durch GDI+
Hier gleiches Ergebnis:STARGÅTE hat geschrieben:Hat noch jemand diesen Fehler?

:::: WIN 10 :: PB 5.73 :: (x64) ::::
Re: [Windows] 2DDrawing Befehle mit AntiAliasing durch GDI+
Noch ein kleiner Trick mit gScale() / gScaleAt():
Wenn man für die Skalierungswerte -1 verwendet, kann man die
Zeichenbefehle spiegeln.
Am besten mal ausprobieren.
Und hier eine Procedure MirrorImage():
Wenn man für die Skalierungswerte -1 verwendet, kann man die
Zeichenbefehle spiegeln.
Am besten mal ausprobieren.
Code: Alles auswählen
XIncludeFile "gDrawing.pbi"
Procedure ScaleDemo(scaleX.f, scaleY.f)
img = CreateImage(#PB_Any,400,300,24)
If gStartDrawing( ImageOutput(img) )
gClear( RGBA($AA,$AA,$AA,$FF) )
gScaleAt(200,150,scaleX,scaleY)
gStartTransform()
gDrawingMode( #PB_2DDrawing_Outlined )
;
; gEllipse rotieren
;
For i = 0 To 90 Step 10
gRotateAt(50,50,i) : gEllipse(50,50,50,15) : gResetTransform()
Next i
gStopTransform()
gStopDrawing()
EndIf
ProcedureReturn img
EndProcedure
If gInit()
mainWin = OpenWindow(#PB_Any,0,0,800,600,"gDrawing scale demo",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ImageGadget(#PB_Any, 0, 0,400,300,ImageID( ScaleDemo( 1, 1) )) ; normal
ImageGadget(#PB_Any,400, 0,400,300,ImageID( ScaleDemo(-1, 1) )) ; gespiegelt um Y-Achse
ImageGadget(#PB_Any, 0,300,400,300,ImageID( ScaleDemo( 1,-1) )) ; gespiegelt um X-Achse
ImageGadget(#PB_Any,400,300,400,300,ImageID( ScaleDemo(-1,-1) )) ; gespiegelt um X- und Y-Achse
Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
gEnd()
EndIf
Code: Alles auswählen
EnableExplicit
XIncludeFile "gDrawing.pbi"
Procedure MirrorImage(original,x,y)
Protected copy, w, h
copy = CreateImage(#PB_Any,ImageWidth(original),ImageHeight(original),24)
;copy = CopyImage(original,#PB_Any)
If copy
w = ImageWidth(original)
h = ImageHeight(original)
If gStartDrawing( ImageOutput(copy) )
gSetPenImage( ImageID(original) ,#WrapModeTileFlipXY)
If x : gSetPenOrigin(0,h) : EndIf
If y : gSetPenOrigin(w,0) : EndIf
gBox(0,0,w,h)
gStopDrawing()
EndIf
EndIf
ProcedureReturn copy
EndProcedure
Procedure DrawShearedImage(img,x.f,y.f,ShearX.f,ShearY.f)
gStartTransform()
gShearAt(x,y,ShearX,ShearY)
gSetPenImage( ImageID(img) )
gSetPenOrigin(x,y)
gBox(x,y,ImageWidth(img),ImageHeight(img))
gStopTransform()
EndProcedure
Define pbLogo, pbLogoMirror, img
pbLogo = LoadImage(#PB_Any,#PB_Compiler_Home+"Examples\Sources\Data\PureBasicLogo.bmp")
If Not pbLogo : MessageRequester("ERROR","Unable to load PureBasic logo!") : End : EndIf
If gInit()
pbLogoMirror = MirrorImage(pbLogo,1,0)
img = CreateImage(#PB_Any,800,600)
If gStartDrawing( ImageOutput(img) )
DrawImage(ImageID(pblogo),100,100)
DrawShearedImage(pbLogoMirror,100,100+ImageHeight(pbLogo),0.8,0)
gStopDrawing()
EndIf
OpenWindow(#PB_Any,0,0,800,600,"gDrawing gShear",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ImageGadget(#PB_Any,0,0,800,600,ImageID( img ),#PB_Image_Border ) ; normal
Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
gEnd()
EndIf
Schaue ich morgen früh. Jetzt muß ich gleich auf Arbeit.STARGÅTE hat geschrieben:Bei mir funktioneirt gDrawText() irgendwie garnicht, oder nur sehr schlecht:
[...]
Kannst du Danilo oder jemand anderes mir sagen, wie ich das beheben kann?
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
- PureLust
- Beiträge: 1145
- Registriert: 21.07.2005 00:02
- Computerausstattung: Hab aktuell im Grunde nur noch 'nen Lenovo Yoga 2 Pro im Einsatz.
- Wohnort: am schönen Niederrhein
Re: [Windows] 2DDrawing Befehle mit AntiAliasing durch GDI+
Das Problem liegt an dem (in gStartDrawing() vordefinierten) Wert des TextAntialiasingModes.STARGÅTE hat geschrieben:Kannst du Danilo oder jemand anderes mir sagen, wie ich das beheben kann?
Die FarbProbleme treten seltsamerweise bei #TextAntialiasMode_AntiAliasGridFit sowie #TextAntialiasMode_SingleBitPerPixelGridFit auf.
Du könntest also zuvor gSetTextAntialiasMode(#TextAntialiasMode_AntiAlias) ausführen.
Vermutlich wäre aber ein anderer Defaultwert in gStartDrawing() die bessere Lösung.
@Danilo:
In gSetFont() ist noch ein (kleiner) Fehler, da die Fontgröße beim Erstellen/Laden des Fonts zuerst noch entsprechend der DPI-Auflösung des Ausgabedevices angepasst werden muss.
Ohne Anpassung werden die Schriftarten für eine Auflösung von 72 DPI erstellt (was der üblichen DPI-Auflösung früherer Röhrenmonitore entspricht).
Bei heutigen TFT-Bildschirmen liegt die Auflösung jedoch bei rund 96 DPI - wodurch die Schriften dann ohne Anpassung der Größe zu klein sind.
Nachfolgend die nötige Umrechnung für eine Ausgabe auf dem Bildschirm:
Code: Alles auswählen
Protected *hdc = GetDC_(#Null);
AlignedFontSize = (FontSize * GetDeviceCaps_(*hdc, #LOGPIXELSY) / 72)
ReleaseDC_(#Null, *hdc)
Da ich nirgends gefunden habe, dass Du den *hDC zwischenspeicherst, den Du bei StartDrawing() erhaltenen hast, poste ich anbei mal ein paar Änderungen durch die sowohl die FarbProbleme bei der Fontausgabe behoben werden, als auch der DC zwischengespeichert wird um die Fontgröße korrekt auf den DC anpassen zu können:
Code: Alles auswählen
; --- einfügen in Zeile 331
Global __currentDC.i ; <--- neue Variable, um DC zwischen zu speichern
Code: Alles auswählen
Procedure gStartDrawing( out )
Protected hDC
hDC = StartDrawing(out)
If Not hDC : ProcedureReturn 0 : EndIf
GdipCreateFromHDC_(hDC ,@__graphics)
If Not __graphics
StopDrawing()
ProcedureReturn 0
EndIf
__drawingMode = #PB_2DDrawing_Default
__lineCapStart = #LineCapFlat
__lineCapEnd = #LineCapFlat
__currentTextAntialiasingMode = #TextAntialiasMode_AntiAlias
gSetPen(RGBA($FF,$FF,$FF,$FF),1.0)
gSetFont("Arial",12,#PB_Font_Default)
GdipCreateMatrix_(@__transformMatrix)
GdipSetSmoothingMode_ (__graphics,#SmoothingModeAntiAlias)
GdipSetCompositingMode_ (__graphics,#CompositingModeSourceOver)
GdipSetCompositingQuality_(__graphics,#CompositingQualityGammaCorrected)
GdipSetInterpolationMode_ (__graphics,#InterpolationModeHighQualityBicubic)
GdipSetPixelOffsetMode_ (__graphics,#PixelOffsetModeNone)
__currentDC = hDC ; <--- buffering DC
ProcedureReturn hDC
EndProcedure
Procedure gStopDrawing()
If __graphics : GdipDeleteGraphics_( __graphics ) : __graphics = 0 : EndIf
If __currentPen : GdipDeletePen_ ( __currentPen ) : __currentPen = 0 : EndIf
If __currentBrush : GdipDeleteBrush_ ( __currentBrush ) : __currentBrush = 0 : EndIf
If __currentFont : GdipDeleteFont_ ( __currentFont ) : __currentFont = 0 : EndIf
If __transformMatrix : GdipDeleteMatrix_ (__transformMatrix) : __transformMatrix = 0 : EndIf
StopDrawing()
__currentDC = #False ; <--- Clearing buffered DC
EndProcedure
Procedure gSetFont( FontName$="Arial", FontSize.f=12, FontStyle.l = 0)
Protected fs, *fontFamily, *font, *fontName
If FontStyle = #PB_Font_Default : FontStyle = 0: EndIf
If FontStyle & #PB_Font_Bold : fs | 1 : EndIf
If FontStyle & #PB_Font_Italic : fs | 2 : EndIf
If FontStyle & #PB_Font_Underline : fs | 4 : EndIf
If FontStyle & #PB_Font_StrikeOut : fs | 8 : EndIf
If Not __currentDC
Protected *hdc = GetDC_(#Null);
AlignedFontSize = (FontSize * GetDeviceCaps_(*hdc, #LOGPIXELSY) / 72)
ReleaseDC_(#Null, *hdc)
Else
AlignedFontSize = (FontSize * GetDeviceCaps_(__currentDC, #LOGPIXELSY) / 72)
EndIf
CompilerIf #PB_Compiler_Unicode = 0
Protected len = Len(FontName$)
Protected tmp$ = Space(len*2+2)
PokeS(@tmp$,FontName$,-1,#PB_Unicode)
*fontName = @tmp$
CompilerElse
*fontName = @FontName$
CompilerEndIf
If GdipCreateFontFamilyFromName_(*fontName,0, @*fontFamily)
If GdipGetGenericFontFamilySansSerif_(@*fontFamily)
If GdipGetGenericFontFamilySerif_(@*fontFamily)
If GdipGetGenericFontFamilyMonospace_(@*fontFamily)
ProcedureReturn
EndIf
EndIf
EndIf
EndIf
If Not GdipCreateFont_(*fontFamily,FontSize,fs,2,@*font)
If __currentFont : GdipDeleteFont_(__currentFont) : EndIf
__currentFont = *font
GdipDeleteFontFamily_(*fontFamily)
EndIf
EndProcedure
bei dem man dann - ohne die obigen Anpassungen vorzunehmen - auch die fehlerhafte Schriftgröße sehen kann:
Code: Alles auswählen
Enumeration
#Window : #Gadget : #Image
EndEnumeration
XIncludeFile "gDrawing.pbi"
gInit()
CreateImage(#Image, 256, 512, 32|#PB_Image_Transparent)
StartDrawing(ImageOutput(#Image))
DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Transparent)
For Size = 1 To 24
DrawText(10, Size*Size*0.8, Str(Size), $FF000000)
Next
Box( 50, 0, 100, 512, $FFF0A050)
Box(150, 0, 100, 512, $FFF050a0)
StopDrawing()
For Size = 1 To 24
LoadFont(0, "Arial", Size)
gStartDrawing(ImageOutput(#Image))
gSetFont("Arial", Size)
gDrawText(60, Size*Size*0.8, "Hallo", $FF000000)
DrawingFont(FontID(0))
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(160, Size*Size*0.8, "Hallo", $FF000000)
gStopDrawing()
Next
OpenWindow(#Window, 0, 0, ImageWidth(#Image), ImageHeight(#Image), "Image", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
ImageGadget(#Gadget, 0, 0, ImageWidth(#Image), ImageHeight(#Image), ImageID(#Image))
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Greetz, PL.
PS: Anbei noch ein paar ScreenShots.
Links ohne Änderungen, rechts mit den o.g. Änderungen:


Zuletzt geändert von PureLust am 12.07.2011 08:38, insgesamt 3-mal geändert.
[Dynamic-Dialogs] - komplexe dynamische GUIs einfach erstellen
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
Re: [Windows] 2DDrawing Befehle mit AntiAliasing durch GDI+
@STARGÅTE:
Du kannst übrigens die 2 Schleifen auch kombinieren und gDrawing- und 2DDrawing-Befehle
mixen, da gStartDrawing() intern StartDrawing() aufruft.
@PureLust:
Vielen Dank! Wird übernommen.
EDIT: Update v0.66, Include & Beispiel
- gSetFont() geändert wie von PureLust vorgeschlagen
- Fehler bei gTextWidth() nach Transformationen behoben
TODO: Unterstützung für 32bit PB-Images bei gSetPenImage() einbauen,
der Alphakanal geht durch GDI+ verloren (offiziell dokumentiert).
Du kannst übrigens die 2 Schleifen auch kombinieren und gDrawing- und 2DDrawing-Befehle
mixen, da gStartDrawing() intern StartDrawing() aufruft.
Code: Alles auswählen
Enumeration
#Window : #Gadget : #Image
EndEnumeration
XIncludeFile "gDrawing.pbi"
If gInit()
CreateImage(#Image, 256, 512, 24);|#PB_Image_Transparent)
If gStartDrawing(ImageOutput(#Image))
gSetTextAntialiasMode(#TextAntialiasMode_Antialias)
DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Transparent)
Box(50, 0, 100, 512, $FFF0A050)
For Size = 1 To 24
DrawText(10, Size*Size*0.8, Str(Size), $FF000000)
gSetFont("Arial", Size)
gDrawText(60, Size*Size*0.8, "Hallo", $FF000000)
Next
gStopDrawing()
EndIf
OpenWindow(#Window, 0, 0, ImageWidth(#Image), ImageHeight(#Image), "Image", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
ImageGadget(#Gadget, 0, 0, ImageWidth(#Image), ImageHeight(#Image), ImageID(#Image))
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
gEnd()
EndIf
Vielen Dank! Wird übernommen.

EDIT: Update v0.66, Include & Beispiel
- gSetFont() geändert wie von PureLust vorgeschlagen
- Fehler bei gTextWidth() nach Transformationen behoben
TODO: Unterstützung für 32bit PB-Images bei gSetPenImage() einbauen,
der Alphakanal geht durch GDI+ verloren (offiziell dokumentiert).
Zuletzt geändert von Danilo am 12.07.2011 11:00, insgesamt 1-mal geändert.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Re: [Windows] 2DDrawing Befehle mit AntiAliasing durch GDI+
Oke danke, wäre das schon mal gelöst.
Nächstes Problem, ist genau die schon angesprochene Auflösung:
Lasse ich:
Auf einem Image laufen, bekomme ich genau eine Linie von 100px länge und 100px Breite bei Position 100,100
Auf einem Drucker (zB. FreePDF) bekomme ich jedoch völlig anderes:
- Die linie ist nicht bei 100px,100px und sie ist ca 6mal länger. (600dpi zu 96dpi)
Das einzige was stimmt ist die Breite von 100px.
Daraus schließe ich, das noch irgendwo eine Anpassung vorgenommen werde muss, damit alle gDrawing-Befehle auch bei verschiedenen Auflösungen richtig (wie PB) arbeiten.
ich glaube irgendwo gelesen zu haben, das man sogar bei GDI+ die Einheit angegeben kann, in der die Befehle arbeiten sollen.
Dort müsste dann alles auf Pixel und nicht auf Punkte gestellt werden.
Nächstes Problem, ist genau die schon angesprochene Auflösung:
Lasse ich:
Code: Alles auswählen
gSetPen($FF000000, 100)
gLineXY(100,100, 200, 100)
Auf einem Drucker (zB. FreePDF) bekomme ich jedoch völlig anderes:
- Die linie ist nicht bei 100px,100px und sie ist ca 6mal länger. (600dpi zu 96dpi)
Das einzige was stimmt ist die Breite von 100px.
Daraus schließe ich, das noch irgendwo eine Anpassung vorgenommen werde muss, damit alle gDrawing-Befehle auch bei verschiedenen Auflösungen richtig (wie PB) arbeiten.
ich glaube irgendwo gelesen zu haben, das man sogar bei GDI+ die Einheit angegeben kann, in der die Befehle arbeiten sollen.
Dort müsste dann alles auf Pixel und nicht auf Punkte gestellt werden.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr