How to increase Graphics2D text quality?
barcode, graphics2d, java, rendering, text-rendering
Solution
If someone wants to use pixel images in such cases, and not vector, then image should be upscaled for better printing quality:
static final int PIXELS_PER_POINT = 4; // 4x
Then define all dimensions in points, not in pixels:
// Image size in points
static final int IMAGE_WIDTH = 150;
static final int IMAGE_HEIGHT = 60;
// Font size in points
static final int FONT_SIZE = 11;
Now, when do any drawing, always use points converted to pixels:
static int toPixels(int value) {
return value * PIXELS_PER_POINT;
}
BufferedImage draw() {
BufferedImage image =
new BufferedImage(toPixels(IMAGE_WIDTH), toPixels(IMAGE_HEIGHT), TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
// <graphics init code goes here>
Font font = new Font("Arial", Font.PLAIN, toPixels(FONT_SIZE));
g.setFont(font);
g.drawString("Grapes", toPixels(5), toPixels(40)); // coordinates are in points
g.dispose()
return image;
}
So, with this approach you can operate with 'standard' dimentions. This approach works quite well for me for low- and medium complexity drawings.
You can go further and convert `PIXELS_PER_POINT` to a parameter: use `1x` for images on web-pages with ordinary display, `2x` for Retina displays and `4x` for printing!
Problem
I have a question concerning printing additional information on barcodes. I am using http://barbecue.sourceforge.net/ to create my barcodes. After I created my barcodes I want to add some additional information. At the moment i do this with the following way! For example: ``` Graphics2D g2d5 = container4Barcode.createGraphics(); g2d5.setBackground(Color.WHITE); g2d5.clearRect(0, 33, 200, 200); g2d5.setColor(Color.BLACK); g2d5.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2d5.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP); g2d5.setFont(new Font("Arial", Font.PLAIN, 8)); g2d5.drawString(barcode, 8, 40); g2d5.drawString(generateRandomNumber(ekPreis), 57, 40); String datumResult = datum; g2d5.drawString(location, 98, 40); g2d5.drawString(datum.substring(2), 114, 40); g2d5.dispose(); ``` The output is in a pdf the following: As you can see is the quality of my text (above and under the barcode) is really bad ... How can I increase the quality of the text to make the text more smoother and not that pixelated?! (When I print my barcodes, the barcodes look very pixelated ...) Any tips? UPDATE: So, I added here the a picture of my latest outcome ... When I print out these barcodes they look horrible! So here is the code what I did: ``` Graphics2D g2d6 = container4Barcode.createGraphics(); g2d6.setColor(Color.black); g2d6.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2d6.setFont(new Font("Verdana", Font.BOLD, 7)); g2d6.drawString("FLORETT", 9, 20); g2d6.drawString("50-521-60", 57, 20); Graphics2D g2d4 = container4Barcode.createGraphics(); g2d4.setColor(Color.black); g2d4.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2d4.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); g2d4.setFont(new Font("Verdana", Font.BOLD, 11)); g2d4.drawString("SSYYS", 105, 19); g2d4.dispose(); ``` With that Code I get the best results! Of course I played with "Metrics, AA_GASP, LCS_HRGB, different fonts (Verdana is the best in my opinion) ..." and a lot more, but some of them I couldn't use, because then my barcode got blurred! So actioally I am forcing the problem that I am unable to improve the quality of my text-quality of the drawstring from graphics2d! So, I want to ask if there is a possibility to let the "SSYYS" (Font Size 11) and the "FLORETT" (Font Size 7) look much nicer! Is there a possibility in JAVA to draw "smooth" text on an image with a font size less than "12" ? Is there a workaround to to that ? As you can see in the picture the letters "S and Y" look very awful... 2nd Update: Some Example code so far... Please be sure that the following folder exists: C:\TestBarcodes\ Hope I reduced my code to the minimum that you can imagine what my problem is... ``` package generator; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.FileOutputStream; import java.io.IOException; import net.sourceforge.barbecue.Barcode; import net.sourceforge.barbecue.BarcodeException; import net.sourceforge.barbecue.BarcodeFactory; import net.sourceforge.barbecue.output.OutputException; import org.apache.pdfbox.exceptions.COSVisitorException; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.edit.PDPageContentStream; import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg; import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage; public class BarcodeGen { // sets the picWidth private static int picWidth = 149; // sets the picHeigth private static int picHeigth = 60; public static void main(String[] args) throws BarcodeException, OutputException, COSVisitorException, IOException { generateBarcode("11138500"); } public static void generateBarcode(String barcode) throws IOException, COSVisitorException, BarcodeException, OutputException { Barcode barcode2 = BarcodeFactory.createCode39(barcode, false); int gw = barcode2.getWidth(); // change this to suit if you want higher, default 50 // barcode2.setBarWidth(50); // this sets DPI barcode2.setResolution(100); // barcode2.setFont(font); int gh = barcode2.getHeight(); // change this if you want a coloured background // image = new BufferedImage(t, s, BufferedImage.TYPE_INT_RGB) BufferedImage image = new BufferedImage(gw, gh, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = (Graphics2D) image.getGraphics(); // default is black so draw a white box first // change type to INT_RGB if you want a coloured background g2.setColor(Color.white); g2.fillRect(0, 0, gw, gh); barcode2.draw(g2, 0, 0); // CREATE ADDITIONAL INFORMATION ON BARCODE BufferedImage container4Barcode = new BufferedImage( picWidth, picHeigth, image.getType()); Graphics2D g2d = container4Barcode.createGraphics(); g2d.setBackground(Color.WHITE); g2d.clearRect(0, 0, picWidth, picHeigth); g2d.setColor(Color.black); g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); g2d.drawImage(image, 8, 21, 130, 18, null); g2d.dispose(); Graphics2D g2d6 = container4Barcode.createGraphics(); g2d6.setColor(Color.black); g2d6.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2d6.setFont(new Font("Verdana", Font.BOLD, 7)); g2d6.drawString("FLORETT", 9, 20); g2d6.drawString("50-521-60", 57, 20); Graphics2D g2d4 = container4Barcode.createGraphics(); g2d4.setColor(Color.black); g2d4.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2d4.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); g2d4.setFont(new Font("Verdana", Font.BOLD, 11)); g2d4.drawString("SSYYS", 105, 19); g2d4.dispose(); // PRINT PDF int ver = 782; PDDocument doc = new PDDocument(); PDPage page = new PDPage(PDPage.PAGE_SIZE_A4); doc.addPage(page); PDXObjectImage image2 = new PDJpeg(doc, container4Barcode); PDPageContentStream content = new PDPageContentStream(doc, page); content.drawImage(image2, 5, ver); content.close(); doc.save(new FileOutputStream("C:\\TestBarcodes\\barcode.pdf")); // opens the pdf file Process p = Runtime .getRuntime() .exec("rundll32 url.dll,FileProtocolHandler C:\\TestBarcodes\\barcode.pdf"); try { p.waitFor(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } ```