Перейти к основному содержимому

Добавление текста к изображению в Java

· 5 мин. чтения

1. Обзор

Иногда нам нужно добавить текст к изображению или набору изображений. Сделать это вручную легко с помощью инструмента для редактирования изображений. Но когда мы хотим одинаковым образом добавить один и тот же текст на значительное количество картинок, было бы очень полезно сделать это программно.

В этом кратком руководстве мы узнаем , как добавить текст к изображениям с помощью Java.

2. Добавление текста к изображению

Чтобы прочитать изображение и добавить текст, мы можем использовать разные классы. В последующих разделах мы увидим несколько вариантов.

2.1. ImagePlus и ImageProcessor

Для начала посмотрим, как использовать классы ImagePlus и ImageProcessor , доступные в библиотеке ImageJ . Чтобы использовать эту библиотеку, нам нужно включить эту зависимость в наш проект:

<dependency>
<groupId>net.imagej</groupId>
<artifactId>ij</artifactId>
<version>1.51h</version>
</dependency>

Чтобы прочитать изображение, мы будем использовать статический метод openImage . Результат этого метода будет сохранен в памяти с помощью объекта ImagePlus :

ImagePlus image = IJ.openImage(path);

Как только мы загрузили изображение в память, давайте добавим к нему текст, используя класс ImageProcessor :

Font font = new Font("Arial", Font.BOLD, 18);

ImageProcessor ip = image.getProcessor();
ip.setColor(Color.GREEN);
ip.setFont(font);
ip.drawString(text, 0, 20);

С помощью этого кода мы добавляем указанный текст зеленым цветом в левом верхнем углу изображения. Обратите внимание, что мы устанавливаем позицию, используя второй и третий аргументы метода drawString , которые представляют количество пикселей слева и сверху соответственно.

2.2. Буферизованное изображение и графика

Далее мы увидим , как можно добиться того же результата, используя классы BufferedImage и Graphics . Стандартная сборка Java включает эти классы, поэтому дополнительные библиотеки не нужны.

Точно так же, как мы использовали openImage для ImageJ , мы собираемся использовать метод чтения , доступный в ImageIO :

BufferedImage image = ImageIO.read(new File(path));

Как только мы загрузили изображение в память, давайте добавим к нему текст, используя класс Graphics :

Font font = new Font("Arial", Font.BOLD, 18);

Graphics g = image.getGraphics();
g.setFont(font);
g.setColor(Color.GREEN);
g.drawString(text, 0, 20);

Как мы видим, обе альтернативы очень похожи в том, как они используются. В этом случае второй и третий аргументы метода drawString указываются так же, как мы это сделали для метода ImageProcessor .

2.3. Рисование на основе AttributedCharacterIterator

Метод drawString, доступный в Graphics , позволяет нам печатать текст с помощью AttributedCharacterIterator . Это означает, что вместо использования простой строки мы могли бы использовать текст с некоторыми связанными свойствами. Давайте посмотрим пример:

Font font = new Font("Arial", Font.BOLD, 18);

AttributedString attributedText = new AttributedString(text);
attributedText.addAttribute(TextAttribute.FONT, font);
attributedText.addAttribute(TextAttribute.FOREGROUND, Color.GREEN);

Graphics g = image.getGraphics();
g.drawString(attributedText.getIterator(), 0, 20);

Этот способ печати текста дает нам возможность напрямую связать формат со строкой , что чище, чем изменение свойств объекта Graphics всякий раз, когда мы хотим изменить формат.

3. Выравнивание текста

Теперь, когда мы узнали, как добавить простой текст в левом верхнем углу изображения, давайте теперь посмотрим, как мы можем добавить этот текст в определенные позиции .

3.1. Текст по центру

Первый тип выравнивания, которым мы собираемся заняться, — это центрирование текста . Чтобы динамически установить правильную позицию, где мы хотим написать текст, нам нужно выяснить некоторую информацию:

  • Размер изображения
  • Размер шрифта

Эту информацию можно получить очень легко. В случае размера изображения доступ к этим данным можно получить с помощью методов getWidth и getHeight объекта BufferedImage . С другой стороны, чтобы получить данные, связанные с размером шрифта, нам нужно использовать объект FontMetrics .

Давайте посмотрим на пример, где мы вычисляем правильное положение для нашего текста и рисуем его:

Graphics g = image.getGraphics();

FontMetrics metrics = g.getFontMetrics(font);
int positionX = (image.getWidth() - metrics.stringWidth(text)) / 2;
int positionY = (image.getHeight() - metrics.getHeight()) / 2 + metrics.getAscent();

g.drawString(attributedText.getIterator(), positionX, positionY);

3.2. Текст выровнен по нижнему правому краю

Следующий тип выравнивания, который мы увидим, — нижний правый . В этом случае нам нужно динамически получать правильные позиции:

int positionX = (image.getWidth() - metrics.stringWidth(text));
int positionY = (image.getHeight() - metrics.getHeight()) + metrics.getAscent();

3.3. Текст расположен в левом верхнем углу

Наконец, давайте посмотрим, как напечатать наш текст в левом верхнем углу :

int positionX = 0;
int positionY = metrics.getAscent();

Остальные выравнивания можно вывести из трех, которые мы видели.

4. Адаптация размера текста на основе изображения

Когда мы рисуем текст на изображении, мы можем обнаружить, что этот текст превышает размер изображения. Чтобы решить эту проблему, мы должны адаптировать размер шрифта , который мы используем, в зависимости от размера изображения.

Во-первых, нам нужно получить ожидаемую ширину и высоту текста, используя базовый шрифт. Для этого мы будем использовать классы FontMetrics , GlyphVector и Shape .

FontMetrics ruler = graphics.getFontMetrics(baseFont);
GlyphVector vector = baseFont.createGlyphVector(ruler.getFontRenderContext(), text);

Shape outline = vector.getOutline(0, 0);

double expectedWidth = outline.getBounds().getWidth();
double expectedHeight = outline.getBounds().getHeight();

Следующим шагом будет проверка необходимости изменения размера шрифта. Для этого сравним ожидаемый размер текста и размер изображения:

boolean textFits = image.getWidth() >= expectedWidth && image.getHeight() >= expectedHeight;

Наконец, если наш текст не помещается на изображении, мы должны уменьшить размер шрифта. Мы будем использовать метод, производный Font для этого:

double widthBasedFontSize = (baseFont.getSize2D()*image.getWidth())/expectedWidth;
double heightBasedFontSize = (baseFont.getSize2D()*image.getHeight())/expectedHeight;

double newFontSize = widthBasedFontSize < heightBasedFontSize ? widthBasedFontSize : heightBasedFontSize;
newFont = baseFont.deriveFont(baseFont.getStyle(), (float)newFontSize);

Обратите внимание, что нам нужно получить новый размер шрифта на основе ширины и высоты и применить наименьший из них.

5. Резюме

В этой статье мы увидели, как написать текст на изображении, используя разные методы.

Мы также узнали, как динамически получить положение, в котором мы хотим напечатать наш текст, в зависимости от размера изображения и свойств шрифта.

Наконец, мы увидели, как адаптировать размер шрифта текста, если он превышает размер изображения, на котором мы его рисуем.

Как всегда, полный исходный код статьи доступен на GitHub .