测量旋转字符串Java的像素高度

Posted

技术标签:

【中文标题】测量旋转字符串Java的像素高度【英文标题】:Measure pixel height of rotated string Java 【发布时间】:2020-02-16 14:59:37 【问题描述】:

我正在尝试在 Java 中计算旋转字符串的像素高度。目前,我正在创建仿射变换并将其旋转所需的量。

然后,我从这个仿射变换中创建了一个派生字体。我还创建了一个 FontRenderContect 和一个 GlyphVector。

当我尝试从字形向量中获取像素边界时,它给了我文本的高度,就好像它没有被旋转一样

AffineTransform affineTransform = new AffineTransform();
affineTransform.rotate(Math.toRadians(45),0,0);

Font rotatedFont = font.deriveFont(affineTransform);

FontRenderContext frc = new FontRenderContext(affineTransform, true, false);


GlyphVector gv = rotatedFont.createGlyphVector(frc, "i");

System.out.println(gv.getPixelBounds(frc, 0, 0).getBounds());

gv = rotatedFont.createGlyphVector(frc, "iiiiiiiiiiii");
System.out.println(gv.getPixelBounds(frc, 0, 0).getBounds());

结果:

java.awt.Rectangle[x=0,y=1,width=9,height=2]
java.awt.Rectangle[x=0,y=1,width=31,height=2]

高度应该更大,因为它以 45 度角旋转(宽度应该等于高度)。

感谢任何帮助。

【问题讨论】:

旋转不应影响文本的宽度和高度。但是它会影响边界矩形的高度和宽度。 我怎样才能得到边界矩形。我找不到获取边界框的方法 【参考方案1】:

通过使用Shape 并将AffineTransform 直接应用于该形状,可以轻松确定边界框。

import java.awt.*;
import java.awt.geom.*;
import java.awt.font.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class BoundingBoxRotatedText 

    private JComponent ui = null;
    JLabel output = new JLabel();
    Font font = new Font(Font.SERIF, Font.PLAIN, 20);
    String string = "The quick brown fox jumps over the lazy dog";
    Shape textShape = getShapeOfText(font, string);
    Rectangle2D rectangle = textShape.getBounds2D();

    BoundingBoxRotatedText() 
        initUI();
    

    public final void initUI() 
        if (ui!=null) return;

        ui = new JPanel(new BorderLayout(4,4));
        ui.setBorder(new EmptyBorder(4,4,4,4));

        ui.add(output);
        output.setIcon(new ImageIcon(getImage()));
    

    public static Shape getShapeOfText(Font font, String msg) 
        BufferedImage bi = new BufferedImage(
                1, 1, BufferedImage.TYPE_INT_RGB);

        Graphics2D g = bi.createGraphics();

        FontRenderContext frc = g.getFontRenderContext();
        GlyphVector gv = font.createGlyphVector(frc, msg);

        return gv.getOutline();
    

    public static Shape moveShapeToCenter(Shape shape, int w, int h) 
        Rectangle2D b = shape.getBounds2D();
        double xOff = -b.getX() + ((w - b.getWidth()) / 2d);
        double yOff = -b.getY() + ((h - b.getHeight()) / 2d);
        AffineTransform move = AffineTransform.getTranslateInstance(xOff, yOff);
        return move.createTransformedShape(shape);
    

    private BufferedImage getImage() 
        int sz = (int)(rectangle.getBounds().width*1.2);
        BufferedImage bi = new BufferedImage(
                sz, sz, BufferedImage.TYPE_INT_RGB);

        Graphics2D g = bi.createGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, sz, sz);

        Shape shape = moveShapeToCenter(textShape, sz, sz);
        g.setColor(Color.GREEN);
        g.fill(shape);
        g.draw(shape);
        g.draw(shape.getBounds());

        AffineTransform rotate45 = AffineTransform.
                getRotateInstance(Math.PI/4, sz/2, sz/2);
        shape = rotate45.createTransformedShape(shape);
        g.setColor(Color.BLUE);
        g.fill(shape);
        g.draw(shape);
        g.draw(shape.getBounds());

        shape = rotate45.createTransformedShape(shape);
        g.setColor(Color.RED);
        g.fill(shape);
        g.draw(shape);
        g.draw(shape.getBounds());

        g.dispose();

        return bi;
    

    public JComponent getUI() 
        return ui;
    

    public static void main(String[] args) 
        Runnable r = () -> 
            try 
                UIManager.setLookAndFeel(
                        UIManager.getSystemLookAndFeelClassName());
             catch (Exception ex) 
                ex.printStackTrace();
            
            BoundingBoxRotatedText o = new BoundingBoxRotatedText();

            JFrame f = new JFrame(o.getClass().getSimpleName());
            f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            f.setLocationByPlatform(true);

            f.setContentPane(o.getUI());
            f.pack();
            f.setMinimumSize(f.getSize());

            f.setVisible(true);
        ;
        SwingUtilities.invokeLater(r);
    

【讨论】:

假人BufferedImageGraphics2D 真的对操作有用吗?还是return font.createGlyphVector(new FontRenderContext(null, true, false), msg) .getOutline(); 不够?

以上是关于测量旋转字符串Java的像素高度的主要内容,如果未能解决你的问题,请参考以下文章

具有非方形像素的图像旋转的宽度/高度缩放

如何正确测量文字高度

如何测量图像中每个极点的长度(以像素为单位)

NSString 文本像素长度

为啥在 Tkinter 中计算的字符串的像素宽度和高度因平台而异?

找到对象的几何中心并旋转它以最大化边界框高度