Transparent painting with feather effect

I made this little think.
http://www.youtube.com/watch?v=HjYAQf_qxQA
You can paint with real transparency.


function setup()
    parameter("red",0,255,244)
    parameter("green",0,255,100)
    parameter("blue",0,255,100)
    parameter("alpha",0,255,200)
    parameter("thickness",1,80,25)
    iparameter("cap",0,2,0)
    iparameter("feather",0,1,0)
    myDrawing=image(WIDTH,HEIGHT)
    myBack=image(WIDTH,HEIGHT)

end

function draw()
    local v,t,angle
    if(CurrentTouch.state==BEGAN or CurrentTouch.state==MOVING) then
        if(feather==1) then
            v = vec2(CurrentTouch.x,CurrentTouch.y)
                -vec2(CurrentTouch.prevX,CurrentTouch.prevY)
            angle = v:angleBetween(vec2(1,-1))
            t = thickness * math.abs(math.cos(angle))+5
        else 
            t = thickness
        end    
        strokeWidth(t)
        lineCapMode(cap)
        stroke(red, green, blue, 255)
        setContext(myDrawing)
        tint(255, 255, 255, 255)
        line(CurrentTouch.prevX,CurrentTouch.prevY,CurrentTouch.x,CurrentTouch.y)
    else
        setContext(myBack)
        tint(255, 255, 255, alpha)
        sprite(myDrawing,WIDTH/2,HEIGHT/2)
        setContext(myDrawing)
        background(0,0,0,0)
                
    end
    setContext()
    background(0, 0, 0, 255)
    tint(255, 255, 255, 255)
    sprite(myBack,WIDTH/2,HEIGHT/2)
    tint(255, 255, 255, alpha)
    sprite(myDrawing,WIDTH/2,HEIGHT/2)
end

BTW I’m a musician, did you notice :-)) ?

Wow, looks nice!!! :slight_smile:

But waaay slow on my New iPad

Very nice, @pepinganos! You’ve created a nice brush effect there, which is great for symbols. Your code is so short, too!

As a musician, you might be interested in some musical programs that have been published on these forums, some for generating sounds, a Theremin instrument and my attempt at developing a music engine.

Great piece of code, @pepinganos. Love the simplicity of it and the results are great.

Is there a method to force the lower resolution with the new ipad? @Simeon

this runs to slow on a new iPad

@Inviso version 1.4 will have a way to do this. It introduces a new global variable called ContentScaleFactor. This will be set to 2 on retina devices (1 on non-retina devices). You could use this to determine if you are rendering on a retina device and allocate a half-sized image, then scale it up. That should deliver performance equivalent to a non-retina device.

Edit: You can actually check for retina at the moment using the following hack:

function isRetina()
    local img = image(20,20)

    if img.width ~= img.rawWidth then
        return true

    return false
end

(This takes advantage of the fact that retina devices will internally allocate images that are double sized.)

@Fred, I will look at those musical programs. @Inviso, I didn’t know about the program running slow on the new iPad, because I don’t have one. I imagine this is because of the greater resolution.
@Simeon, I have a problem: when I trace a line without lifting the finger, often I get holes. Why is it?
Thanks to everyone for your comments.

hey @pepinganos, i wanted to test this on my ipad 3, so i “changed the resolution to half” and it’s now usable. and i used my own prevY and prevX Variables, and then, no holes…

heres the code:



function setup()
    parameter("red",0,255,244)
    parameter("green",0,255,100)
    parameter("blue",0,255,100)
    parameter("alpha",0,255,200)
    parameter("thickness",1,80,25)
    iparameter("cap",0,2,0)
    iparameter("feather",0,1,0)
    myDrawing=image(WIDTH/2,HEIGHT/2)
    myBack=image(WIDTH/2,HEIGHT/2)
    prevx = 0
    
    
end

function touched()
 --  print(CurrentTouch.state)
if CurrentTouch.state == 0 then
    prevx =0
end
    
end    
function draw()
    local v,t,angle
    
   
    if prevx==0 then
        prevx = CurrentTouch.x
        prevy = CurrentTouch.y
    end
    

    
    if(CurrentTouch.state==BEGAN or CurrentTouch.state==MOVING) then
        if(feather==1) then
            v = vec2(CurrentTouch.x,CurrentTouch.y)
                -vec2(prevx,prevy)
            angle = v:angleBetween(vec2(1,-1))
            t = thickness * math.abs(math.cos(angle))+5
        else 
            t = thickness
        end    
        strokeWidth(t)
        lineCapMode(cap)
        stroke(red, green, blue, 255)
        setContext(myDrawing)
        tint(255, 255, 255, 255)
        line(prevx/2,prevy/2,CurrentTouch.x/2,CurrentTouch.y/2)
       -- print(mytouch.state)
    else
        setContext(myBack)
        tint(255, 255, 255, alpha)
        sprite(myDrawing,WIDTH/4,HEIGHT/4, WIDTH/2,HEIGHT/2)
        setContext(myDrawing)
        background(0,0,0,0)
        prevx = 0
        prevy = 0
      -- print("loose")
                
    end
    setContext()
    background(0, 0, 0, 255)
    tint(255, 255, 255, 255)
    sprite(myBack,WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
    tint(255, 255, 255, alpha)
    sprite(myDrawing,WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
    prevx = CurrentTouch.x
    prevy = CurrentTouch.y
end

Thanks @Inviso, now there are no gaps at all. The question is “why”…

i think it’s something in the CurrentTouch.prevX and prevY Values gettings updated too fast, so that it’s maybe the same value as the .x value… so i tried to override that and make my own…
there is one thing, in the else block (CurrentTouch.state should be ended) i made a print, there i set prevx = 0

but that was not enough, i had to add

function touched()
 --  print(CurrentTouch.state)
if CurrentTouch.state == 0 then
    prevx =0
end

or otherwise it would draw a line from my last ended drawing position…

I tested your solution intensely and… no gaps.
@Simeon, could it be possible that there’s something wrong with CurrentTouch.prevX and prevY?

@pepinganos it’s probably due to CurrentTouch.prevX and prevY retaining their values when the touch hasn’t changed for a particular frame. We should reset them — the reason we don’t do this is because iOS doesn’t, so we were trying to keep the APIs in line.

That is, prevX and prevY represent the previous location of the touch when it was last updated which may, or may not have been the previous frame.