How to simulate Canvas:setPixel?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
Ref
Party member
Posts: 702
Joined: Wed May 02, 2012 11:05 pm

How to simulate Canvas:setPixel?

Post by Ref »

Have created a flood-fill algorithm for Lua but have trouble converting it to Love.

We have Canvas:getPixel(x,y) but no Canvas:setPixel(x,y,color).

Anyone have a way to set a pixel on a canvas?

love.graphics.point(x,y) only works on the Love's main window (not on a canvas?) and can't use drawing primitives on userdata so can't create boundaries for the fill.
love.graphics.circle only seems to work if radius is >1.

Just overlooking something here.
User avatar
s-ol
Party member
Posts: 1077
Joined: Mon Sep 15, 2014 7:41 pm
Location: Cologne, Germany
Contact:

Re: How to simulate Canvas:setPixel?

Post by s-ol »

Did you try drawing a line (x, y, x, y)?

s-ol.nu /blog  -  p.s-ol.be /st8.lua  -  g.s-ol.be /gtglg /curcur

Code: Select all

print( type(love) )
if false then
  baby:hurt(me)
end
User avatar
Ref
Party member
Posts: 702
Joined: Wed May 02, 2012 11:05 pm

Re: How to simulate Canvas:setPixel?

Post by Ref »

S0lll0s wrote:Did you try drawing a line (x, y, x, y)?
Yes, didn't work.
User avatar
veethree
Inner party member
Posts: 875
Joined: Sat Dec 10, 2011 7:18 pm

Re: How to simulate Canvas:setPixel?

Post by veethree »

imagedata has setPixel, Can you use that instead of a canvas? or creating a 1x1 imagedata and drawing that to the canvas perhaps?
User avatar
arampl
Party member
Posts: 248
Joined: Mon Oct 20, 2014 3:26 pm

Re: How to simulate Canvas:setPixel?

Post by arampl »

Ref wrote:Have created a flood-fill algorithm for Lua
Haha funny! And I'm too made this one literally 2 days ago. Just for fun. Also only with canvases. Spent half-day on that damn thing. Already written it 20 years ago in Z80 assembly lang and forgot how it was done. Started with recursion then realised that in Lua it is even not needed for this.
You can even take pixels from image from same coordinates and get "texture fill".

Oh. Wait. Correction, I've used ImageData, as veethree proposed.

Code (non optimized of course):

Code: Select all

function love.load()
	fill_canvas = love.graphics.newCanvas(100, 100)

	love.graphics.setCanvas(fill_canvas)
	fill_canvas:clear()
	love.graphics.setColor(255, 255, 0)
	love.graphics.circle("line", 50, 50, 20)
	love.graphics.setCanvas()

	fillimage = love.graphics.newImage(fill_canvas:getImageData())
end

function fill(image, x, y, red, green, blue)
	if black[1] == nil then
		adj = {-1, 0, 1, 0, -1, -1, 0, -1, 1, -1, -1, 1, 0, 1, 1, 1}
		pixels = image:getData()
		black[#black + 1] = {}
		black[#black].x = x
		black[#black].y = y
	end
	while #black > 0 do
		x = black[1].x; y = black[1].y
		table.remove(black, 1)
		pixels:setPixel(x, y, red, green, blue, 255)
		for i = 1, #adj, 2 do
-- instead of 100's should be variables, size of image
			if x + adj[i] > 0 and x + adj[i] < 100 and y + adj[i + 1] > 0 and y + adj[i + 1] < 100 then
				r, g, b, a = pixels:getPixel(x + adj[i], y + adj[i + 1])
				if (r == 0 and g == 0 and b == 0) then
					pixels:setPixel(x + adj[i], y + adj[i + 1], red, green, blue, 255)
					black[#black + 1] = {}
					black[#black].x = x + adj[i]
					black[#black].y = y + adj[i + 1]
				end
			end
		end
--	fill(image, x, y)
	end
end

function love.draw()
	black = {}
	fill(fillimage, 5, 5, 255, 0, 0)
	fill(fillimage, 50, 50, 255, 255, 0)
	fillimage = love.graphics.newImage(pixels)
	love.graphics.draw(fillimage, 200, 200)
end
Maybe shaders can do flood fill. Checking for neighboring texels' colors...
User avatar
slime
Solid Snayke
Posts: 3132
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: How to simulate Canvas:setPixel?

Post by slime »

You should use Image:refresh instead of creating a whole new image every frame.
User avatar
arampl
Party member
Posts: 248
Joined: Mon Oct 20, 2014 3:26 pm

Re: How to simulate Canvas:setPixel?

Post by arampl »

Oh. Thanks! Useful to know.
User avatar
Ref
Party member
Posts: 702
Joined: Wed May 02, 2012 11:05 pm

Re: How to simulate Canvas:setPixel?

Post by Ref »

Thanks veethree for the suggestion of using imagedata.

Finally got my flood fill to sort of work - lots of patched code.
Found that Love's primitives leak unless border line width is set to 2.
Surprised that the fill routine is actually fairly fast (don't know what I'm going to use it for!)

See that arampl's code fell into the same trap I did. Changing the color in his 'fill' didn't change the color used because love.graphics.setColor wasn't set to white.

Beware, demo code provided uses a canvas.
Attachments
floodfill.love
Simple flood-fill algorithm
(1.31 KiB) Downloaded 87 times
User avatar
arampl
Party member
Posts: 248
Joined: Mon Oct 20, 2014 3:26 pm

Re: How to simulate Canvas:setPixel?

Post by arampl »

Ref wrote:don't know what I'm going to use it for!
For one thing it is surely needed - if you want to do image retouching. Load raster image created elsewhere. Non-vector graphics oriented editor.
User avatar
ArchAngel075
Party member
Posts: 319
Joined: Mon Jun 24, 2013 5:16 am

Re: How to simulate Canvas:setPixel?

Post by ArchAngel075 »

flood fill can be useful actually, i do recall needing such a function for template tiles.
ie tile is only white, you can then use code to color parts of tiled (parts specified in a ini or something) and then draw large amounts of variations thanks to such a function.

I have a error to report though,

Reproduction :
flood the entire screen (not the starting shape, but whats around it)
Then hold Rmouse-button and slide over the inner shapes from outside.

Error : main.lua 41
Bad argument #1 to 'draw' (Drawable expected, got nil)
Traceback :
[C] 'draw'
main 41 'draw'
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 205 guests