How to render small utf fonts in a high quality bufferedImage - java

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?

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.

Java rescaling an image creating half white half grey image

I am having a problem with the Grapics2D API, I am trying to re-size an image but instead of getting the smaller image its showing a half white and half grey area. what am I doing wrong? I tried with and without render hints and it didn't work, or is there another approach that will give me a new Buffered Image object at the specified size?
//height = 400, width = 600, capture_rect = screen size
BufferedImage img = robot.createScreenCapture(CAPTURE_RECT);
BufferedImage resized = new BufferedImage(WIDTH, HEIGHT, img.getType());
Graphics2D g = resized.createGraphics();
g.drawImage(img, 0, 0, WIDTH, HEIGHT, 0, 0, img.getWidth(), img.getHeight(), null);
g.dispose();
setImage(resized);
See the article on Perils of Image.getScaledImage. It has some recommendations.
Here is some code it recommends:
private float xScaleFactor, yScaleFactor = ...;
private BufferedImage originalImage = ...;
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
int newW = (int)(originalImage.getWidth() * xScaleFactor);
int newH = (int)(originalImage.getHeight() * yScaleFactor);
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(originalImage, 0, 0, newW, newH, null);
}
It looks like you just need to specify the new width/height and it will do the scaling for you automatically.
Or maybe the problem is with the img.getType() method. You should be able to just using:
BufferedImage.TYPE_INT_RGB // (or ARGB)
See which works the best.

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

Resizing photos without text .. is RenderingHints necessary?

I am writing a quick little java class that resizes an image into various smaller sizes (thumbnail large/small/etc). I have seen examples that have RenderingHints in it. The output file is significantly larger than without.
My question is: Is it necessary to use RenderingHints if the images that are being resized have no text?
int IMG_WIDTH = 100;
int IMG_HEIGHT = 100;
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();
g.setComposite(AlphaComposite.Src);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
I started with a 45kb image, and the output difference is a 3kb file (without RenderingHints) versus a 24kb file (with RenderingHints)
I suppose, after reading the following stackoverflow.com question/answer:
Java Text on Image
I am inclined to think that RenderingHints will provide no benefit for me when the photos contain no text ... In which case, no text = no RenderingHints = smaller resized image

Categories