I would like to implement a simple bitmap font pattern in a Java AWT application. The application uses a Graphics object, where I would like to implement a simple algorithm:
1) Download the file (possibly using ImageIO.read(new File(fileName)) ), which is a 1-bit PNG that looks something like this:

those. it is 16 * 16 (or 16 * a lot if I want to support Unicode) a matrix of 8 * 8 characters. Black corresponds to the background color, white corresponds to the leading edge.
2) Draw lines by character, mixing the corresponding parts of this bitmap with the target Graphics . So far, I have managed to achieve something similar:
int posX = ch % 16; int posY = ch / 16; int fontX = posX * CHAR_WIDTH; int fontY = posY * CHAR_HEIGHT; g.drawImage( font, dx, dy, dx + CHAR_WIDTH, dy + CHAR_HEIGHT, fontX, fontY, fontX + CHAR_WIDTH, fontY + CHAR_HEIGHT, null );
It works, but, alas, it passes the text as it is, i.e. I cannot replace the black-and-white desired color of the foreground and background, and I cannot even make the background transparent.
So, the question arises: is there a simple (and quick!) Way in Java to split part of one single-bit raster image into another by coloring it during the blitting process (i.e. replacing all 0 pixels with one given color and all 1 pixel with another)?
I researched a couple of solutions, they all look suboptimal to me:
- Using custom BufferedImageOp coloring as described in this solution - it should work, but it seems that it would be very inefficient to repaint the bitmap before each bright operation.
- Using multiple 32-bit RGBA PNGs, with the alpha channel set to 0 for black pixels and maximum for the foreground. Each desired foreground color should have its own preliminary rendering of the bitmap. Thus, I can make a transparent background and draw it as a rectangle separately before blitting, and then select one bitmap with my font pre-painted with the desired color and draw part of it above this rectangle. It seems like a huge kink for me - and what makes this option even worse - it limits the number of foreground colors to a relatively small amount (i.e. I can actually load and hold like hundreds or thousands of bitmaps, not millions).
- Combining and loading a custom font, as described in this solution , may work, but as far as I see in Font # createFont , AWT
Font seems to work only with vector fonts, not bitmap fonts.
Maybe there are libraries that implement such functions? Or is it time for me to move on to some more advanced graphics library, something like lwjgl ?
Benchmarking results
I tested a couple of algorithms in a simple test: I have 2 lines, 71 characters each, and drag them one after another, one after another, right in the same place:
for (int i = 0; i < N; i++) { cv.putString(5, 5, STR, Color.RED, Color.BLUE); cv.putString(5, 5, STR2, Color.RED, Color.BLUE); }
Then I measure the time and calculate the speed: line per second and characters per second. So far, the different implementation I tested gives the following results:
- raster font, 16 * 16 characters raster: 10991 lines / sec, 780391 characters / sec
- raster font, pre-divided images: 11048 lines / sec, 784443 characters / sec
- g.drawString (): 8952 lines / second, 635631 characters / second
- color bitmap font colored with LookupOp and ByteLookupTable: 404 lines / second, 28741 characters / second