Testo Java sull’immagine

Sto caricando un’immagine in bufferedimage e poi scrivendo del testo. Dopo aver aggiunto del testo, rende l’immagine sfocata e il testo distorto. Ho ANTIALIASING DI TESTO SU. Può essere visto come allegato.

inserisci la descrizione dell'immagine qui

Dovresti essere in grado di controllare la qualità del testo con gli hint di rendering mostrati nelle altre risposte. So che funziona perché l’ho fatto molto, quindi penso che debba essere qualcos’altro che causa il degrado della qualità in questo caso.

  1. Come si controlla la qualità dell’immagine? Dipingi la BufferedImage generata direttamente in una grafica a schermo nella tua applicazione java o la salverai su disco, ovvero come JPEG? Se lo salvi sul disco prova a salvarlo come PNG 24 e non come JPEG. Presumo che lo schermo del desktop sia in esecuzione in True Color (profondità colore a 32 o 24 bit), giusto?
  2. Sei sicuro che l’immagine sia effettivamente creata come BufferedImage.TYPE_INT_RGB? Se non hai il controllo sulla creazione di BufferedImage nel tuo codice prova a creare una nuova BufferedImage con TYPE_INT_RGB e dipingi il sorgente in questo e poi disegna il testo in esso.
  3. Prova a impostare RenderingHints.KEY_DITHERING su RenderingHints.VALUE_DITHER_DISABLE (anche se questo non dovrebbe essere necessario per le immagini a colors reali).

Se ciò non ti aiuta ancora a trovare la causa, fornisci ulteriori informazioni (versione VM, sistema operativo) e codice sorgente. Il rendering del testo è diventato abbastanza buono con JDK 1.6 Update 10, ma anche le versioni precedenti erano in grado di produrre testo pulito nelle immagini, ma non sembrava altrettanto bello a causa dell’antialiasing meno sofisticato.

in risposta al tuo commento:

I bordi nitidi ad alto contrasto come nel testo sono un problema generale con la compressione JPEG poiché non è una compressione senza perdita di dati. Se hai davvero bisogno di andare con JPEG e non puoi passare a PNG, puoi ottimizzare la qualità della compressione dell’immagine salvata per trovare un compromesso migliore tra qualità dell’immagine e dimensioni del file. Vedere il codice seguente su come impostare la qualità della compressione quando si salva un JPEG.

import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.plugins.jpeg.JPEGImageWriteParam; import javax.imageio.stream.ImageOutputStream; //---- float quality = 0.85f; File outfile = new File( "MyImage.jpg" ); BufferedImage image = ...; ImageWriter imgWriter = ImageIO.getImageWritersByFormatName( "jpg" ).next(); ImageOutputStream ioStream = ImageIO.createImageOutputStream( outfile ); imgWriter.setOutput( ioStream ); JPEGImageWriteParam jpegParams = new JPEGImageWriteParam( Locale.getDefault() ); jpegParams.setCompressionMode( ImageWriteParam.MODE_EXPLICIT ); jpegParams.setCompressionQuality( quality ); imgWriter.write( null, new IIOImage( image, null, null ), jpegParams ); ioStream.flush(); ioStream.close(); imgWriter.dispose(); 
 import java.awt.image.BufferedImage; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.imageio.*; import java.io.*; import javax.imageio.stream.ImageOutputStream; import javax.imageio.plugins.jpeg.JPEGImageWriteParam; import java.util.Locale; class ImageCompressionDemo { private BufferedImage originalImage; private BufferedImage textImage; private JPanel gui; private JCheckBox antialiasing; private JCheckBox rendering; private JCheckBox fractionalMetrics; private JCheckBox strokeControl; private JCheckBox colorRendering; private JCheckBox dithering; private JComboBox textAntialiasing; private JComboBox textLcdContrast; private JLabel jpegLabel; private JLabel pngLabel; private JTextArea output; private JSlider quality; private int pngSize; private int jpgSize; final static Object[] VALUES_TEXT_ANTIALIASING = { RenderingHints.VALUE_TEXT_ANTIALIAS_OFF, RenderingHints.VALUE_TEXT_ANTIALIAS_ON, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB }; final static Object[] VALUES_TEXT_LCD_CONTRAST = { new Integer(100), new Integer(150), new Integer(200), new Integer(250) }; ImageCompressionDemo() { int width = 280; int height = 100; gui = new JPanel(new BorderLayout(3,4)); quality = new JSlider(JSlider.VERTICAL, 0, 100, 75); quality.setSnapToTicks(true); quality.setPaintTicks(true); quality.setPaintLabels(true); quality.setMajorTickSpacing(10); quality.setMinorTickSpacing(5); quality.addChangeListener( new ChangeListener(){ public void stateChanged(ChangeEvent ce) { updateImages(); } } ); gui.add(quality, BorderLayout.WEST); originalImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); textImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); JPanel controls = new JPanel(new GridLayout(0,1,0,0)); antialiasing = new JCheckBox("Anti-aliasing", false); rendering = new JCheckBox("Rendering - Quality", true); fractionalMetrics = new JCheckBox("Fractional Metrics", true); strokeControl = new JCheckBox("Stroke Control - Pure", false); colorRendering = new JCheckBox("Color Rendering - Quality", true); dithering = new JCheckBox("Dithering", false); controls.add(antialiasing); controls.add(fractionalMetrics); textLcdContrast = new JComboBox(VALUES_TEXT_LCD_CONTRAST); JPanel lcdContrastPanel = new JPanel(new FlowLayout(FlowLayout.LEADING)); lcdContrastPanel.add(textLcdContrast); lcdContrastPanel.add(new JLabel("Text LCD Contrast")); controls.add(lcdContrastPanel); textAntialiasing = new JComboBox(VALUES_TEXT_ANTIALIASING); controls.add(textAntialiasing); controls.add(dithering); controls.add(rendering); controls.add(colorRendering); controls.add(strokeControl); ItemListener itemListener = new ItemListener(){ public void itemStateChanged(ItemEvent e) { updateImages(); } }; antialiasing.addItemListener(itemListener); rendering.addItemListener(itemListener); fractionalMetrics.addItemListener(itemListener); strokeControl.addItemListener(itemListener); colorRendering.addItemListener(itemListener); dithering.addItemListener(itemListener); textAntialiasing.addItemListener(itemListener); textLcdContrast.addItemListener(itemListener); Graphics2D g2d = originalImage.createGraphics(); GradientPaint gp = new GradientPaint( 0f, 0f, Color.red, (float)width, (float)height, Color.orange); g2d.setPaint(gp); g2d.fillRect(0,0, width, height); g2d.setColor(Color.blue); for (int ii=0; ii 

Immagine dello schermo

Uscite tipiche

 Fractional Metrics: true Nonantialiased text mode PNG size: 7390 bytes JPG size: 7036 bytes quality: 35 Fractional Metrics: true Antialiased text mode PNG size: 8741 bytes JPG size: 8663 bytes quality: 55 Fractional Metrics: false Antialiased text mode PNG size: 8720 bytes JPG size: 8717 bytes quality: 55 

questo è solo java. basta distriggersre l’anti-alias del testo. o se ne hai davvero bisogno, esegui il rendering del testo su un’immagine separata, se il testo è nero, ottieni tutti i pixel con il colore sotto a circa rgb (100,100,100) e impostalo su 0. quindi dipingi quel buffer sull’immagine principale.

prova questo:

 public static void setGraphicsQuality(Graphics2D g2D) { g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2D.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); }