draw in an outlined masked image

assume i have an outlined image and i want to draw in it.i do not want to draw on transparent pixels(just visible pixels),I used container to reach this but no success.can you give the clue?

Thanks

Hi @arash45654,

Can you show how your image is set up? Did you apply a graphical mask (graphics.newMask())? Containers achieve “masking” but only in a rectangular bounds, not traced around an image’s actual curves/pixels or anything like that.

Please remember to surround your code with “lua” tags for clarity in this forum post.

[lua] -- code [/lua]

Thanks,

Brent

i used sample of below link and i changed it according to my need:
http://www.jasonschroeder.com/2015/02/17/corona-finger-paint-module-revisited/

I have this image & its mask:
alef.png?dl=1 alefbw.png?dl=1

adding image & mask and touchlistener(first i used [lua] tag but it did not show well):
 

local canvas = display.newContainer(display.actualContentWidth, display.actualContentHeight) canvas.x, canvas.y = x, y local t1= display.newImage( canvas,"resources/alef.png",0,0 ) t1:scale( scaleFactor, scaleFactor ) local maskAlefba = graphics.newMask("resources/alefbw.png") t1:setMask( maskAlefba ) local function touch(event) -- set local variables local phase = event.phase local target = event.target local stroke = strokes[#strokes] -- recalculate touch cooridnates, taking into account canvas position local canvasX, canvasY = canvas:localToContent(canvas.anchorX, canvas.anchorY) local x = event.x - canvasX local y = event.y - canvasY local xStart = event.xStart - canvasX local yStart = event.yStart - canvasY local function getDistance(x1,y1,x2,y2) return math.sqrt((x2 - x1) ^ 2 + (y2 - y1) ^ 2) end if target.lastX == nil then target.lastX, target.lastY = x, y end local distance = getDistance(x, y, target.lastX, target.lastY) -- check for event phase & start, update, or end stroke accordingly if phase == "began" and canvas.isActive then -- empty undone table for i=#undone,1,-1 do display.remove(undone[i]) undone[i] = nil end -- start stroke display.getCurrentStage():setFocus(target, event.id) touchBegan = true strokes[#strokes+1] = display.newGroup() stroke = strokes[#strokes] canvas:insert(stroke) local circle = display.newCircle(stroke, x, y, circleRadius) circle:setFillColor(paintR, paintG, paintB, paintA) target.lastX, target.lastY = x, y elseif phase=="moved" and touchBegan == true and distance \> circleRadius\*.5 then -- append to stroke if segmented then stroke.line = display.newLine(stroke, target.lastX, target.lastY, x, y) local circle = display.newCircle(stroke, x, y, circleRadius) circle:setFillColor(paintR, paintG, paintB, paintA) else if stroke.line == nil then stroke.line = display.newLine(stroke, xStart, yStart, x, y) stroke.circle = display.newCircle(stroke, x, y, circleRadius) stroke.circle:setFillColor(paintR, paintG, paintB, paintA) else stroke.line:append(x, y) stroke.circle.x, stroke.circle.y = x, y end end stroke.line:setStrokeColor(paintR, paintG, paintB, paintA) stroke.line.strokeWidth = strokeWidth target.lastX, target.lastY = x, y -- end elseif (phase == "cancelled" or phase == "ended") and touchBegan == true then -- end stroke display.getCurrentStage():setFocus(nil, event.id) touchBegan = false local circle = display.newCircle(stroke, x, y, circleRadius) circle:setFillColor(paintR, paintG, paintB, paintA) target.lastX, target.lastY = nil, nil return true end end -------------------------------------------------------------------------------- -- ADD TOUCH LISTENER TO CANVAS -------------------------------------------------------------------------------- t1:addEventListener("touch", touch)  

transparent pixel does not fire on begin phase of touch(so it is ok),the problem is that when i begin from visible pixels and move my finger in transparent pixels,it draws on trasparent pixels! how can i solve this?
Thanks

 

Hi @arash45654,

It appears you’re drawing new “strokes” into the “canvas” container. What you should do is mask the entire group which contains the image, then draw strokes into that group.

This should help you:

https://docs.coronalabs.com/guide/media/imageMask/index.html#group-masking

Take care,

Brent

you mean i should remove canvas container and create a displaygroup and insert strokes to this group?
I tested this but no luck

Not exactly… create a new display group (not a container) and then insert your image into it. Then mask the entire group (not just the image). Then apply strokes inside the group (now masked).

Hope this helps,

Brent

I changed it according to your answer but no luck :frowning: , here is the code:

local centerX = display.contentCenterX local centerY = display.contentCenterY local screenTop = display.screenOriginY local screenLeft = display.screenOriginX local screenBottom = display.screenOriginY+display.actualContentHeight local screenRight = display.screenOriginX+display.actualContentWidth local screenWidth = screenRight - screenLeft local screenHeight = screenBottom - screenTop local touchBegan = false local width = screenWidth local height = screenHeight local strokeWidth = 10 local circleRadius = strokeWidth \* .5 local imageGroup=display.newGroup() imageGroup.x=50 imageGroup.y=90 scaleFactor=0.25 local t1= display.newImage( imageGroup,"resources/alef.png",0,0 ) t1:scale( scaleFactor, scaleFactor ) local maskAlefba = graphics.newMask("resources/alefbw.png") imageGroup:setMask( maskAlefba ) imageGroup.strokes = {} local strokes = imageGroup.strokes imageGroup.undone = {} local undone = imageGroup.undone local function touch(event) -- set local variables local phase = event.phase local target = event.target local stroke = strokes[#strokes] local x = event.x - imageGroup.x local y = event.y - imageGroup.y local xStart = event.xStart - imageGroup.x local yStart = event.yStart - imageGroup.y local function getDistance(x1,y1,x2,y2) return math.sqrt((x2 - x1) ^ 2 + (y2 - y1) ^ 2) end if target.lastX == nil then target.lastX, target.lastY = x, y end local distance = getDistance(x, y, target.lastX, target.lastY) -- check for event phase & start, update, or end stroke accordingly if phase == "began" then -- empty undone table for i=#undone,1,-1 do display.remove(undone[i]) undone[i] = nil end -- start stroke display.getCurrentStage():setFocus(target, event.id) touchBegan = true strokes[#strokes+1] = display.newGroup() stroke = strokes[#strokes] imageGroup:insert(stroke) local circle = display.newCircle(stroke, x, y, circleRadius) circle:setFillColor(1, 0,0,1) target.lastX, target.lastY = x, y elseif phase=="moved" and touchBegan == true and distance \> circleRadius\*.5 then if segmented then stroke.line = display.newLine(stroke, target.lastX, target.lastY, x, y) local circle = display.newCircle(stroke, x, y, circleRadius) circle:setFillColor(1, 0, 0, 1) else if stroke.line == nil then stroke.line = display.newLine(stroke, xStart, yStart, x, y) stroke.circle = display.newCircle(stroke, x, y, circleRadius) stroke.circle:setFillColor(1, 0, 0, 1) else stroke.line:append(x, y) stroke.circle.x, stroke.circle.y = x, y end end stroke.line:setStrokeColor(1, 0, 0, 1) stroke.line.strokeWidth = strokeWidth target.lastX, target.lastY = x, y -- end elseif (phase == "cancelled" or phase == "ended") and touchBegan == true then -- end stroke display.getCurrentStage():setFocus(nil, event.id) touchBegan = false local circle = display.newCircle(stroke, x, y, circleRadius) circle:setFillColor(1, 0, 0, 1) target.lastX, target.lastY = nil, nil return true end end -------------------------------------------------------------------------------- -- ADD TOUCH LISTENER TO CANVAS -------------------------------------------------------------------------------- imageGroup:addEventListener("touch", touch) 

I defined imageGroup variable as displaygroup and added image and strokes to it, and masked entire group. 

solved by adding this line after setmask:

imageGroup.maskScaleX = scaleFactor imageGroup.maskScaleY = scaleFactor

Thanks So Much

Hi @arash45654,

Can you show how your image is set up? Did you apply a graphical mask (graphics.newMask())? Containers achieve “masking” but only in a rectangular bounds, not traced around an image’s actual curves/pixels or anything like that.

Please remember to surround your code with “lua” tags for clarity in this forum post.

[lua] -- code [/lua]

Thanks,

Brent

i used sample of below link and i changed it according to my need:
http://www.jasonschroeder.com/2015/02/17/corona-finger-paint-module-revisited/

I have this image & its mask:
alef.png?dl=1 alefbw.png?dl=1

adding image & mask and touchlistener(first i used [lua] tag but it did not show well):
 

local canvas = display.newContainer(display.actualContentWidth, display.actualContentHeight) canvas.x, canvas.y = x, y local t1= display.newImage( canvas,"resources/alef.png",0,0 ) t1:scale( scaleFactor, scaleFactor ) local maskAlefba = graphics.newMask("resources/alefbw.png") t1:setMask( maskAlefba ) local function touch(event) -- set local variables local phase = event.phase local target = event.target local stroke = strokes[#strokes] -- recalculate touch cooridnates, taking into account canvas position local canvasX, canvasY = canvas:localToContent(canvas.anchorX, canvas.anchorY) local x = event.x - canvasX local y = event.y - canvasY local xStart = event.xStart - canvasX local yStart = event.yStart - canvasY local function getDistance(x1,y1,x2,y2) return math.sqrt((x2 - x1) ^ 2 + (y2 - y1) ^ 2) end if target.lastX == nil then target.lastX, target.lastY = x, y end local distance = getDistance(x, y, target.lastX, target.lastY) -- check for event phase & start, update, or end stroke accordingly if phase == "began" and canvas.isActive then -- empty undone table for i=#undone,1,-1 do display.remove(undone[i]) undone[i] = nil end -- start stroke display.getCurrentStage():setFocus(target, event.id) touchBegan = true strokes[#strokes+1] = display.newGroup() stroke = strokes[#strokes] canvas:insert(stroke) local circle = display.newCircle(stroke, x, y, circleRadius) circle:setFillColor(paintR, paintG, paintB, paintA) target.lastX, target.lastY = x, y elseif phase=="moved" and touchBegan == true and distance \> circleRadius\*.5 then -- append to stroke if segmented then stroke.line = display.newLine(stroke, target.lastX, target.lastY, x, y) local circle = display.newCircle(stroke, x, y, circleRadius) circle:setFillColor(paintR, paintG, paintB, paintA) else if stroke.line == nil then stroke.line = display.newLine(stroke, xStart, yStart, x, y) stroke.circle = display.newCircle(stroke, x, y, circleRadius) stroke.circle:setFillColor(paintR, paintG, paintB, paintA) else stroke.line:append(x, y) stroke.circle.x, stroke.circle.y = x, y end end stroke.line:setStrokeColor(paintR, paintG, paintB, paintA) stroke.line.strokeWidth = strokeWidth target.lastX, target.lastY = x, y -- end elseif (phase == "cancelled" or phase == "ended") and touchBegan == true then -- end stroke display.getCurrentStage():setFocus(nil, event.id) touchBegan = false local circle = display.newCircle(stroke, x, y, circleRadius) circle:setFillColor(paintR, paintG, paintB, paintA) target.lastX, target.lastY = nil, nil return true end end -------------------------------------------------------------------------------- -- ADD TOUCH LISTENER TO CANVAS -------------------------------------------------------------------------------- t1:addEventListener("touch", touch)  

transparent pixel does not fire on begin phase of touch(so it is ok),the problem is that when i begin from visible pixels and move my finger in transparent pixels,it draws on trasparent pixels! how can i solve this?
Thanks

 

Hi @arash45654,

It appears you’re drawing new “strokes” into the “canvas” container. What you should do is mask the entire group which contains the image, then draw strokes into that group.

This should help you:

https://docs.coronalabs.com/guide/media/imageMask/index.html#group-masking

Take care,

Brent

you mean i should remove canvas container and create a displaygroup and insert strokes to this group?
I tested this but no luck

Not exactly… create a new display group (not a container) and then insert your image into it. Then mask the entire group (not just the image). Then apply strokes inside the group (now masked).

Hope this helps,

Brent

I changed it according to your answer but no luck :frowning: , here is the code:

local centerX = display.contentCenterX local centerY = display.contentCenterY local screenTop = display.screenOriginY local screenLeft = display.screenOriginX local screenBottom = display.screenOriginY+display.actualContentHeight local screenRight = display.screenOriginX+display.actualContentWidth local screenWidth = screenRight - screenLeft local screenHeight = screenBottom - screenTop local touchBegan = false local width = screenWidth local height = screenHeight local strokeWidth = 10 local circleRadius = strokeWidth \* .5 local imageGroup=display.newGroup() imageGroup.x=50 imageGroup.y=90 scaleFactor=0.25 local t1= display.newImage( imageGroup,"resources/alef.png",0,0 ) t1:scale( scaleFactor, scaleFactor ) local maskAlefba = graphics.newMask("resources/alefbw.png") imageGroup:setMask( maskAlefba ) imageGroup.strokes = {} local strokes = imageGroup.strokes imageGroup.undone = {} local undone = imageGroup.undone local function touch(event) -- set local variables local phase = event.phase local target = event.target local stroke = strokes[#strokes] local x = event.x - imageGroup.x local y = event.y - imageGroup.y local xStart = event.xStart - imageGroup.x local yStart = event.yStart - imageGroup.y local function getDistance(x1,y1,x2,y2) return math.sqrt((x2 - x1) ^ 2 + (y2 - y1) ^ 2) end if target.lastX == nil then target.lastX, target.lastY = x, y end local distance = getDistance(x, y, target.lastX, target.lastY) -- check for event phase & start, update, or end stroke accordingly if phase == "began" then -- empty undone table for i=#undone,1,-1 do display.remove(undone[i]) undone[i] = nil end -- start stroke display.getCurrentStage():setFocus(target, event.id) touchBegan = true strokes[#strokes+1] = display.newGroup() stroke = strokes[#strokes] imageGroup:insert(stroke) local circle = display.newCircle(stroke, x, y, circleRadius) circle:setFillColor(1, 0,0,1) target.lastX, target.lastY = x, y elseif phase=="moved" and touchBegan == true and distance \> circleRadius\*.5 then if segmented then stroke.line = display.newLine(stroke, target.lastX, target.lastY, x, y) local circle = display.newCircle(stroke, x, y, circleRadius) circle:setFillColor(1, 0, 0, 1) else if stroke.line == nil then stroke.line = display.newLine(stroke, xStart, yStart, x, y) stroke.circle = display.newCircle(stroke, x, y, circleRadius) stroke.circle:setFillColor(1, 0, 0, 1) else stroke.line:append(x, y) stroke.circle.x, stroke.circle.y = x, y end end stroke.line:setStrokeColor(1, 0, 0, 1) stroke.line.strokeWidth = strokeWidth target.lastX, target.lastY = x, y -- end elseif (phase == "cancelled" or phase == "ended") and touchBegan == true then -- end stroke display.getCurrentStage():setFocus(nil, event.id) touchBegan = false local circle = display.newCircle(stroke, x, y, circleRadius) circle:setFillColor(1, 0, 0, 1) target.lastX, target.lastY = nil, nil return true end end -------------------------------------------------------------------------------- -- ADD TOUCH LISTENER TO CANVAS -------------------------------------------------------------------------------- imageGroup:addEventListener("touch", touch) 

I defined imageGroup variable as displaygroup and added image and strokes to it, and masked entire group. 

solved by adding this line after setmask:

imageGroup.maskScaleX = scaleFactor imageGroup.maskScaleY = scaleFactor

Thanks So Much