How to increase Graphics2D text quality?
Asked Answered
C

2

9

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: enter image description here

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

enter image description here

Cervical answered 24/11, 2012 at 12:48 Comment(11)
Experiment with possibilities easily, using the code on this answer.Demp
Thank you for your post, but this didn't help :/ I played the last 5 days to increase the quality of the text ... BUT I couldn't manage it ... It is very pixelated !! Is there another opportunity to increase the quality of the text ?! Something else than Graphics2D ?! Or cannot java deal with such a small font size ?! I updated my post that you can see what I have until now, but even the "SSYYS" (font size 13 is very pixelated)...Cervical
Next level of help. For better help sooner, post an SSCCE.Demp
Sorry, I thought I posted it... But something went wrong when I edited the post ... Now it is updated correctly.Cervical
"I thought I posted it." There is still no SSCCE on this question.Demp
What do you exactly want ?! ... The whole java code ? :/ Don't understand ... :DCervical
Exactly an SSCCE! Did you read the linked document? If there is anything in it you do not understand - ask, but be specific. The code I linked earlier was an SSCCE (if you consider 294 lines of code to be 'short').Demp
Ok, I added that SSCCE and broke my code down to the minimum ! Hope I did that correctly :) Thanks for your help until now anyway !!! :)Cervical
OK.. & what does pdfbox have to do with writing clear text? Is the text sharp and clear when you draw it on a plain image? In that case, the problem is pdfbox for which I don't provide support. If not, then it could be argued that pdfbox is not relevant to the problem, and should be removed. One huge advantage of removing the code that relates to pdfbox is that then people will be able to compile & run the code using J2SE with no 3rd party plug-ins. I've spent a lot more time trying to explain how to post code than I usually do & I am very near abandoning this thread. Last try.Demp
Could you write the text as actual text to the PDF instead of as images? That way you get the text in vector format in the final result.Impugn
Hell man ! You are a good boy ... Thank you very much... Why didn't I get this idea ?! This is brilliant man! I was so focused on the Graphics2D ... Thank you very much ... Short answer, but very helpful! :)Cervical
E
2

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!

Ethnarch answered 8/10, 2013 at 12:0 Comment(1)
Shouldn't PIXELS_PER_POINT be of type double, calculated by something like: PIXELS_PER_POINT = 300./90. for a 300dpi Print (assuming standard monitors have 90dpi) PIXELS_PER_POINT = 600./90. for a 600dpi Print ... and so onKaterinekates
W
1

To fix the jagged edges in text or shapes in Graphics2d you need to set RenderingHint.

Graphics2D g2d = bufferedImage.createGraphics();

    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

Explanation

A typical antialiasing algorithm works by blending the existing colors of the pixels along the boundary of a shape with the requested fill paint according to the estimated partial pixel coverage of the shape.

Text antialiasing hint key. The TEXT_ANTIALIASING hint can control the use of antialiasing algorithms for text independently of the choice used for shape rendering. Often an application may want to use antialiasing for text only and not for other shapes. Additionally, the algorithms for reducing the aliasing artifacts for text are often more sophisticated than those that have been developed for general rendering so this hint key provides additional values which can control the choices of some of those text-specific algorithms. If left in the DEFAULT state, this hint will generally defer to the value of the regular KEY_ANTIALIASING hint key.

Walter answered 21/9, 2021 at 15:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.