Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » BITMAP Border

This thread is locked; no one can reply to it. rss feed Print
BITMAP Border
Onewing
Member #6,152
August 2005
avatar

I haven't actually written any code, but the idea is in my head and I though I'd share to get some general feedback. What I want to do is make function like the following:

void draw_border(BITMAP *bImage, BITMAP *bBorder);

This function will draw the bBorder image around the bImage. For example, if this were bBorder:

http://comp.uark.edu/~spsilve/border.JPG

And this were bImage:

http://comp.uark.edu/~spsilve/image.JPG

Then this should be the final output:

http://comp.uark.edu/~spsilve/final.JPG

The purpose of draw_border is to draw a border on what's actually seen. The image above is just a big square, so no problem there. If I were to have a circle, however, that would be a different situation. The border should follow the edges of the circle or polygon or whatever shape it is. Following the edges isn't really that difficult of a question, but what I've been wondering about is the corners. Notice above the border image turns with the picture. I've thought of a few different methods that might work, but I'm curious as to what you think.

My favorite method so far consists of stripping the border image and drawing pieces of it at a time. Like taking the top one-pixel line of the image and drawing that around the entire space and then go to the next part of the border. Since this is going to be a one-time process in the actual program, it's okay if it takes a little time.

Also note that above I used a very simple border. I could use something like a smile face and get some weird results. :)

------------
Solo-Games.org | My Tech Blog: The Digital Helm

Richard Phipps
Member #1,632
November 2001
avatar

I think this is more difficult than it seems if it can follow polygons and curves while keeping the pattern..

Onewing
Member #6,152
August 2005
avatar

Thought it'd be a nice thing for my gui. If it's too complicated, I'll probably just throw it out. :-/

------------
Solo-Games.org | My Tech Blog: The Digital Helm

Hrvoje Ban
Member #4,537
April 2004
avatar

Nevermind, I missunderstand question...

Indeterminatus
Member #737
November 2000
avatar

Quote:

I think this is more difficult than it seems if it can follow polygons and curves while keeping the pattern..

That could be simplified by adding the restriction of a one-pixel-width border image, so there'd be no "real" pattern to keep.

_______________________________
Indeterminatus. [Atomic Butcher]
si tacuisses, philosophus mansisses

Ceagon Xylas
Member #5,495
February 2005
avatar

Exactly right, Indeterminatus.
You also couldn't have very dramatic curves in your circle or polygon =/
Otherwise you'll get reaaaally werid looking borders

Tobias Dammers
Member #2,604
August 2002
avatar

I guess a generalized approach would be:
1) Vectorize the shape into a polygon.
2) For each edge, create a parallel line.
3) Find the intersection points of two adjacent parallels.
4) You have now vectorized the outline; render it as quads, with appropriate texture coords (s as running variable, increment by edge length per vertex; t as 0 on the original outline and as 1 on the shifted one).

The math involved in step 3 can be a bit tricky though, and you cannot use arbitrary shapes with arbitrary borders.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

GullRaDriel
Member #3,861
September 2003
avatar

a simple way:

use only one line of pixel gradient,

and (pseudo code):

1int it; /* should i say that's just an ... iterator ? */
2 
3/* admitting that your border is 20 pixel width */
4int gradline[20];
5 
6/* fill it here with the color of your choice , i'm just making an example*/
7 
8for( it = 0 ; it < 5 , it ++ )
9gradline[it] = makecol( 100 , 0 , 0 );
10 
11for( it = 5 ; it < 10 , it ++ )
12gradline[it] = makecol( 150 , 0 , 0 );
13 
14for( it = 10 ; it < 15 , it ++ )
15gradline[it] = makecol( 200 , 0 , 0 );
16 
17for( it = 15 ; it < 20 , it ++ )
18gradline[it] = makecol( 255 , 0 , 0 );
19 
20 
21/* draw each border */
22
23for( it = 0; it < 20 ; it ++ )
24rect( dest_bitmap , it , it , dest_bitmap -> w - it , dest_bitmap -> h - it , gradline[20]);

Note that it's only working for what you need.

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Onewing
Member #6,152
August 2005
avatar

Quote:

That could be simplified by adding the restriction of a one-pixel-width border image, so there'd be no "real" pattern to keep.

Yeah, I was thinking I might have to do that due to my limited knowledge. For simple borders above, that'd work fine, since the border is too complex. It would be nice to have different patterns though. Of course, most borders don't have patterns...

Quote:

You also couldn't have very dramatic curves in your circle or polygon =/
Otherwise you'll get reaaaally werid looking borders

The corners and curves are giving me some complications. I haven't tried to code anything yet, so I don't know how difficult it will be.

Quote:

I guess a generalized approach would be:
1) Vectorize the shape into a polygon.
2) For each edge, create a parallel line.
3) Find the intersection points of two adjacent parallels.
4) You have now vectorized the outline; render it as quads, with appropriate texture coords (s as running variable, increment by edge length per vertex; t as 0 on the original outline and as 1 on the shifted one).

This sounds most like what I had in my head, especially number 2. However, you kind of lost me on number 4, I'll have to take a closer look.

Quote:

a simple way:

Nothing wrong with simple. Even if I limit the borders to be pattern-less and only 1-pixel-width wide, you'd still be able to create a multitude of borders for simple, rectangular shapes. Thanks.

------------
Solo-Games.org | My Tech Blog: The Digital Helm

Fladimir da Gorf
Member #1,565
October 2001
avatar

In OpenLayer 2.0, you could make that textured border pretty simply: ;)

- First retrieve the collision Shape for the image object
- Then convert from Shape to LineStrip
- Select the texture of the LineStrip
- Render the LineStrip and the image

Actually the code does then exactly what Tobias suggested...

OpenLayer has reached a random SVN version number ;) | Online manual | Installation video!| MSVC projects now possible with cmake | Now alvailable as a Dev-C++ Devpack! (Thanks to Kotori)

Hrvoje Ban
Member #4,537
April 2004
avatar

I'll made this two days ago, but didn't have change to post it till now:

1#include <allegro.h>
2 
3int border_color;
4 
5unsigned long border_blender15(unsigned long, unsigned long, unsigned long)
6{
7 return makecol15(getr(border_color), getg(border_color), getb(border_color));
8}
9 
10unsigned long border_blender16(unsigned long, unsigned long, unsigned long)
11{
12 return makecol16(getr(border_color), getg(border_color), getb(border_color));
13}
14 
15unsigned long border_blender24(unsigned long, unsigned long, unsigned long)
16{
17 return makecol32(getr(border_color), getg(border_color), getb(border_color));
18}
19 
20void draw_sprite_border(BITMAP *src, BITMAP *dest, int x, int y, int b_w, int b_c, int colors[])
21{
22 int i;
23 BITMAP *tmp;
24 
25 tmp = create_bitmap(src->w + b_w * b_c * 2, src->h + b_w * b_c * 2);
26 
27 if (!tmp)
28 return;
29 
30 set_blender_mode(border_blender15, border_blender16, border_blender24, 0, 0, 0, 0);
31 
32 for (i = 0; i < b_c; ++i)
33 {
34 
35 clear_to_color(tmp, makecol(255, 0, 255));
36 stretch_sprite(tmp, src, b_w * i, b_w * i, tmp->w - b_w * i * 2, tmp->h - b_w * i * 2);
37 border_color = colors<i>;
38 draw_trans_sprite(dest, tmp, x, y);
39 }
40 
41 draw_sprite(dest, src, x + b_w * b_c, y + b_w * b_c);
42 destroy_bitmap(tmp);
43}

First custom blender is set which for each pixel drawn with draw_trans/lit_sprite returns global_color. Then for each border, image is stretched into temporary and drawn into destination. This is when custom blender kicks in and draws entire image as solid color. This is repeated for every border except image is stretched less and less. Finally original image is drawn.

It has two problems: It looks ugly and borders are drawn tiner as lines get more angled (see attached image, red primitive is default image).

Onewing
Member #6,152
August 2005
avatar

Cool! Although, at first glance, I haven't quite figured out how it works. :-/ Is b_w "border width" and b_c "border color"? Also, is src the bitmap border to be applied to the picture?

Quote:

It has two problems: It looks ugly and borders are drawn tiner as lines get more angled (see attached image, red primitive is default image).

Looks pretty good to me! I'll mess around with it when I get home and let you know if I have any other problems. :)

------------
Solo-Games.org | My Tech Blog: The Digital Helm

Hrvoje Ban
Member #4,537
April 2004
avatar

src is bitmap which should be bordered (not modified)
dest is bitmap on which src + borders are drawn
b_w is single border width
b_c is number of borders (count)
colors is simple a array of ints created my makecol*() (number of colors == b_c)

Working is quite simple: When draw_trans_sprite/draw_lit_sprite are used they call special blender functions for each pixel they are about to draw (see Truecolor transparency). When my blenders are use they simple return current border color for every pixel.
When drawing border I stretch source bitmap into temporary so it has size as current border and then I draw it with draw_trans_sprite which draws that stretched sprite in one color (blenders). I repeat this for all borders.

Fladimir da Gorf
Member #1,565
October 2001
avatar

However, that can't do textured borders, but only solid color ones... (Though you could render several solid color borders to get the effect like in the screenshot)

OpenLayer has reached a random SVN version number ;) | Online manual | Installation video!| MSVC projects now possible with cmake | Now alvailable as a Dev-C++ Devpack! (Thanks to Kotori)

Go to: