Java AWT text produces artifacts - java

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.

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

How to render small utf fonts in a high quality bufferedImage

I want to render a string using java in a a bufferedImage. the problem is when i use a small font (for example: 8pt) i have bad quality images and the image resolution is 72dpi.
i want to have the best quality for images and if possible change the images resolution to 360dpi.
Noted that i want to generate a database of a language words with differents fonts, font sizes and font styles. and i used the standard java API (Graphics2D, Font, RenderingHints, FontMetrics,...) to generate images.
here is my code:
public static void main(String[] args) {
String text = "ⴰⴱⴱⵓⵥⵥⵍ";
String [] polices=polices();
for(int i=0;i<polices.length;i++){
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g2d = img.createGraphics();
Font font = new Font(polices[i], Font.PLAIN, 8);
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
int width = fm.stringWidth(text);
int height = fm.getHeight();
g2d.dispose();
img = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setFont(font);
g2d.setBackground(Color.WHITE);
g2d.clearRect(0, 0, width, height);
fm = g2d.getFontMetrics();
g2d.setColor(Color.BLACK);
g2d.drawString(text, 0, fm.getAscent());
g2d.dispose();
try {
ImageIO.write(img, "png", new File("Text "+i+".png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
I searched a lot for a solution vainly, if someone can help me i will be thankfull.
A solution that uses any externe libraries is welcome too.
An 8pt font at 72dpi is 8/72*360 = size 40 font at 360dpi - so set the font size to 40.
As to how to set the DPI for an image, see the question How to set DPI information in an image?

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.

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

How to get rid of White rectangle from an image using java

I had tired the following code to generate the thumb nail but when I place it on another image, the thumbnail has a white rectangle. How can I remove it using java graphics 2D?
Image image = javax.imageio.ImageIO.read(new File(originalFile));
BufferedImage thumbImage = new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = thumbImage.createGraphics();
graphics2D.setBackground(Color.WHITE);
graphics2D.setPaint(Color.WHITE);
graphics2D.fillRect(0, 0, thumbWidth, thumbHeight);
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, null);
File file = new File(thumbnailFile);
if(javax.imageio.ImageIO.write(thumbImage, "png", file))
return file;
}
Even if i remove these three lines I am getting black rectangle.
graphics2D.setBackground(Color.WHITE);
graphics2D.setPaint(Color.WHITE);
graphics2D.fillRect(0, 0, thumbWidth, thumbHeight);
How to get this image as transparent? Please some one help me out.
Color transparent = new Color(0,0,0,0)
by setting Composite . here : AlphaComposite
// Create an image that supports arbitrary levels of transparency
Graphics2D g2d = (Graphics2D) image.getGraphics();
BufferedImage thumbImage = g2d.getDeviceConfiguration().createCompatibleImage(
thumbWidth, thumbHeight, Transparency.TRANSLUCENT);
..BufferedImage.TYPE_INT_RGB
That should be:
..BufferedImage.TYPE_INT_ARGB

Categories