Cannot get right height of text in java.awt.BufferdImage/Graphics2D - java

Im creating a servlet that renders a jpg/png with a given text. I want the text to be centered on the rendered image. I can get the width, but the height i'm getting seems to be wrong
Font myfont = new Font(Font.SANS_SERIF, Font.BOLD, 400);
BufferedImage image = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
g.setFont(myfont);
g.setColor(Color.BLACK);
FontMetrics fm = g.getFontMetrics();
Integer textwidth = fm.stringWidth(imagetext);
Integer textheight = fm.getHeight();
FontRenderContext fr = g.getFontRenderContext();
LineMetrics lm = myfont.getLineMetrics("5", fr );
float ascent = lm.getAscent();
float descent = lm.getDescent();
float height = lm.getHeight();
g.drawString("5", ((imagewidth - textwidth) / 2) , y?);
g.dispose();
ImageIO.write(image, "png", outputstream);
These are the values I get:
textwidth = 222
textheight = 504
ascent = 402
descent = 87
height = 503
Anyone know how to get the exact height om the "5" ? The estimated height should be around 250

It's still a bit off, but much closer (288): ask the Glyph (the actual graphical representation)
GlyphVector gv = myfont.createGlyphVector(fr, "5");
Rectangle2D bounds = gv.getGlyphMetrics(0).getBounds2D();
float height = bounds.height();
Other Glyph methods (getGlyphVisualBounds, getGlyphPixelBounds, ...) return the same value. This is the region of the affected pixels when the glyph is drawn, so you won't get a better value IMO

FontRenderContext frc = gc.getFontRenderContext();
float textheight = (float) font.getStringBounds(comp.text, frc).getHeight();

Related

Java Graphics2D drawString result confusion when scale Font size

I use drawString by Font1, suppose deriveFont is 20f.
final int width = fontMetrics.stringWidth(text);
final int height = fontMetrics.getHeight();
BufferedImage rendered = new BufferedImage(
width, height, BufferedImage.TYPE_INT_ARGB
);
System.out.println("render:" + width + "," + height);
final Graphics2D gOfRendered = (Graphics2D) rendered.getGraphics();
gOfRendered.setRenderingHints(getRenderingHints());
gOfRendered.setColor(fontColor);
gOfRendered.setFont(fontMetrics.getFont());
gOfRendered.drawString(
text, 0, height - fontMetrics.getMaxDescent() - fontMetrics.getLeading()
);
result:
But when I scale font size(scale=4 result maybe normal,scale=8 will cause error result):
final Font font = (wordFrequency.hasFont() ? wordFrequency.getFont() : kumoFont).getFont().deriveFont(fontHeight * 1.0f);
final Font font2 = (wordFrequency.hasFont() ? wordFrequency.getFont() : kumoFont).getFont().deriveFont(fontHeight * scale * 1.0f);
final FontMetrics fontMetrics = graphics.getFontMetrics(font);
final FontMetrics fontMetrics2 = graphics.getFontMetrics(font2);
and render again:
final int width = fontMetrics2.stringWidth(text);
final int height = fontMetrics2.getHeight();
BufferedImage rendered = new BufferedImage(
width, height, BufferedImage.TYPE_INT_ARGB
);
final Graphics2D gOfRendered = (Graphics2D) rendered.getGraphics();
// set the rendering hint here to ensure the font metrics are correct
gOfRendered.setRenderingHints(getRenderingHints());
gOfRendered.setColor(fontColor);
gOfRendered.setFont(fontMetrics2.getFont());
gOfRendered.drawString(
text, 0, height - fontMetrics2.getMaxDescent() - fontMetrics2.getLeading()
);
Error result(scale=8):
I find final int width = fontMetrics2.stringWidth(text); is not 8 times the font width,the Numbers are very different,How to fix it?Thank you!

Infinite while loop in Java application

In my Java application i am trying to resize an image until it fits a required dimension but still keeping its original scale.
the following method is used for resizing the image.
public BufferedImage ImageScaler(BufferedImage image){
scaledWidth = (int) image.getWidth() / SCALE_FACTOR * 100;
scaledHeight = (int) image.getHeight() / SCALE_FACTOR * 100;
scaledImage = resize(image, scaledHeight, scaledWidth);
while(scaledHeight > 150){
scaledHeight = scaledImage.getHeight();
scaledWidth = scaledImage.getWidth();
scaledImage = resize(image, scaledHeight, scaledWidth);
scaledHeight = scaledImage.getHeight();
scaledWidth = scaledImage.getWidth();
}
return scaledImage;
}
the while loop goes into an infinte loop. please help.
resize method.
private static BufferedImage resize(BufferedImage img, int height, int width) {
java.awt.Image tmp = img.getScaledInstance(width, height, java.awt.Image.SCALE_SMOOTH);
BufferedImage resized = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = resized.createGraphics();
g2d.drawImage(tmp, 0, 0, null);
g2d.dispose();
return resized;
}
Your code doesn't actually change anything. Suppose that when it goes into the loop, the width and height are both 200; the first two lines merely set scaledHeight and scaledWidth to 200, the third edits the image to conform to said variables, and then the fourth and fifth line set it to.. Exactly the same dimensions again. If after the initial resizing before the loop scaledHeight doesn't reach 150, it never will.

Text doesnot rotate Graphics2D

I checked on site and followed all examples.
I have written the code, the position, font of text changes but the angle or rotation doesnt take place. Any help advice pointers are much appreciated
int x = X;
int y = Y;
int w = 9;
int h = 9;
int fontsize = 7;
Rectangle bounds = new java.awt.Rectangle(x, y, w, h);
ShapeGroup group = new ShapeGroup();
group.setAnchor(bounds);
slide.addShape(group);
Graphics2D graphics = new PPGraphics2D(group);
AffineTransform affineTransform = new AffineTransform();
affineTransform.rotate(50);
java.awt.Shape circle = new Ellipse2D.Float(x, y, 9, 9);
graphics.draw(circle);
graphics.setPaint(colorRating);
graphics.fill(circle);
//graphics.rotate(-Math.PI/2);
graphics.setColor(new Color(159, 78, 15));
Font font = new Font("Arial", Font.BOLD, fontsize);
Font rotatedFont = font.deriveFont(affineTransform);
graphics.setFont(rotatedFont);
graphics.setTransform(affineTransform);
graphics.drawString(siteName, x + 11, y + fontsize + 1);
graphics.setFont(font);
I reported a similar bug to vldocking project: when used on MacOS, tab titles didn’t rotate 90° when the tabs were on the left/right. After investigating further, I submitted a patch, which amounted to one line:
graphics.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
Without antialiasing, the text rendering took an optimized path, which skipped the ability to rotate the glyphs.
I don’t know if you are on a MacOS, with the same java implementation. Try setting the antialiasing attribute, and if that doesn’t work, some other rendering hints as well.
Good luck!

How to zoom a buffered image?

I am trying to create a Plagiarism checker software. Till now I have created a buffered Image which converts any text written in an text area into a png,jpg,jpeg, gif format.
When I open the image text written inside the image is shown too small and it is shown properly only when I manually zoom my screen from keyboard or Mouse.
I have tried several techniques to zoom out or reposition the image but failed. How could I achieve a zoomed in image?
Here is my Code.
String text = textArea.getText();
Font font = new Font("Tahoma", Font.PLAIN, 40);
FontRenderContext frc = new FontRenderContext(null, true, true);
//get the height and width of the text
Rectangle2D bounds = font.getStringBounds(text, frc);
int w = (int) bounds.getWidth();
int h = (int) bounds.getHeight();
String[] parts = text.split("\n");
//create a BufferedImage object
BufferedImage img = new BufferedImage(w, h * parts.length, BufferedImage.TYPE_INT_RGB);
//calling createGraphics() to get the Graphics2D
Graphics2D g = img.createGraphics();
//set color and other parameters
g.setColor(Color.WHITE);
g.setFont(font);
int index = 0;
for(String part : parts){
g.drawString(part, 4000, h * index++);
}
g.dispose();

Wrapping/Rotating text on a image using graphics2D

void multiLine (int x, int y, String label, Graphics2D g) {
AffineTransform fontAT = new AffineTransform();
Font theFont = g.getFont();
fontAT.rotate(-Math.PI / 2);
Font theDerivedFont = theFont.deriveFont(fontAT);
g.setFont(theDerivedFont);
AttributedString attrStr = new AttributedString(label);
// Get iterator for string:
AttributedCharacterIterator characterIterator = attrStr.getIterator();
// Get font context from graphics:
FontRenderContext fontRenderContext = g.getFontRenderContext();
// Create measurer:
LineBreakMeasurer measurer = new LineBreakMeasurer(characterIterator,
fontRenderContext);
while (measurer.getPosition() < characterIterator.getEndIndex()) {
TextLayout textLayout = measurer.nextLayout(200);
y += textLayout.getAscent(); //Have tried changing y to x
textLayout.draw(g, x, y);
y += textLayout.getDescent() + textLayout.getLeading(); //Have tried changing y to x
}
g.setFont(theFont);
}
I am expecting this to print lines vertically but it does not , any ideas about how can I resolve this.
This outputs texts horizontally wrapped.
Edit: Changed the question to correctly reflect what I am trying to achieve
Reduce your wrapping width. 200 is too large, so it is not wrapping. Set it to 0, if you want each character on a new line.
TextLayout textLayout = measurer.nextLayout(0);

Categories