Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (580)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1] 2
  ignore  |  Print  
  Java2D drawing colored bitmap fonts  (Read 3662 times)
0 Members and 1 Guest are viewing this topic.
Offline joeyismusic

Junior Member





« Posted 2012-04-25 14:47:24 »

I couldn't come up with a more elegant way of drawing any color font from a single bitmap (png) font loaded in memory.

The only way I could get it to work was to render everything into a buffered image, which is then modified at pixel level by the font drawing.

The only other way I can think of how to do this would be to create the buffered image, then steal its array, and have to do my own pixel copying / color operations from there on instead of using drawImage calls... But I'd really like to avoid going that far if I could!

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
public final class Font {

   private static int trans = 16777215;

   public static final int w = 8;
   public static final int h = 8;
   
   public static void printString(BufferedImage bimg, String string, int x, int y, int width, int color, int bgcolor) {
      int px = 0;
      int py = 0;
      char c;
      int sx;
      int sy;
      int pixel_x = 0;
      int pixel_y = 0;
      int ix = 0;
      int iy = 0;
      int i = 0;
      int src_color = 0;
     
      for(i = 0; i < string.length(); i++) {
         c = string.charAt(i);
         if(c == 32) {
            px += w * 2;
            if(px / (w * 2) > width) {
               px = 0;
               py += h * 2;
            }
            continue;
         }
         sx = c;
         sy = 0;
         while(sx > 15) {
            sx -= 16;
            sy++;
         }
         sx *= w;
         sy *= h;
         for(ix = 0; ix < w; ix++) {
            for(iy = 0; iy < h; iy++) {
               src_color = Art.font.getRGB(sx + ix, sy + iy);
               if(src_color != trans) {
                  pixel_x = x + px + (ix * 2);
                  pixel_y = y + py + (iy * 2);
                  if(pixel_x >= 0 && pixel_x + 2 < Game.WIDTH && pixel_y >= 0 && pixel_y + 2 < Game.HEIGHT) {
                     bimg.setRGB(pixel_x + 1, pixel_y + 1, bgcolor);
                     bimg.setRGB(pixel_x + 2, pixel_y + 2, bgcolor);
                     bimg.setRGB(pixel_x + 2, pixel_y + 1, bgcolor);
                     bimg.setRGB(pixel_x + 1, pixel_y + 2, bgcolor);
                  }
                  if(pixel_x >= 0 && pixel_x + 1 < Game.WIDTH && pixel_y >= 0 && pixel_y + 1 < Game.HEIGHT) {
                     bimg.setRGB(pixel_x + 0, pixel_y + 0, color);
                     bimg.setRGB(pixel_x + 1, pixel_y + 1, color);
                     bimg.setRGB(pixel_x + 1, pixel_y + 0, color);
                     bimg.setRGB(pixel_x + 0, pixel_y + 1, color);
                  }
               }
            }
         }
         px += w * 2;
         if(px / (w * 2) > width) {
            px = 0;
            py += h * 2;
         }
      }
   }
}
Offline Tom-Todd

Senior Newbie





« Reply #1 - Posted 2012-04-25 20:50:03 »

I'd be tempted to take a look at Notch's code for Prelude of the Chambered, pretty sure he did it in there... in particular I'd look at the Art and Bitmap classes... think that's where it's handled.
Offline joeyismusic

Junior Member





« Reply #2 - Posted 2012-04-25 23:02:59 »

Hmm. I'll have a look. I am pretty sure he's just modifying the int's in the array, which sucks because I'd have to write a lot of new rendering code.

I guess I don't have too much to worry about. If I fill the screen with as many characters as it can possibly show, it goes from 60 fps to 47 fps. Any other normal text display doesn't phase it.

Looking forward to any other contributions anyone else might have to this topic. Thanks.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #3 - Posted 2012-04-26 05:30:53 »

Wait, you want to copy a portion of a BufferedImage into another BufferedImage right?

1  
2  
3  
4  
5  
BufferedImage destination = ....
Graphics g = destination.getGraphics();

//(dx1,dy1) = destination top left, (dx2,dy2) destination bottom right, (sx1,sy1) = source top left, (sx2,sy2) = source bottom right
g.drawImage(fontImage,dx1,dy1,dx2,dy2,sx1,sy1,sx2,sy2,null);


To draw it a certain color, you use AlphaComposite to blend a color with the font image.

Offline joeyismusic

Junior Member





« Reply #4 - Posted 2012-04-26 05:44:05 »

i have an image of a font my artist drew. its black and transparent

wherever there is a black pixel, i want to put a color of my choice in place of where that black pixel would go
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #5 - Posted 2012-04-26 07:21:13 »

Make the font white, draw it, then use AlphaComposite.SRC_IN to draw a colored rectangle above it.

Offline joeyismusic

Junior Member





« Reply #6 - Posted 2012-04-26 17:50:41 »

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
   public static void test(Graphics2D g, String string, int x, int y, int cwidth, int color, int bgcolor) {
      int px = 0;
      int py = 0;
      char c;
      int sx;
      int sy;
      int pixel_x = 0;
      int pixel_y = 0;
      int ix = 0;
      int iy = 0;
      int i = 0;
      int src_color = 0;
     
      for(i = 0; i < string.length(); i++) {
         c = string.charAt(i);
         if(c == 32) {
            px += w * 2;
            if(px / (w * 2) > cwidth) {
               px = 0;
               py += h * 2;
            }
            continue;
         }
         sx = c;
         sy = 0;
         while(sx > 15) {
            sx -= 16;
            sy++;
         }
         sx *= w;
         sy *= h;
         
         pixel_x = x + px;
         pixel_y = y + py;
         
         g.drawImage(Art.font_white, pixel_x, pixel_y, pixel_x + w * 2, pixel_y + h * 2, sx, sy, sx + w, sy + h, null);
         
         
         px += w * 2;
         if(px / (w * 2) > cwidth) {
            px = 0;
            py += h * 2;
         }
      }
     
      Composite comp = g.getComposite();
     
      g.setComposite(AlphaComposite.SrcIn);
      g.setColor(Color.red);
      g.fillRect(x, y, cwidth * 16, 32);
      g.setComposite(comp);
   }




What am I doing wrong?

Here's what happens if I comment out the composite / fillrect section

Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #7 - Posted 2012-04-26 23:40:20 »

You're supposed to set the Composite before you draw the rect Tongue

Also, make sure you reset the AlphaComposite to what it was previously after drawing the rect.

Offline joeyismusic

Junior Member





« Reply #8 - Posted 2012-04-27 03:03:09 »

did you read my code? because i did that.
Offline joeyismusic

Junior Member





« Reply #9 - Posted 2012-04-27 03:20:30 »

You're supposed to set the Composite before you draw the rect Tongue

Also, make sure you reset the AlphaComposite to what it was previously after drawing the rect.
Oh wait, you're assuming that I'm rendering text to a image which gets drawn to another image, I think... which would explain why none of this is working because I'm just drawing the text (bitmapped font) directly onto the canvas.

So I'm guessing this would work if I was using a BufferedImage just for text rendering, clearing it to black every frame (Huh) and then using alpha composite to draw that to the canvas.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #10 - Posted 2012-04-27 03:23:24 »

:O I must be going blind, I swear I saw you setting the AlphaComposite after the fillRect XD

Anyway, according to the description of SRC_IN, only the overlapping source pixels are left.

And I just realized that you are drawing the text directly onto the screen right? There are already pixels there Tongue

You need to draw onto a blank and transparent BufferedImage, then use the composite Smiley

EDIT: haha, you just posted the same thing Roll Eyes

EDIT2: no, you simply need to clear the BufferedImage, draw the text, then draw the colored rect using the composite. After that, simply draw that image onto the screen.

Offline joeyismusic

Junior Member





« Reply #11 - Posted 2012-04-27 03:26:40 »

How do I clear the BufferedImage back to transparent each frame, to prevent dirty-ness Cheesy
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #12 - Posted 2012-04-27 03:31:47 »

g.setComposite(AlphaComposite.CLEAR);
g.setColor(new Color(0,0,0,0));
g.fillRect(0,0,width,height);

Offline joeyismusic

Junior Member





« Reply #13 - Posted 2012-04-27 03:40:54 »

oh my god it works

:evil laugh:
Offline joeyismusic

Junior Member





« Reply #14 - Posted 2012-04-27 03:44:33 »

BLAH! its not any faster than setRGB
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #15 - Posted 2012-04-27 04:07:27 »

Try to reuse objects. This should be faster since you're not un-managing the BufferedImage.

Offline joeyismusic

Junior Member





« Reply #16 - Posted 2012-04-27 04:35:43 »

I read that setRGB doesn't unmanage the BufferedImage
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #17 - Posted 2012-04-27 04:51:23 »

O_o last time I checked, it should.

Offline joeyismusic

Junior Member





« Reply #18 - Posted 2012-04-27 05:02:31 »

I get 47 FPS @ rendering 1872 characters (the most that will fit on the screen, at once) with both methods (setRGB, and the AlphaComposite)

I'm not recreating BufferedImages every frame or anything like that, so when you say re-use objects I'm not sure what you mean. I am already re-using objects.
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #19 - Posted 2012-04-27 05:40:16 »

Hmm, well I would stick with the AlphaComposite way, but it really should be a bit faster. Oh well Smiley

Offline joeyismusic

Junior Member





« Reply #20 - Posted 2012-04-27 05:45:36 »

Would it be stupid to keep switching the composite mode for each character being drawn, so the color rect that goes over it EXACTLY fits each letter drawn?
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #21 - Posted 2012-04-27 05:48:32 »

How would it be any different from drawing 1 rect? Yes, it would be Smiley

Offline joeyismusic

Junior Member





« Reply #22 - Posted 2012-04-27 05:49:45 »

There's no way to get a single rect to fit the shape of the text exactly if there's a line wrap.
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #23 - Posted 2012-04-27 05:54:25 »

Then stretch the rect to the entire BufferedImage, or calculate the wrap.

Offline joeyismusic

Junior Member





« Reply #24 - Posted 2012-04-27 05:56:55 »

the stretch method won't allow multiple colors?
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #25 - Posted 2012-04-27 06:08:00 »

Draw the letters, set the Composite, set the Color, fill the entire image, draw the image to the screen, clear the image. Repeat Smiley

Offline joeyismusic

Junior Member





« Reply #26 - Posted 2012-04-27 06:11:01 »

oh are you saying to do all of that within one frame, per text && text_color?

so if i wanna draw something in red, then something in orange, i'm "drawing the letters, setting the composite, setting the color, filling the image, drawing the image, clearing the image" once for red, and once again for orange (all in the same rendering frame)
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #27 - Posted 2012-04-27 06:18:25 »

Well if you want to draw multiple colors at time, you will have to know the X, Y, width and height of each letter draw, which you already should know. So you can do it all at one time.

1  
2  
3  
4  
5  
6  
7  
8  
public void drawString(....) {
   for(each letter) {
       //figure out X, Y, width and height of letter
      //draw the letter
     
       //set composite, draw colored rect (X,Y,width,height) , reset composite
  }
}

Offline joeyismusic

Junior Member





« Reply #28 - Posted 2012-04-27 06:28:40 »

er...
Offline joeyismusic

Junior Member





« Reply #29 - Posted 2012-04-27 07:00:00 »

Perhaps I did not explain my example very well...

Let's say I want to draw a string of information in red, and then later (somewhere else, in some other class or on some other GUI window) in a completely separate function call, I want to draw a string of information in orange.
Pages: [1] 2
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (51 views)
2014-04-15 18:08:23

BurntPizza (47 views)
2014-04-15 03:46:01

UprightPath (63 views)
2014-04-14 17:39:50

UprightPath (45 views)
2014-04-14 17:35:47

Porlus (62 views)
2014-04-14 15:48:38

tom_mai78101 (86 views)
2014-04-10 04:04:31

BurntPizza (144 views)
2014-04-08 23:06:04

tom_mai78101 (243 views)
2014-04-05 13:34:39

trollwarrior1 (202 views)
2014-04-04 12:06:45

CJLetsGame (209 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!