Page 2 of 2

Re: Find a point between two points

Posted: Sun Jun 28, 2015 4:11 pm
by [blendman]
Hi

Thank you all for your code and explications.
As falsam has said, I'm looking for a way to paint stroke, for my 2D application (animatoon).

I would like to find a way to create a beautiful antialiased lines with stroke (use of drawalphaImage(), or another technic with image-brush, not linexy()).

I have tried a lot of code (found here or in other forums/size), but I haven't found a code to draw a beautifull curve with circle or image (drawalphaImage()) which are Antialiased event in a few pixels (1 or 2 pixels of width for exemple).

If someone has an idea how I can achieve that, it would be very usefull ;)

Re: Find a point between two points

Posted: Sun Jun 28, 2015 4:47 pm
by Julian
Cant you draw it onto an image that is 2x or 4x the size required then resize it down using #PB_Image_Smooth and paste that where your drawing is happening?

Re: Find a point between two points

Posted: Sun Jun 28, 2015 5:16 pm
by infratec
Does this help:

Code: Select all

OpenWindow(0, 0, 0, 800, 600, "Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 800, 600)

Repeat
  
  Event = WaitWindowEvent()
  
  Select Event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
          Select EventType()
            Case #PB_EventType_LeftButtonDown
              If Not Drawing
                If StartDrawing(CanvasOutput(0))
                  LastX = GetGadgetAttribute(0, #PB_Canvas_MouseX)
                  LastY = GetGadgetAttribute(0, #PB_Canvas_MouseY)
                  Circle(LastX, LastY, 4, #Red)
                  StopDrawing()
                  Drawing = #True
                EndIf
              EndIf
            Case #PB_EventType_MouseMove
              If Drawing
                If StartDrawing(CanvasOutput(0))
                  
                  CurrentX = GetGadgetAttribute(0, #PB_Canvas_MouseX)
                  CurrentY = GetGadgetAttribute(0, #PB_Canvas_MouseY)
                  
                  dx = CurrentX - LastX
                  dy = CurrentY - LastY
                  distance = Sqr(dx*dx + dy*dy)
                  
                  If distance > 4
                    
                    p.f = 4 / distance
                    
                    Repeat
                      ;Debug "B" + Str(distance)
                      LastX + (dx * p)
                      LastY + (dy * p)
                      Circle(LastX, LastY, 4, #Green)
                      
                      distance - 4
                    Until distance <= 0
                    
                  Else
                    Circle(CurrentX, CurrentY, 4, #Red)
                  EndIf
                  
                  LastX = CurrentX
                  LastY = CurrentY
                  
                  StopDrawing()
                EndIf
              EndIf
            Case #PB_EventType_LeftButtonUp
              If Drawing
                Drawing = #False
              EndIf
          EndSelect
      EndSelect
      
    Case #PB_Event_CloseWindow
      Exit = #True
  EndSelect
  
Until Exit
Bernd

Re: Find a point between two points

Posted: Sun Jun 28, 2015 6:16 pm
by Julian
Julian wrote:Cant you draw it onto an image that is 2x or 4x the size required then resize it down using #PB_Image_Smooth and paste that where your drawing is happening?
Now I remember, weren't you having problems with alpha's around resized images? If so the above wont really work for you.

The solution is to have an up sampled version of your canvas in memory that you can draw to, you can then grab off this and down sample to introduce anti-aliasing.

Here's a really simple example I threw together to show how to do it, an anti-aliased circle with no edge artefacts.

Let me know if you have any questions about it.

You could do this a few ways, you could also GrabImage where you are about to draw, scale it up by resampleFactor, draw your circle (or curve), scale it down then paste it back. This would not restrict you to a maximum image size (if this is even the case with 64bit?).

Code: Select all

displayedImageSize = 1024 ; the size of the image on the canvas

resampleFactor = 4 ; how much scaling we want to do to smooth things out
memoryImage = CreateImage(#PB_Any, displayedImageSize * resampleFactor, displayedImageSize * resampleFactor, 32, #PB_Image_Transparent)

circleSize = 50 ; .oO

OpenWindow(0, 0, 0, displayedImageSize, displayedImageSize, "Test")

CanvasGadget(0, 0, 0, displayedImageSize, displayedImageSize)

drawing = #False

Repeat
  Event = WindowEvent()
  Select Event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
          Select EventType()
            Case #PB_EventType_LeftButtonDown
              drawing = #True
            Case #PB_EventType_LeftButtonUp
              drawing = #False
          EndSelect
      EndSelect
  EndSelect
  
  If drawing
    
    x = GetGadgetAttribute(0, #PB_Canvas_MouseX) * resampleFactor
    y = GetGadgetAttribute(0, #PB_Canvas_MouseY) * resampleFactor
    
    If x > circleSize And y > circleSize ; this is a bodge as this is a quick example, to get around this create a border around the edge of your memoryimage the size of your biggest brush
      
      
      ;draw the cirlce onto the memoryImage (which is resampleFactor times the size of the displayed image)
      ;StartTime = ElapsedMilliseconds()
      ;Debug ("1 " + Str(ElapsedMilliseconds() - StartTime))
      StartDrawing(ImageOutput(memoryImage))
      DrawingMode(#PB_2DDrawing_AlphaBlend)
      Circle(x, y, circleSize, RGBA(255,0,0,255))
      StopDrawing()
      ;Debug ("2 " + Str(ElapsedMilliseconds() - StartTime))
      
      ;resizing the whole canvas every draw call was slow so we're grabbing the changed part directly off memoryImage and only scaling that
      ;grab a new image off the memoryImage the size of the circle being drawn
      grab = GrabImage(memoryImage, #PB_Any, x-circleSize, y-circleSize, circleSize * resampleFactor, circleSize * resampleFactor)
      ;resize the grabbed image a scale it using smoothing to antialias everything
      ResizeImage(grab, circleSize, circleSize)
      
      ;Debug ("3 " + Str(ElapsedMilliseconds() - StartTime))
      StartDrawing(CanvasOutput(0))
      DrawingMode(#PB_2DDrawing_AlphaBlend)
      DrawImage(ImageID(grab), (x / resampleFactor) - circleSize / resampleFactor, (y / resampleFactor) - circleSize / resampleFactor)
      StopDrawing()
      ;Debug ("4 " + Str(ElapsedMilliseconds() - StartTime))
      
      FreeImage(grab)
    
    EndIf
  EndIf
  
  
Until Event = #PB_Event_CloseWindow

Re: Find a point between two points

Posted: Mon Jun 29, 2015 1:23 pm
by [blendman]
Hi

Thank you for your answer.

I have start another thread related to drawing a good stroke (AA, brush...) ;) :
http://www.purebasic.fr/english/viewtop ... 13&t=62511