Seite 1 von 2

Resize CanvasGadget -> Artefakte ?!

Verfasst: 13.10.2018 12:15
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:

Re: Resize CanvasGadget -> Artefakte ?!

Verfasst: 13.10.2018 12:17
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

Re: Resize CanvasGadget -> Artefakte ?!

Verfasst: 13.10.2018 12:19
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.

Re: Resize CanvasGadget -> Artefakte ?!

Verfasst: 13.10.2018 12:32
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()

Re: Resize CanvasGadget -> Artefakte ?!

Verfasst: 13.10.2018 12:46
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?

Re: Resize CanvasGadget -> Artefakte ?!

Verfasst: 13.10.2018 13:25
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.

Re: Resize CanvasGadget -> Artefakte ?!

Verfasst: 13.10.2018 13:28
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 ;)

Re: Resize CanvasGadget -> Artefakte ?!

Verfasst: 13.10.2018 13:45
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]).

Re: Resize CanvasGadget -> Artefakte ?!

Verfasst: 13.10.2018 14:03
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:

Re: Resize CanvasGadget -> Artefakte ?!

Verfasst: 13.10.2018 15:50
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]