Я хотел бы реализовать простой рисунок растрового шрифта в приложении на базе Java AWT.Приложение рисует объект Graphics
, где я хотел бы реализовать простой алгоритм:
1) Загрузить файл (возможно, с использованием ImageIO.read(new File(fileName))
), который представляет собой 1-битный PNG, который выглядит примерно так:
Т.е. это 16 * 16 (или 16 * много, если я бы хотел поддерживать Unicode) матрица из 8 * 8 символов.Черный соответствует цвету фона, белый соответствует переднему плану.
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 пикселей другим)?
Я исследовал пару решений, все они выглядят неоптимальными для меня:
- Используя пользовательскую раскраску BufferedImageOp , как указано в , это решение - оно должно работать, но кажется, что было бы очень неэффективно перекрашивать растровое изображение перед каждой блит-операцией.
- Использование нескольких 32-битных RGBA PNG с альфа-каналом, установленным на 0 для черных пикселей и на максимум для переднего плана.Каждый желаемый цвет переднего плана должен получить свое собственное предварительно обработанное растровое изображение.Таким образом, я могу сделать фон прозрачным и нарисовать его в виде прямоугольника отдельно, а затем выбрать одно растровое изображение с моим шрифтом, предварительно раскрасить нужным цветом и нарисовать его часть над этим прямоугольником.Мне кажется, это излишнее излишнее - и что делает эту опцию еще хуже - она ограничивает количество цветов переднего плана относительно небольшим количеством (т.е. я могу реально загружать и хранить как сотни или тысячи растровых изображений, а не миллионы)
- Объединение и загрузка пользовательского шрифта, как описано в , это решение может работать, но, насколько я вижу в документации 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);
}
Затем я измеряю время и вычисляю скорость: строка в секунду и количество символов ввторой.До сих пор различные реализации, которые я тестировал, дают следующие результаты:
- растровый шрифт, 16 * 16 символов растрового изображения: 10991 строк / с, 780391 символов / с
- растрового шрифта,предварительно разделенные изображения: 11048 строк / с, 784443 символа / с
- g.drawString (): 8952 строки / с, 635631 символа / с
- цветной растровый шрифт, раскрашенный с использованием LookupOp и ByteLookupTable: 404 строки / сек, 28741 символ / сек