outline

BlitzMax Forums/OpenGL Module/outline

Bremer(Posted 2008) [#1]
How would you add an outline to an 2d image in openGL? Lets say that I load the picture shown below and create a quad which uses this as its texture. Is there a way to make an even outline?

I tried just upscaling it and drawing it all black, then set the scale to 1 again and draw the image on top, but that doesn't work.




fredborg(Posted 2008) [#2]
this should work:
Function DrawImageOutline(img:TImage,x:Float,y:Float,thickness:Int=1)
	
	Local r:Int,g:Int,b:Int
	GetColor(r,g,b)
	SetColor(0,0,0)
	For Local dx:Int = -thickness To thickness
		For Local dy:Int = -thickness To thickness
			DrawImage(img,x+dx,y+dy)
		Next
	Next
	SetColor(r,g,b)
	DrawImage(img,x,y)

EndFunction
Although it isn't OpenGL specific, you can do the same..


Dreamora(Posted 2008) [#3]
The simplest way for an outline is doing it in the graphics application. It will take less performance as well then adding 1+ new quads for a "line".


fredborg(Posted 2008) [#4]
Maybe he's doing an app that can add the outline automatically :)


Bremer(Posted 2008) [#5]
@fredborg, I don't know why I didn't think of that solution, I am sure that I have used similar before. Ofcause it solves the problem, but it would have been nice, if there were a way to do it without having to draw the image so many times.

@Dreamora, It can be done in a graphics application, but if its needed for an editor of sorts, where the user manipulates the output directly, then that won't help. I should have mentioned that ofcause.


ImaginaryHuman(Posted 2008) [#6]
You can `jitter` the drawing. Draw the image four or eight times in black at the same coords except -1,0 then 1,0 then 0,-1 then 0,1 (add these to the normal coords).

If you want to do it 8 times, also draw it at -1,-1, -1,1, 1,-1 and 1,1 to cover the diagonals.

This will put a 1-pixel border around it. Then draw the regular image on top.


Bremer(Posted 2008) [#7]
@ImaginaryHuman, thats what fredborgs function does, isn't it?

@fredborg, thats correct, I need this for my own application and need it to be changeable in realtime.


Dreamora(Posted 2008) [#8]
In that case I would suggest implementing a a small little edge detection by running a matrix filter operation.

not tested code for it would be
' assuming pix holds the pixmap
' assuming that maskColor holds the ARGB value of the "to cut color"
' assuming borderColor holds the color for the border / outline
local pw:int = pixmapwidth(pix) - 1
local ph:int = pixmapheight(pix) - 1
for local x:int = 0 to pw
 for local y:int = 0 to ph
   local pixel:int = 0
   
   for local i:int = max(x-radius,0) to min(x+radius, pw)
    for local j:int = max(y-radius,0) to min(y+radius, ph)
     pixel :+ readpixel(pix,x+i, y+j)
    next
   next
   pixel :/ int(radius*radius)
   if( pixel <> maskColor )
    writepixel(pix, x, y, borderColor)
   else
    writepixel(pix, x, y, maskColor)
   endif
 next
next


this uses a square combination ... you could reduce it to do it only if i + j <= radius so you get a "rounder" shape that collects the data for the outline.

There are other, quite optimized algorithms for that, so having a look at those might actually be an idea if it is too slow :)


ImaginaryHuman(Posted 2008) [#9]
Oh yea, doh, I didn't notice the nested loop.


ImaginaryHuman(Posted 2008) [#10]
Since your symbol more or less looks like it could be vector art, why not construct it out of triangles, draw it, and then draw a wireframe outline?


Bremer(Posted 2008) [#11]
It was for a bitmap image manipulation effect, the ankh was just something I had lying around that was simple.