it-swarm.com.de

Textinhalt in Bild konvertieren

Gibt es eine Java Bibliothek, die das Konvertieren von Textinhalten in Bilddateien ermöglicht? Ich kenne nur ImageMagick (JMagick in diesem Fall), möchte diese aber nicht installieren Alle externen Binärdateien (meine App wird als WAR-Datei auf einem Tomcat-Server bereitgestellt, sodass ich keine weiteren Abhängigkeiten als Java möchte.).

Zum Beispiel möchte ich aus der Zeichenfolge "Hallo" folgendes einfaches Bild erzeugen:

Basic image from string "hello"

25
jarandaf

Die Graphics 2D API sollte in der Lage sein, das zu erreichen, was Sie benötigen. Es hat auch einige komplexe Textverarbeitungsfunktionen.

enter image description here

import Java.awt.Color;
import Java.awt.Font;
import Java.awt.FontMetrics;
import Java.awt.Graphics2D;
import Java.awt.RenderingHints;
import Java.awt.image.BufferedImage;
import Java.io.File;
import Java.io.IOException;
import javax.imageio.ImageIO;

public class TextToGraphics {

    public static void main(String[] args) {
        String text = "Hello";

        /*
           Because font metrics is based on a graphics context, we need to create
           a small, temporary image so we can ascertain the width and height
           of the final image
         */
        BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = img.createGraphics();
        Font font = new Font("Arial", Font.PLAIN, 48);
        g2d.setFont(font);
        FontMetrics fm = g2d.getFontMetrics();
        int width = fm.stringWidth(text);
        int height = fm.getHeight();
        g2d.dispose();

        img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        g2d = img.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
        g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
        g2d.setFont(font);
        fm = g2d.getFontMetrics();
        g2d.setColor(Color.BLACK);
        g2d.drawString(text, 0, fm.getAscent());
        g2d.dispose();
        try {
            ImageIO.write(img, "png", new File("Text.png"));
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }

}

Schauen Sie sich auch Schreiben/Speichern und Bild an

WARNUNG Ich habe dies verwendet, um 90k PNG-Bilder zu generieren, nur um festzustellen, dass sie in IE aber nicht in Chrome Version 70.0.3538.77) angezeigt werden können

Der obige Code funktioniert einwandfrei für mich (ich habe die Textfarbe in WHITE geändert, damit ich ihn in Chrom sehen kann)

Running in Chrome

Ich habe Chrome 70.0.3538.77 unter Mac OS Mojave 10.14 mit Java 10.0.2. Das resultierende Bild hatte 4778x2411 Pixel ...

Aktualisiert...

Am IE das ist schwarz auf weiß aber am Chrome das ist schwarz auf schwarz. Dennoch habe ich den Hintergrund auf weiß gesetzt.

Was Sie mir sagen, ist, dass ein transparentes PNG auf verschiedenen Browsern unterschiedlich angezeigt wird, weil die Browser unterschiedliche Standardhintergründe verwenden. Warum wundert Sie das?

Die ursprüngliche Lösung verwendete bewusst ein transparentes Bild. Dies wird durch die Verwendung von BufferedImage.TYPE_INT_ARGB beim Erstellen des Bildes, das ein Alpha (A) basiertes RGB Farbmodell anwendet.

Dies ist unerwartet, da es g2d.setBackground (Color.white) gibt.

Nein, eigentlich wird es nur erwartet, wenn Sie verstanden haben, was setBackground tatsächlich tut und wie es verwendet werden sollte

Aus den JavaDocs

Legt die Hintergrundfarbe für den Graphics2D-Kontext fest. Die Hintergrundfarbe wird zum Löschen eines Bereichs verwendet . Wenn eine Graphics2D für eine Komponente erstellt wird, wird die Hintergrundfarbe von der Komponente übernommen. Das Festlegen der Hintergrundfarbe im Graphics2D-Kontext wirkt sich nur auf die nachfolgenden clearRect-Aufrufe und nicht auf die Hintergrundfarbe der Komponente aus. Verwenden Sie die entsprechenden Methoden der Komponente, um den Hintergrund der Komponente zu ändern.

Von den "Geräuschen" der Dinge wollen Sie ein nicht transparentes Bild mit einer gefüllten Hintergrundfarbe. Also, noch einmal, es geht los mit JavaDocs und ein bisschen Lesen hätte Sie zu BufferedImage.TYPE_INT_RGB, wodurch der Alpha-Kanal entfernt wird, der Hintergrund des Bilds jedoch immer noch ausgefüllt werden muss.

Dafür würde ich Graphics2D#setColor und Graphics2D#fillRect, nur weil es funktioniert.

Am Ende müsste also eine modifizierte Version der obigen stehen, die ungefähr so ​​aussehen könnte ...

img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
g2d = img.createGraphics();
//...
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.setColor(Color.BLACK);
g2d.drawString(text, 0, fm.getAscent());
g2d.dispose();
try {
    ImageIO.write(img, "png", new File("Text.png"));
} catch (IOException ex) {
    ex.printStackTrace();
}

Wenn ich zu "jpg" wechsle, erhalte ich sowohl auf IE= als auch auf Chrome orange/rosa Text auf schwarzem Hintergrund

Nun, dies hängt mit einem bekannten und leider häufigen Problem in ImageIO zusammen, bei dem versucht wird, den Alphakanal transparenter Farbmodelle auf das JPG anzuwenden, das Alphakanäle nicht unterstützt.

Weitere Informationen finden Sie unter Problem mit der ImageIO.write-JPG-Datei: rosa Hintergrund .

Die grundlegende Lösung besteht jedoch darin, entweder PNG zu verwenden, das Alphakanäle unterstützt, oder ein nicht transparentes Bild zu verwenden.

Also, das Lange und Kurze von all dem ist. Das Problem liegt NICHT bei der ursprünglichen Antwort, noch bei ImageIO, BufferedImage, Graphics, der AWT-Bibliothek, Chrome oder IE , aber wenn Sie nicht wissen, wie diese APIs (und das Beispiel) funktionieren.

62
MadProgrammer

Gehen Sie ohne externe Bibliotheken wie folgt vor:

  1. Messen Sie die Textgröße in Pixel (siehe Text messen )
  2. Erstellen Sie ein Java.awt.image.BufferedImage in der richtigen Größe für den Text
  3. Erfassen Sie das Grafikobjekt für das BufferedImage mit der createGraphics () -Methode
  4. Zeichne den Text
  5. Speichern Sie das Bild mit der Javax ImageIO-Klasse

Bearbeiten - Link behoben

6
Barak Itkin

Betrachten Sie das folgende Snippet:

public static final HashMap<RenderingHints.Key, Object> RenderingProperties = new HashMap<>();

static{
    RenderingProperties.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    RenderingProperties.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
    RenderingProperties.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
}

public static BufferedImage textToImage(String Text, Font f, float Size){
    //Derives font to new specified size, can be removed if not necessary.
    f = f.deriveFont(Size);

    FontRenderContext frc = new FontRenderContext(null, true, true);

    //Calculate size of buffered image.
    LineMetrics lm = f.getLineMetrics(Text, frc);

    Rectangle2D r2d = f.getStringBounds(Text, frc);

    BufferedImage img = new BufferedImage((int)Math.ceil(r2d.getWidth()), (int)Math.ceil(r2d.getHeight()), BufferedImage.TYPE_INT_ARGB);

    Graphics2D g2d = img.createGraphics();

    g2d.setRenderingHints(RenderingProperties);

    g2d.setBackground(Color.WHITE);
    g2d.setColor(Color.BLACK);

    g2d.clearRect(0, 0, img.getWidth(), img.getHeight());

    g2d.setFont(f);

    g2d.drawString(Text, 0, lm.getAscent());

    g2d.dispose();

    return img;
}

Verwendet nur die Java Graphics API, um ein Bild basierend auf einer Schriftart zu erstellen, die auf einem gepufferten Bild gerendert wurde.

2
initramfs

Hier ist ein einfaches Programm, um Grafikinhalte in das png Format zu schreiben.

import Java.awt.Graphics;
import Java.awt.Image;
import Java.awt.image.BufferedImage;

import javax.swing.JFrame;
import javax.swing.JPanel;
import Java.io.File;
import javax.imageio.ImageIO;

class ImageWriteEx extends JPanel{

    public void Paint(Graphics g){

        Image img = createImageWithText();
        g.drawImage(img, 20, 20, this);

    }

    private static BufferedImage createImageWithText(){ 

        BufferedImage bufferedImage = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
        Graphics g = bufferedImage.getGraphics();

        g.drawString("www.stackoverflow.com", 20, 20);
        g.drawString("www.google.com", 20, 40);
        g.drawString("www.facebook.com", 20, 60);
        g.drawString("www.youtube.com", 20, 80);
        g.drawString("www.Oracle.com", 20, 1000);

        return bufferedImage;

    }

    public static void main(String[] args){

        try{
            BufferedImage bi = createImageWithText();
            File outputfile = new File("save.png");
            ImageIO.write(bi, "png", outputfile);
        } catch(Exception e){
            e.printStackTrace();
        }

        JFrame frame = new JFrame();
        frame.getContentPane().add(new ImageWriteEx());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300,300);
        frame.setVisible(true);

    }

}
1
S. M. AMRAN

Falls jemand TextImages mit mehreren Zeilen haben möchte. Ich machte einige und zeigte sie mit

new ImageIcon(*here the image*)

in JOptionPane (ohne Text hinzuzufügen). Das füllt die gesamte JOptionPane gut aus. Hier der Code:

import Java.awt.Color;
import Java.awt.Font;
import Java.awt.FontMetrics;
import Java.awt.Graphics2D;
import Java.awt.RenderingHints;
import Java.awt.image.BufferedImage;

public class TextImage
{
   public static BufferedImage make(String...textrows)
   {
      BufferedImage helperImg = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
      Graphics2D g2d = helperImg.createGraphics();
      Font font = *here some font*;
      g2d.setFont(font);
      FontMetrics fm = g2d.getFontMetrics();
      String longestText = "";
      for(String row: textrows)
      {
         if(row.length()>longestText.length())
         {
            longestText = row;
         }
      }
      int width = fm.stringWidth(longestText);
      int height = fm.getHeight()*textrows.length;
      g2d.dispose();


      BufferedImage finalImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
      g2d = finalImg.createGraphics();
      g2d.setColor(*here some Color*);
      g2d.fillRect(0, 0, width, height);
      g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
      g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
      g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
  g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
      g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
      g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
      g2d.setFont(font);
      fm = g2d.getFontMetrics();
      g2d.setColor(Color.BLACK);
      int y = fm.getAscent();
      for(String row: textrows)
      {
         g2d.drawString(row, 0, y);
         y += fm.getHeight();
      }
      g2d.dispose();
      return finalImg;
   }
}
0
gute Fee