Improve "drawString" methods text quality - java

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

Related

Crop image by polygon area in Java

by using Canvas and JS I can draw a shape like this and have the x,y of each point :
Tha area can be choosen by more than 4 points, look at this link to have an idea.
I need to save and crop the image of the selected area by using the points. I can not use BufferedImage as it is just rectangular. Which lib in java I can use?
Okay, so starting with...
I used...
BufferedImage source = ImageIO.read(new File("Example.jpg"));
GeneralPath clip = new GeneralPath();
clip.moveTo(65, 123);
clip.lineTo(241, 178);
clip.lineTo(268, 405);
clip.lineTo(145, 512);
clip.closePath();
Rectangle bounds = clip.getBounds();
BufferedImage img = new BufferedImage(bounds.width, bounds.height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
clip.transform(AffineTransform.getTranslateInstance(-65, -123));
g2d.setClip(clip);
g2d.translate(-65, -123);
g2d.drawImage(source, 0, 0, null);
g2d.dispose();
ImageIO.write(img, "png", new File("Clipped.png"));
to generate...
Now, the image is rectangular, that's just the way it works
Now, setClip is quite rough and isn't effect by any RenderingHints, you could make use of "soft clipping" instead, which is more involved, but generates a nicer results. See this example and this exmaple for more details

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 Graphics2D Drawn Text Exported Exactly To SVG

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.

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

Writing on a premade Image

http://www.robinswebsitestudio.com/ButtonSamples/buttons.html
The following code does write to a premade image. The resulting image, though, has significant problems.
the original png file is a 3D button with Index Transparency and a matte so that the gif file would
blend in with the page background color
the resulting gif file is flat, the matte is gone, and the text doesn’t look smooth. The resulting
file is therefore is not something you would get from Adobe Photoshop or Fireworks and doesn’t look
professional.
If anyone has suggestions, I’m all ears. Is it impossible to get a high quality 3D button using Java?
String pathToWeb = getServletContext().getRealPath(File.separator);
File f = new File(pathToWeb + "activities.png");
BufferedImage bufferedImage = ImageIO.read(f);
// Create a graphics which can be used to draw into the buffered image
Graphics2D g2d = bufferedImage.createGraphics();
g2d.setFont(new Font( "Arial", Font.BOLD, 15 ));
//create a string with black
g2d.setColor(Color.black);
g2d.drawString("Activities", 40, 40);
// Disposes of this graphics context and releases any system resources that it is using.
g2d.dispose();
// Save as gif
File file = new File("myactivities.gif");
ImageIO.write(bufferedImage, "gif", file);

Categories