1. 概要

画像または画像のセットにテキストを追加する必要がある場合があります。 これを手動で行うには、画像編集ツールを使用すると簡単です。 しかし、同じテキストを同じ方法でかなりの数の写真に追加したい場合は、これをプログラムで行うと非常に便利です。

このクイックチュートリアルでは、Javaを使用して画像にテキストを追加する方法を学習します。

2. 画像へのテキストの追加

画像を読んでテキストを追加するために、さまざまなクラスを使用できます。 以降のセクションでは、いくつかのオプションについて説明します。

2.1. ImagePlusおよびImageProcessor

まず、ImageJライブラリで利用可能なImagePlusクラスとImageProcessorクラスの使用方法を見てみましょう。 このライブラリを使用するには、この依存関係をプロジェクトに含める必要があります。

<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番目と3番目の引数を使用して位置を設定していることに注意してください。これらは、それぞれ左と上からのピクセル数を表します。

2.2. BufferedImageおよびGraphics

次に、クラスBufferedImageとGraphicsを使用して同じ結果を達成する方法を見ていきます。 Javaの標準ビルドにはこれらのクラスが含まれているため、追加のライブラリは必要ありません。

ImageJopenImageを使用したのと同じ方法で、ImageIOで使用可能なreadメソッドを使用します。

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 の2番目と3番目の引数は、ImageProcessorメソッドに対して行ったのと同じ方法で指定されます。

2.3. AttributedCharacterIteratorに基づく描画

Graphicsで使用可能なメソッドdrawStringを使用すると、AttributedCharacterIteratorを使用してテキストを印刷できます。 これは、プレーンな String を使用する代わりに、いくつかのプロパティが関連付けられたテキストを使用できることを意味します。 例を見てみましょう:

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);

このテキストの印刷方法により、フォーマットを String に直接関連付けることができます。これは、フォーマットを変更するときにGraphicsオブジェクトのプロパティを変更するよりもクリーンです。

3. テキストの配置

画像の左上に簡単なテキストを追加する方法を学習したので、このテキストを特定の位置に追加する方法を見てみましょう。

3.1. 中央揃えのテキスト

取り組む最初のタイプの配置は、テキストの中央揃えです。 テキストを書きたい正しい位置を動的に設定するには、いくつかの情報を把握する必要があります。

  • 画像サイズ
  • フォントサイズ

この情報は非常に簡単に取得できます。 画像サイズの場合、このデータには、BufferedImageオブジェクトのメソッドgetWidthおよびgetHeightを介してアクセスできます。 一方、フォントサイズに関連するデータを取得するには、オブジェクト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();

残りの配置は、これまでに見た3つから推測できます。

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;

最後に、テキストが画像に収まらない場合は、フォントサイズを小さくする必要があります。 そのためにメソッドderiveFontを使用します。

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から入手できます。