Resize CanvasGadget -> Artefakte ?!

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Resize CanvasGadget -> Artefakte ?!

Beitrag von Mijikai »

Ich schreibe gerade ein kleines Tool zur Bildbearbeitung.
Für die spätere Darstellung mehrerer Bilder gleichzeitig verwende ich das CanvasGadget.
Wenn ich jetzt aber die Größe des CanvasGadgets ändere bekomme ich Artefakte bei der Darstellung!?

Artefakte (Linien werden nicht korrekt gezeichnet - hier sollte kein Abstand sein):
Bild

Hier mein Code:

Code: Alles auswählen

;PB x64 v.5.62 (Windows 7)

EnableExplicit

Structure GADGET_STRUCT
  Canvas.i
  StatusBar.i
EndStructure

Structure WINDOW_STRUCT
  Id.i
  Handle.i
  Flags.i
  Width.i
  Height.i
  Event.i
  Gadget.GADGET_STRUCT
EndStructure

Structure IMAGE_BUFFER_STRUCT
  Width.f
  Height.f
  FactorX.f
  FactorY.f
EndStructure

Global Window.WINDOW_STRUCT
Global ImageBuffer.IMAGE_BUFFER_STRUCT

Procedure.i Render()
  Protected X.i
  Protected Y.i
  Protected Index.i
  With Window
    If StartDrawing(CanvasOutput(\Gadget\Canvas))
      DrawingMode(#PB_2DDrawing_Default)
      Box(0,0,ImageBuffer\Width,ImageBuffer\Height,$FFFFFFFF)
      DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_Transparent)
      For Y = 0 To 9
        For X = 0 To 9
          Box(X * ImageBuffer\FactorX,Y * ImageBuffer\FactorY,ImageBuffer\FactorX,ImageBuffer\FactorY,$DDDDDDDD)
          DrawText(X * ImageBuffer\FactorX + 3,Y * ImageBuffer\FactorY + 3,Str(Index),$0,$FFFFFFFF)
          Index + 1
        Next
      Next
      StopDrawing()
    EndIf 
  EndWith 
EndProcedure

Procedure.i Resize()
  With Window
    \Width = WindowWidth(\Id,#PB_Window_InnerCoordinate)
    \Height = WindowHeight(\Id,#PB_Window_InnerCoordinate)
    ResizeGadget(\Gadget\Canvas,#Null,#Null,\Width,\Height - StatusBarHeight(\Gadget\StatusBar))
    ImageBuffer\Width = GadgetWidth(\Gadget\Canvas,#PB_Gadget_ActualSize)
    ImageBuffer\Height = GadgetHeight(\Gadget\Canvas,#PB_Gadget_ActualSize)
    ImageBuffer\FactorX = ImageBuffer\Width / 10
    ImageBuffer\FactorY = ImageBuffer\Height / 10
    Render()
  EndWith
EndProcedure

Procedure.i Main()
  With Window
    \Width = 800
    \Height = 600
    \Flags = #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget
    \Id = OpenWindow(#PB_Any,#Null,#Null,\Width,\Height,#Null$,\Flags)
    If \Id
      \Handle = WindowID(\Id)
      WindowBounds(\Id,\Width,\Height,#PB_Ignore,#PB_Ignore)
      \Gadget\StatusBar = CreateStatusBar(#PB_Any,\Handle)
      \Gadget\Canvas = CanvasGadget(#PB_Any,#Null,#Null,\Width,\Height - StatusBarHeight(\Gadget\StatusBar))
      Resize()
      BindEvent(#PB_Event_SizeWindow,@Resize())
      
      Repeat
        \Event = WaitWindowEvent()
        Select \Event
          Case #PB_Event_CloseWindow
            If EventWindow() = \Id
              Break
            EndIf
        EndSelect
        
      ForEver
      CloseWindow(\Id)
    EndIf 
  EndWith
EndProcedure

Main()
Wie kann ich die Artefakte vermeiden?
:coderselixir:
Benutzeravatar
Kiffi
Beiträge: 10620
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Resize CanvasGadget -> Artefakte ?!

Beitrag von Kiffi »

sieht mir nach einem Rundungsfehler aus.

vielleicht so?

Code: Alles auswählen

Structure IMAGE_BUFFER_STRUCT
  Width.i
  Height.i
  FactorX.i
  FactorY.i
EndStructure
Hygge
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Resize CanvasGadget -> Artefakte ?!

Beitrag von Mijikai »

Kiffi hat geschrieben:sieht mir nach einem Rundungsfehler aus.

vielleicht so?

Code: Alles auswählen

Structure IMAGE_BUFFER_STRUCT
  Width.i
  Height.i
  FactorX.i
  FactorY.i
EndStructure
Könnte ein Rundungsfehler sein aber mit Int's geht es leider auch nicht.
Statt dem Zeilenversatz gibt es nun große Lücken an den Rändern.
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Resize CanvasGadget -> Artefakte ?!

Beitrag von mk-soft »

Es gibt keine halben Pixel

Nicht perfekt, aber ein Satz

Code: Alles auswählen

;PB x64 v.5.62 (Windows 7)

EnableExplicit

Structure GADGET_STRUCT
  Canvas.i
  StatusBar.i
EndStructure

Structure WINDOW_STRUCT
  Id.i
  Handle.i
  Flags.i
  Width.i
  Height.i
  Event.i
  Gadget.GADGET_STRUCT
EndStructure

Structure IMAGE_BUFFER_STRUCT
  Width.f
  Height.f
  FactorX.f
  FactorY.f
EndStructure

Global Window.WINDOW_STRUCT
Global ImageBuffer.IMAGE_BUFFER_STRUCT

Procedure.i Render()
  Protected X.i, DX.i, XC.i
  Protected Y.i, DY.i, YC.i
  Protected Index.i
  With Window
    If StartDrawing(CanvasOutput(\Gadget\Canvas))
      DrawingMode(#PB_2DDrawing_Default)
      Box(0,0,ImageBuffer\Width,ImageBuffer\Height,$FFFFFFFF)
      DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_Transparent)
      X = 0
      Y = 0
      DX = ImageBuffer\FactorX
      DY = ImageBuffer\FactorY
      For YC = 0 To 9
        For XC = 0 To 9
          Box(X, Y, DX, DY ,$DDDDDDDD)
          DrawText(X + 3,Y + 3,Str(Index),$0,$FFFFFFFF)
          X + DX
          Index + 1
        Next
        X = 0
        Y + DY
      Next
      StopDrawing()
    EndIf 
  EndWith 
EndProcedure


Procedure.i Resize()
  With Window
    \Width = WindowWidth(\Id,#PB_Window_InnerCoordinate)
    \Height = WindowHeight(\Id,#PB_Window_InnerCoordinate)
    ResizeGadget(\Gadget\Canvas,#Null,#Null,\Width,\Height - StatusBarHeight(\Gadget\StatusBar))
    ImageBuffer\Width = GadgetWidth(\Gadget\Canvas,#PB_Gadget_ActualSize)
    ImageBuffer\Height = GadgetHeight(\Gadget\Canvas,#PB_Gadget_ActualSize)
    ImageBuffer\FactorX = ImageBuffer\Width / 10
    ImageBuffer\FactorY = ImageBuffer\Height / 10
    Render()
  EndWith
EndProcedure

Procedure.i Main()
  With Window
    \Width = 800
    \Height = 600
    \Flags = #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget
    \Id = OpenWindow(#PB_Any,#Null,#Null,\Width,\Height,#Null$,\Flags)
    If \Id
      \Handle = WindowID(\Id)
      WindowBounds(\Id,\Width,\Height,#PB_Ignore,#PB_Ignore)
      \Gadget\StatusBar = CreateStatusBar(#PB_Any,\Handle)
      \Gadget\Canvas = CanvasGadget(#PB_Any,#Null,#Null,\Width,\Height - StatusBarHeight(\Gadget\StatusBar))
      Resize()
      BindEvent(#PB_Event_SizeWindow,@Resize())
      
      Repeat
        \Event = WaitWindowEvent()
        Select \Event
          Case #PB_Event_CloseWindow
            If EventWindow() = \Id
              Break
            EndIf
        EndSelect
        
      ForEver
      CloseWindow(\Id)
    EndIf 
  EndWith
EndProcedure

Main()
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Resize CanvasGadget -> Artefakte ?!

Beitrag von Mijikai »

mk-soft hat geschrieben:Es gibt keine halben Pixel

Nicht perfekt, aber ein Satz
Leider das gleiche Problem wie bei Kiffis Versuch:
Bild

Das Ergebnis ist auch hier nicht akzeptabel.

Edit:
Mit VectorDrawing sieht es besser aus jedoch gibt es auch hier doppelte Linien (jedoch ohne Abstand dazwischen).

Also irgendwas ist faul.
Wie soll man da was vernünftig Zeichnen können - Bug?
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Resize CanvasGadget -> Artefakte ?!

Beitrag von STARGÅTE »

Mijikai hat geschrieben:Also irgendwas ist faul.Wie soll man da was vernünftig Zeichnen können - Bug?
Wo soll hier ein Bug sein.
Wenn du dein Canvas beliebig vergrößern kannst, dann aber dein Zeichenbereich in 10 Teile teilst, dann muss logischerweise ein Problem auftreten:
A) Entweder alle Boxen sind gleich groß, dann bekommst du einen Freiraum rechts und unten
B) Die Boxen sind nicht alle gleich groß, dann darfst du aber nicht alle Boxen mit der gleichen Größe berechnen, sondern z.B. so:

Code: Alles auswählen

;PB x64 v.5.62 (Windows 7)

EnableExplicit

Structure GADGET_STRUCT
  Canvas.i
  StatusBar.i
EndStructure

Structure WINDOW_STRUCT
  Id.i
  Handle.i
  Flags.i
  Width.i
  Height.i
  Event.i
  Gadget.GADGET_STRUCT
EndStructure

Structure IMAGE_BUFFER_STRUCT
  Width.f
  Height.f
  FactorX.f
  FactorY.f
EndStructure

Global Window.WINDOW_STRUCT
Global ImageBuffer.IMAGE_BUFFER_STRUCT

Procedure.i Render()
  Protected X.i
  Protected Y.i
  Protected Index.i
  With Window
    If StartDrawing(CanvasOutput(\Gadget\Canvas))
      DrawingMode(#PB_2DDrawing_Default)
      Box(0,0,ImageBuffer\Width,ImageBuffer\Height,$FFFFFFFF)
      DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_Transparent)
      For Y = 0 To 9
        For X = 0 To 9
          Box(Int(X*ImageBuffer\FactorX), Int(Y*ImageBuffer\FactorY), Int((X+1)*ImageBuffer\FactorX)-Int(X*ImageBuffer\FactorX), Int((Y+1)*ImageBuffer\FactorY)-Int(Y*ImageBuffer\FactorY),$DDDDDDDD)
          DrawText(X * ImageBuffer\FactorX + 3,Y * ImageBuffer\FactorY + 3,Str(Index),$0,$FFFFFFFF)
          Index + 1
        Next
      Next
      StopDrawing()
    EndIf 
  EndWith 
EndProcedure

Procedure.i Resize()
  With Window
    \Width = WindowWidth(\Id,#PB_Window_InnerCoordinate)
    \Height = WindowHeight(\Id,#PB_Window_InnerCoordinate)
    ResizeGadget(\Gadget\Canvas,#Null,#Null,\Width,\Height - StatusBarHeight(\Gadget\StatusBar))
    ImageBuffer\Width = GadgetWidth(\Gadget\Canvas,#PB_Gadget_ActualSize)
    ImageBuffer\Height = GadgetHeight(\Gadget\Canvas,#PB_Gadget_ActualSize)
    ImageBuffer\FactorX = ImageBuffer\Width / 10
    ImageBuffer\FactorY = ImageBuffer\Height / 10
    Render()
  EndWith
EndProcedure

Procedure.i Main()
  With Window
    \Width = 800
    \Height = 600
    \Flags = #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget
    \Id = OpenWindow(#PB_Any,#Null,#Null,\Width,\Height,#Null$,\Flags)
    If \Id
      \Handle = WindowID(\Id)
      WindowBounds(\Id,\Width,\Height,#PB_Ignore,#PB_Ignore)
      \Gadget\StatusBar = CreateStatusBar(#PB_Any,\Handle)
      \Gadget\Canvas = CanvasGadget(#PB_Any,#Null,#Null,\Width,\Height - StatusBarHeight(\Gadget\StatusBar))
      Resize()
      BindEvent(#PB_Event_SizeWindow,@Resize())
      
      Repeat
        \Event = WaitWindowEvent()
        Select \Event
          Case #PB_Event_CloseWindow
            If EventWindow() = \Id
              Break
            EndIf
        EndSelect
        
      ForEver
      CloseWindow(\Id)
    EndIf 
  EndWith
EndProcedure

Main()
PS: Für Int() kann auch Round() verwendet 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
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: Resize CanvasGadget -> Artefakte ?!

Beitrag von Bisonte »

Also mit Kiffi's Versuch ist hier alles in Ordnung. Diese Lücken da rechts und unten ... die sind sofort verschwunden (d.h. komplettes Fenster ausgefüllt) wenn ich die linke Maustaste nach dem Resizen loslasse. Ist jetzt allerdings W10. Sollte aber bei W7 das gleiche sein.

Das was da den Rand verursacht ist dein / 10 (wenn's mal nicht rund ist ist halt eine Lücke) und ein noch nicht fertig "resized" Canvas Gadget.

Edit: Uh wieder zu langsam ;)
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
#NULL
Beiträge: 2235
Registriert: 20.04.2006 09:50

Re: Resize CanvasGadget -> Artefakte ?!

Beitrag von #NULL »

Das Problem ist in etwa folgendes:
Stell dir vor du hast eine Höhe von 100 und willst 3 Zeilen:

Code: Alles auswählen

For i=1 To 3
  f.f = i * 100.0 / 3
  n = f
  Debug f
  Debug n
Next
du siehst also, dass ein Schritt in Integer (oder Pixel) 33 wäre aber der Zweite Schritt bei 67 landet.
Entweder du passt die Größe einzelner Zeilen an, so dass die volle Höhe ausgenutzt werden kann aber dann eben nicht alle Boxen extakt gleich groß sind (z.B. 33 + 34 + 33), oder du berechnest die größt-mögliche Box-Höhe die du auf alle Boxen anwenden kannst ohne den Gesamtbereich zu überschreiten, dann wiederum hast du unten eben einen kleinen Leerraum der den restlichen Platz einnimmt (33 + 33 + 33 [+ 1]).
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Resize CanvasGadget -> Artefakte ?!

Beitrag von Mijikai »

Wenn ich mit Floats/Doubles arbeite ist doch die errechnete Bild-Box doch immer gleich groß?

Code: Alles auswählen

Global Width.i
Global BoxWidth.d
Global Index.i
Global Offset.d

Width = 1333
BoxWidth = Width / 10

Debug BoxWidth
Debug "------------"

For Index = 0 To 9
  Offset = (Index + 1) * BoxWidth
  Debug Offset
Next
Im ScreenMode bekomme ich ja auch keine Artefakte wenn ich z.B. Tiles zeichne... :freak:

Danke für die vielen Beiträge aber ich habs wohl noch immer noch nicht ganz Verstanden :|
- STARGÅTEs Code erzielt ein korrektes Ergebnis :)

:coderselixir:
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Resize CanvasGadget -> Artefakte ?!

Beitrag von mk-soft »

War gerade einkaufen und daher STARGATE schneller :mrgreen:

Habe es noch ein wenig optimiert...

Code: Alles auswählen

;PB x64 v.5.62 (Windows 7)

EnableExplicit

Structure GADGET_STRUCT
  Canvas.i
  StatusBar.i
EndStructure

Structure WINDOW_STRUCT
  Id.i
  Handle.i
  Flags.i
  Width.i
  Height.i
  Event.i
  Gadget.GADGET_STRUCT
EndStructure

Structure IMAGE_BUFFER_STRUCT
  Width.f
  Height.f
  FactorX.f
  FactorY.f
EndStructure

Global Window.WINDOW_STRUCT
Global ImageBuffer.IMAGE_BUFFER_STRUCT

Procedure.i Render()
  Protected X.i, x0.i, x1.i, dx.i
  Protected Y.i, y0.i, y1.i, dy.i
  
  Protected Index.i
  With Window
    If StartDrawing(CanvasOutput(\Gadget\Canvas))
      DrawingMode(#PB_2DDrawing_Default)
      Box(0,0,ImageBuffer\Width,ImageBuffer\Height,$FFFFFFFF)
      DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_Transparent)
      For Y = 0 To 9
        y0 = Y * ImageBuffer\FactorY
        y1 = (Y + 1) * ImageBuffer\FactorY
        dy = y1 - y0 - 1
        For X = 0 To 9
          x0 = X * ImageBuffer\FactorX
          x1 = (X + 1) * ImageBuffer\FactorX
          dx = x1 - x0 - 1
          Box(x0, y0, dx, dy ,$DDDDDDDD)
          DrawText(x0 + 3, y0 + 3, Str(Index),$0,$FFFFFFFF)
          Index + 1
        Next
      Next
      StopDrawing()
    EndIf 
  EndWith 
EndProcedure

Procedure.i Resize()
  With Window
    \Width = WindowWidth(\Id,#PB_Window_InnerCoordinate)
    \Height = WindowHeight(\Id,#PB_Window_InnerCoordinate)
    ResizeGadget(\Gadget\Canvas,#Null,#Null,\Width,\Height - StatusBarHeight(\Gadget\StatusBar))
    ImageBuffer\Width = GadgetWidth(\Gadget\Canvas,#PB_Gadget_ActualSize)
    ImageBuffer\Height = GadgetHeight(\Gadget\Canvas,#PB_Gadget_ActualSize)
    ImageBuffer\FactorX = ImageBuffer\Width / 10
    ImageBuffer\FactorY = ImageBuffer\Height / 10
    Render()
  EndWith
EndProcedure

Procedure.i Main()
  With Window
    \Width = 600
    \Height = 400
    \Flags = #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget
    \Id = OpenWindow(#PB_Any,#Null,#Null,\Width,\Height,#Null$,\Flags)
    If \Id
      \Handle = WindowID(\Id)
      WindowBounds(\Id,\Width,\Height,#PB_Ignore,#PB_Ignore)
      \Gadget\StatusBar = CreateStatusBar(#PB_Any,\Handle)
      \Gadget\Canvas = CanvasGadget(#PB_Any,#Null,#Null,\Width,\Height - StatusBarHeight(\Gadget\StatusBar))
      Resize()
      BindEvent(#PB_Event_SizeWindow,@Resize())
      
      Repeat
        \Event = WaitWindowEvent()
        Select \Event
          Case #PB_Event_CloseWindow
            If EventWindow() = \Id
              Break
            EndIf
        EndSelect
        
      ForEver
      CloseWindow(\Id)
    EndIf 
  EndWith
EndProcedure

Main()
[/size]
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Antworten