Aggiunta di testo a un'immagine in Java

1. Panoramica

A volte abbiamo bisogno di aggiungere del testo a un'immagine o a un insieme di immagini. Farlo manualmente è facile utilizzando uno strumento di modifica delle immagini. Ma quando vogliamo aggiungere lo stesso testo allo stesso modo a un numero significativo di immagini, sarebbe molto utile farlo a livello di programmazione.

In questo rapido tutorial, impareremo come aggiungere del testo alle immagini utilizzando Java.

2. Aggiunta di testo a un'immagine

Per leggere un'immagine e aggiungere del testo, possiamo usare classi diverse. Nelle sezioni successive, vedremo un paio di opzioni.

2.1. ImagePlus e ImageProcessor

Per prima cosa, vediamo come utilizzare le classi ImagePlus e ImageProcessor disponibili nella libreria ImageJ. Per utilizzare questa libreria dobbiamo includere questa dipendenza nel nostro progetto:

 net.imagej ij 1.51h 

Per leggere l'immagine useremo il metodo statico openImage . Il risultato di questo metodo verrà archiviato in memoria utilizzando un oggetto ImagePlus :

ImagePlus image = IJ.openImage(path);

Una volta caricata l'immagine in memoria, aggiungiamo del testo utilizzando la classe 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);

Con questo codice, quello che stiamo facendo è aggiungere il testo specificato in verde nella parte superiore sinistra dell'immagine. Si noti che impostiamo la posizione utilizzando il secondo e il terzo argomento del metodo drawString che rappresentano il numero di pixel rispettivamente da sinistra e dall'alto.

2.2. BufferedImage e grafica

Successivamente, vedremo come possiamo ottenere lo stesso risultato utilizzando le classi BufferedImage e Graphics . La build standard di Java include queste classi, quindi non sono necessarie librerie aggiuntive.

Nello stesso modo in cui abbiamo usato openImage di ImageJ , useremo il metodo di lettura disponibile in ImageIO :

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

Una volta caricata l'immagine in memoria, aggiungiamo del testo usando la classe 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);

Come possiamo vedere, entrambe le alternative sono molto simili nel modo in cui vengono utilizzate. In questo caso, il secondo e il terzo argomento del metodo drawString sono specificati nello stesso modo in cui abbiamo fatto per il metodo ImageProcessor .

2.3. Disegna in base a AttributedCharacterIterator

Il metodo drawString disponibile in Graphics ci consente di stampare il testo utilizzando un AttributedCharacterIterator . Ciò significa che invece di usare una semplice stringa , potremmo usare del testo con alcune proprietà associate. Vediamo un esempio:

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

Questo modo di stampare il testo ci dà la possibilità di associare il formato direttamente alla String , che è più pulito rispetto alla modifica delle proprietà dell'oggetto Graphics ogni volta che vogliamo cambiare il formato.

3. Allineamento del testo

Ora che abbiamo imparato come aggiungere un semplice testo in alto a sinistra di un'immagine vediamo ora come possiamo aggiungere questo testo in determinate posizioni .

3.1. Testo centrato

Il primo tipo di allineamento che affronteremo è centrare il testo . Per impostare dinamicamente la posizione corretta in cui vogliamo scrivere il testo, abbiamo bisogno di capire alcune informazioni:

  • Dimensione dell'immagine
  • Dimensione del font

Queste informazioni possono essere ottenute molto facilmente. Nel caso della dimensione dell'immagine, questi dati si può accedere attraverso metodi getWidth e GetHeight del BufferedImage dell'oggetto. D'altra parte, per ottenere i dati relativi alla dimensione del carattere dobbiamo utilizzare l'oggetto FontMetrics .

Vediamo un esempio in cui calcoliamo la posizione corretta per il nostro testo e lo disegniamo:

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. Testo allineato in basso a destra

Il prossimo tipo di allineamento che vedremo è in basso a destra . In questo caso, dobbiamo ottenere dinamicamente le posizioni corrette:

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

3.3. Testo situato in alto a sinistra

Infine, vediamo come stampare il nostro testo in alto a sinistra :

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

Il resto degli allineamenti può essere dedotto dai tre che abbiamo visto.

4. Adattamento delle dimensioni del testo in base all'immagine

Quando disegniamo il testo nell'immagine, potremmo scoprire che questo testo supera le dimensioni dell'immagine. Per risolvere questo problema, dobbiamo adattare la dimensione del carattere che stiamo utilizzando in base alla dimensione dell'immagine.

Innanzitutto, dobbiamo ottenere la larghezza e l'altezza previste del testo utilizzando il carattere di base. Per ottenere ciò, utilizzeremo le classi FontMetrics , GlyphVector e 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(); 

Il passaggio successivo consiste nel verificare se è necessario il ridimensionamento del carattere. A tal fine, confrontiamo la dimensione prevista del testo e la dimensione dell'immagine:

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

Infine, se il nostro testo non rientra nell'immagine, dobbiamo ridurre la dimensione del carattere. Useremo il metodo deriveFont per questo:

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

Nota che dobbiamo ottenere la nuova dimensione del carattere in base sia alla larghezza che all'altezza e applicare la più bassa di esse.

5. Riepilogo

In questo articolo abbiamo visto come scrivere del testo in un'immagine usando metodi diversi.

Abbiamo anche imparato come ottenere dinamicamente la posizione in cui vogliamo stampare il nostro testo in base alla dimensione dell'immagine e alle proprietà del carattere.

Infine, abbiamo visto come adattare la dimensione del carattere del testo nel caso in cui superi la dimensione dell'immagine in cui lo stiamo disegnando.

Come sempre, il codice sorgente completo dell'articolo è disponibile su GitHub.