JavaAWTベースのアプリケーションで単純なビットマップフォントの描画を実装したいと思います。アプリケーションはGraphics
、単純なアルゴリズムを実装したいオブジェクトを描画します。
1)ファイルをロードします(おそらくを使用してImageIO.read(new File(fileName))
)。これは、次のような1ビットのPNGです。
つまり、8*8文字の16*16(Unicodeをサポートしたい場合は16 *多く)のマトリックスです。黒は背景色に対応し、白は前景色に対応します。
2)文字列を文字ごとに描画し、このビットマップの関連部分をターゲットにブリットしますGraphics
。これまでのところ、私はそのようなものでしか成功していません:
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
);
それは機能しますが、残念ながら、テキストをそのままブリットします。つまり、白黒を希望の前景色と背景色に置き換えることはできず、背景を透明にすることさえできません。
したがって、問題は次のとおりです。Javaには、1ビットビットビットの一部を別のビットビットにブリットし、ブリッティングの過程で色付けする(つまり、すべての0ピクセルを1つの特定の色とすべての1ピクセルに置き換える)簡単な(そして高速な)方法がありますか?他のと)?
私はいくつかの解決策を研究しましたが、それらはすべて私には最適ではないように見えます:
- このソリューションで概説されているように、カスタムカラー化BufferedImageOpを使用すると、機能するはずですが、すべてのブリット操作の前にビットマップを再カラー化することは非常に非効率的であるようです。
- 複数の32ビットRGBAPNGを使用し、アルファチャネルを黒ピクセルの場合は0に、前景の場合は最大に設定します。必要なすべての前景色は、独自の事前レンダリングされたビットマップを取得する必要があります。このようにして、背景を透明にし、ブリットする前に長方形として個別に描画し、フォントで1つのビットマップを選択し、目的の色で事前に色付けして、その長方形の上にその一部を描画できます。私には大きなやり過ぎのように思えます-そしてこのオプションをさらに悪化させるのは-それは前景色の数を比較的少量に制限します(つまり、数百万ではなく数百または数千のビットマップのように現実的にロードして保持できます)
- このソリューションで概説されているように、カスタムフォントのバンドルとロードは機能しますが、 Font#createFontのドキュメントで確認できる限り、AWT
Font
はベクターベースのフォントでのみ機能し、ビットマップベースでは機能しないようです。
そのような機能を実装するライブラリはすでにあるのでしょうか?または、 lwjglのようなより高度なグラフィックライブラリに切り替える時が来ましたか?
ベンチマーク結果
簡単なテストでいくつかのアルゴリズムをテストしました。2つの文字列(それぞれ71文字)があり、同じ場所に次々と連続して描画します。
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);
}
次に、かかった時間を測定し、速度を計算します。1秒あたりの文字数と1秒あたりの文字数です。これまでにテストしたさまざまな実装により、次の結果が得られます。
- ビットマップフォント、16 * 16文字ビットマップ:10991文字列/秒、780391文字/秒
- ビットマップフォント、分割前の画像:11048文字列/秒、784443文字/秒
- g.drawString():8952文字列/秒、635631文字/秒
- LookupOpおよびByteLookupTableを使用して色付けされた色付きビットマップフォント:404文字列/秒、28741文字/秒