outline

BlitzMax Forums/BlitzMax OpenGL Programming/outline

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.



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..

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".

Maybe he's doing an app that can add the outline automatically :)

@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.

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.

@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.

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 :)

Oh yea, doh, I didn't notice the nested loop.

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?

It was for a bitmap image manipulation effect, the ankh was just something I had lying around that was simple.