Java Graphics2D Drawn Text Exported Exactly To SVG - java

Am trying to export text to an SVG file and have it look similar to what is drawn using java Graphics2D. The precision is crucial for my application meaning the text in both Java and the SVG need to line up. Both the SVG and the Graphics2D texts have the same font(family, style, size) and I can definitely see that the resulting texts are different.
Example: Seems the chars look the same but for some reason the spacing between 'T' and 'e' differ.
BLACK - SVG Text
BLUE - Java drawn Text
Code for the drawing of text using Graphics2D.
Graphics2D g2 = (Graphics2D) g;
String text = "Test";
Font font = new Font("Arial", Font.PLAIN, 33);
g.setFont(getTextFont());
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g.drawString("Test", 0.f, 0.f);
SVG text
<text fill="rgb(0,115,198)" font-family="Arial" font-size="33.0">
<tspan dy="0" x="0">Test</tspan>
</text>
Any ideas how to change either the SVG(viewed in Adobe) or Java text such that they display exactly the same thing?
Update:
Turning kerning does make it like up better but not perfectly.
Example: Seems the spacing between f A is different. But the rest of the text lines up.
Code
public void draw() {
Graphics2D g2 = (Graphics2D) g;
String text = "Test";
Font font = new Font("Arial", Font.PLAIN, 33);
Map<TextAttribute, Object> map = new Hashtable<TextAttribute, Object>();
map.put(TextAttribute.KERNING, TextAttribute.KERNING_ON);
font = font.deriveFont(map);
g.setFont(font);
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g.draw(getTextShapeByLine(text);
}
public Shape getTextShapeByLine(String line) {
AttributedString attstring = new AttributedString(line);
attstring.addAttribute(TextAttribute.FONT, getTextFont());
FontRenderContext frc = new FontRenderContext(null, true, true);
TextLayout t = new TextLayout(attstring.getIterator(), frc);
return t.getOutline(null);
}
This draws the text with kerning and allows scaling on the graphics context. But, now the spacing(white-space) is sometimes messed up between certain characters.

Related

Java AWT text produces artifacts

I'm trying to draw some text on some plain color background, and I'm getting some artifacts around the text. Is there a way to get clean writing?
final BufferedImage image = new BufferedImage(400, 400,
BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setColor(Color.BLUE);
g2d.fillRect(0,0, image.getWidth(), image.getHeight());
Font font = new Font ("Verdana", Font.PLAIN, 40);
AffineTransform affinetransform = new AffineTransform();
FontRenderContext frc = new FontRenderContext(affinetransform, true, true);
TextLayout layout = new TextLayout("Hello World!", font, frc);
g2d.setColor(Color.WHITE);
layout.draw(g2d, 100, 100);
ImageIO.write(image, "jpg", new File("testDirtyText.jpg"));
It's producing some artifacts as shown here:
Any advice around any other aspect of this would be appreciated as well.
Thanks!
I'm not quite sure whether you're referring to aliasing artifacts or JPEG compression artifacts. To fix the former, add:
g2d.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
See https://docs.oracle.com/javase/8/docs/api/java/awt/RenderingHints.html for more rendering options.
To fix the latter, save as a PNG instead:
ImageIO.write(image, "png", new File("test.png"));
Or if you really need a JPEG, see this Q&A about setting the JPEG quality level.

Java blurrying background with Graphics2D

I'm using Java to create an image with text. I set the color of the background and fill it up. Then I place the text using LineBreakMeasurer. The problem is (As you can see in the attached image) the image background around the text is blurry (if you zoom on). This is a problem for me. Is it possible to fix that?
final BufferedImage image = new BufferedImage(600, 400, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setColor(new Color(255,0,0));
g2d.fillRect (0, 0, image.getWidth(), image.getHeight());
...
AttributedString attributedString = getAttributedString(text, fontSize, new Color(1.0f,1.0f,1.0f,0.9f));
AttributedCharacterIterator characterIterator = attributedString
.getIterator();
FontRenderContext fontRenderContext = g2d.getFontRenderContext();
LineBreakMeasurer measurer = new LineBreakMeasurer(characterIterator,
fontRenderContext);
while (measurer.getPosition() < characterIterator.getEndIndex()) {
TextLayout textLayout = measurer.nextLayout(width);
int currentX = x + (int)(width - textLayout.getVisibleAdvance()) / 2;
y += textLayout.getAscent();
textLayout.draw(g2d, currentX, y);
}
If you're referring to the artifacts around the letters, the problem isn't with your painting code. It's the result of saving the image as a JPEG. Save it using a non-lossy format, like PNG. You could also try reducing the compression of the JPEG, but saving as a PNG is probably easier.

Using Java AWT to generate monochrome 1bitpp PNG with Ancillary Chunks

I am trying to generate PNG with the following ancillary chunks (header from a reference image)
The ancillary chunks in the reference image probably came from GIMP processing.
Whereas the Image I generate with Java AWT does not have those ancillary chunks.
Here is the header of the PNG I am generating. Please note the critical chunks are identical.
Here is the code fragment
{
:
// The color map contains the colors black and white
byte[] cMap = {0, 0, 0, (byte)255, (byte)255, (byte)255};
// Create an IndexColorModel setting white as the transparent color
IndexColorModel monochrome = new IndexColorModel(8, 2, cMap, 0, false, 0);
BufferedImage img = new BufferedImage(width_img, height_img,
BufferedImage.TYPE_BYTE_INDEXED,monochrome);
Graphics2D g2d = img.createGraphics();
:
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width_img, height_img);
Font font = new Font("Arial Bold", Font.PLAIN, 48);
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
g2d.setColor(Color.BLACK);
:
:
g2d.dispose();
imgName = ".\\Panel"+width_img+"x"+height_img+".png";
ImageIO.write(img, "png", new File(imgName));
:
}
How do I add chunks (pHYs, tIME) using Java AWT?
Any pointers will be helpful too- please let me know.
Thank you
I concluded that AWT does not support - this questions identifies couple of ways to add chunks
How can I save a PNG with a tEXt or iTXt chunk from Java?
Here is what I propose to do -
Use AWT / Graphics 2D to generate the .PNG
Read PNG, refer to the link for details on how to do it
Add the Chunks you want to add
Write it(them) back to the .PNG

How to set fonts to a string

Is there a way to set fonts on a string, and then draw the string using graphics? I know you can do it on Jlabels, and Jtextfields, and J-other components, but is there a way to do it just on the string instead? Thank you.
You can do it with attributed strings an example of is
Font font = new Font("LucidaSans", Font.PLAIN, 14);
AttributedString atString= new AttributedString("Example text string");
atString.addAttribute(TextAttribute.FONT, font);
graphic.drawString(atString.getIterator(),x,y);
Cheers!
We can actually set the font in graphics...and then draw the string.
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.setFont(Fonts.f);
g.drawString(Fonts.text, 50, 50);
}
Yes, it's possible, start by checking out the Graphics, Text tutorials
Basically, you can set the font using Graphics#setFont and draw a String using Graphics#drawString.
Also see Performing Custom Painting for how you can perform custom painting in Swing
For example
List available font names....
String fonts[] = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
for (String font : fonts) {
System.out.println(font);
}
or
Font fonts[] = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
for (Font font : fonts) {
System.out.println(font);
}
You can manipulate a font's properties using one of the Font#derive methods...
Font font = ...;
Font bigger = font.derive(32f);
Font bolder = font.derive(Font.BOLD);
Font biggerAndBolder = font.derive(Font.BOLD, 32f);

Improve "drawString" methods text quality

I'm in the process of making a captcha in Java but I'm having trouble improving the text quality the "drawString" method generates on top of my image.
Example of the text quality:
You can actually see the horrible edges on the text.
Java code:
File file = new File("C:\\captcha.png");
File file2 = new File("C:\\captcha2.png");
File fontfile = new File("C:\\xerox.ttf");
BufferedImage bfimage = ImageIO.read(file);
Graphics2D g = bfimage.createGraphics();
Font myfont = Font.createFont(Font.PLAIN, fontfile);
myfont = myfont.deriveFont(50f);
g.setFont(myfont);
g.setColor(Color.black);
AffineTransform att = new AffineTransform();
g.translate(100, 50);
att.rotate(Math.toRadians(15), 100, 50);
g.setTransform(att);
g.drawString("12345", 100, 50);
RenderedImage rimg = bfimage;
ImageIO.write(rimg, "PNG", file2);
Example of same font used in php, but here the quality is A LOT better with smooth edges:
How do I improve the text quality generated by the "drawString" method in Java?
Graphics and Graphics2D provide a rendering hint framework that allows you to configure some parts of the rendering of a component. Use an antialiasing rendering hint:
g2d.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
and you should get antialiased text on your captcha.
http://docs.oracle.com/javase/6/docs/api/java/awt/RenderingHints.html for reference

Categories