Добавяне на текст към изображение в Java

1. Общ преглед

Понякога трябва да добавим малко текст към изображение или набор от изображения. Правенето на това ръчно е лесно с помощта на инструмент за редактиране на изображения. Но когато искаме да добавим един и същ текст по същия начин към значителен брой снимки, би било много полезно да направим това програмно.

В този бърз урок ще научим как да добавяме малко текст към изображения с помощта на Java.

2. Добавяне на текст към изображение

За да прочетем изображение и да добавим малко текст, можем да използваме различни класове. В следващите раздели ще видим няколко опции.

2.1. ImagePlus и ImageProcessor

Първо, нека видим как да използваме класовете ImagePlus и ImageProcessor, които са налични в библиотеката ImageJ. За да използваме тази библиотека, трябва да включим тази зависимост в нашия проект:

 net.imagej ij 1.51h 

За да прочетем изображението, ще използваме статичния метод 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);

Този начин на отпечатване на текста ни дава възможност да свържем формата директно със String , който е по-чист от промяната на свойствата на 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;

И накрая, ако нашият текст не се побира в изображението, трябва да намалим размера на шрифта. За това ще използваме метода 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.