2016-11-02 10 views
0

背景の幅に合わせてフォントを拡大するのに問題があります。私は1000の高さと350の幅の背景を持っています、そして、私はそれが背景よりも大きいときにフォントを拡大しようとしています。 私は別のフォントでいくつかのテストを行いましたが、結果は同じで、一部の文字が欠落しているか、テキストの最後に空白があります。Java Graphics2Dスケールフォントで背景を塗りつぶす

import java.awt.Color; 
import java.awt.Font; 
import java.awt.FontMetrics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.geom.AffineTransform; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 

public class PruebaStackoverflow { 

public static void main(String[] args) { 

    String titleText = null; 
    Graphics2D g2D = null; 
    Font testFont = null; 

    File imageGrayBackgroundFile = new File(
      "resources/pruebaAltaResolucionGris.png"); 
    File destinationImageGray = new File("resources/outputTextGray.png"); 

    BufferedImage background = readImage(imageGrayBackgroundFile); 

    titleText = "Lorem ipsum dolor sit amet asdkf sdm"; 
    testFont = new Font("Lucida Console", Font.PLAIN, 50); 

    g2D = background.createGraphics(); 
    g2D.setColor(Color.BLACK); 
    g2D.setFont(testFont); 

    g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 
      RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 

    g2D = scaleFontFromFontMetrics(g2D, background, titleText); 

    g2D.drawString(titleText, 0, 150); 
    g2D.dispose(); 

    writeImage(destinationImageGray, background); 

} 

private static Graphics2D scaleFontFromFontMetrics(Graphics2D g2D, 
     BufferedImage backgroundImage, String text) { 
    double xScale; 
    double yScale; 
    double scale; 
    Integer backgroundWidth = null; 
    Integer backgroundHeight = null; 
    Integer textWidth = null; 
    Integer textHeigth = null; 

    backgroundWidth = backgroundImage.getWidth(); 
    backgroundHeight = backgroundImage.getHeight(); 

    Font f = g2D.getFont(); 
    FontMetrics fm = g2D.getFontMetrics(f); 

    textWidth = fm.stringWidth(text); 
    textHeigth = fm.getHeight(); 

    xScale = backgroundWidth/(double) textWidth; 
    yScale = backgroundHeight/(double) textHeigth; 

    if (xScale > yScale) { 
     scale = yScale; 
    } else { 
     scale = xScale; 
    } 

    g2D.setFont(f.deriveFont(AffineTransform.getScaleInstance(scale, scale))); 

    return g2D; 
} 

private static BufferedImage readImage(File sourceImage) { 
    BufferedImage bufferedImage = null; 
    try { 
     bufferedImage = ImageIO.read(sourceImage); 
    } catch (IOException e1) { 
     e1.printStackTrace(); 
    } 
    return bufferedImage; 
} 

private static void writeImage(File destinationImage, 
     BufferedImage bufferedImage) { 
    try { 
     ImageIO.write(bufferedImage, "png", destinationImage); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    System.out.println("Image Saved"); 
} 

}

これは "Loremのイプサム悲しみSDM asdkf AMET座る" スケーリングするテキストであり、これはテキストアフィン変換を用いてスケーリングされる:

これはコードです。

output image with font scaled and 'm' letter missed

私はあなたが私を助けるかもしれないことを願って、感謝

+0

それは、それが幅に最も近いフォントptサイズを選択しているためです。この場合、13ptではなく14ptですが、13ptは幅全体を「塗りつぶす」ことはありません。テキストを含む画像を作成して、画像を拡大してみる必要があるかもしれません。 –

答えて

0

あなたは文字列の長さを測定し、それはあなたのコンテンツに収まるかどうかを確認することができます。

int lengthInPixel = graphics.getFontMetrics().stringWidth("Lorem ipsum dolor sit amet asdkf sdm") 
0

これまでの私のコメントから、画像の幅に最も近いフォントサイズが使用される解決策があります。テキストは別のイメージに描画され、サイズ変更され、最終イメージに描画されます。これは、すべてcreateTextImage()メソッドで行われます。注:ファイルを使用するのではなく、背景イメージを作成しました。

結果は希望どおりにはっきりしない場合がありますが、サイズを変更するためのさまざまなアルゴリズムを試すことができます。うまくいけば、それはあなたに出発点を与えるでしょう。

import java.awt.Color; 
import java.awt.Font; 
import java.awt.Graphics2D; 
import java.awt.Image; 
import java.awt.geom.AffineTransform; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 

public class Main { 

    public static void main(String[] args) { 
     String titleText = "Lorem ipsum dolor sit amet asdkf sdm"; 
     Font initialFont = new Font("Lucida Console", Font.PLAIN, 50); 
     BufferedImage textImg = createTextImage(titleText, 350, 1000, 150, 
       initialFont, Color.BLACK, Color.GRAY); 
     writeImage(new File("outputTextGray.png"), textImg); 
    } 

    private static BufferedImage createTextImage(String text, int targetWidth, 
      int targetHeight, int textYOffset, Font font, Color textColor, Color bgColor) { 

     // The final image 
     BufferedImage finalImg = createBackgroundImg(targetWidth, targetHeight, bgColor); 
     Graphics2D finalImgG = finalImg.createGraphics();   
     Font closestFont = scaleFont(finalImg, font, text); 
     finalImgG.setFont(closestFont); 

     // Create new image to fit text 
     int textWidth = finalImgG.getFontMetrics().stringWidth(text); 
     int textHeight = finalImgG.getFontMetrics().getHeight(); 
     BufferedImage textImg = createBackgroundImg(textWidth, textHeight * 2, bgColor); 

     // Draw text 
     Graphics2D textImgG = textImg.createGraphics(); 
     textImgG.setFont(closestFont); 
     textImgG.setColor(textColor); 
     textImgG.drawString(text, 0, textHeight); 

     // Scale text image 
     double scale = getScale(textImg.getWidth(), textImg.getHeight(), 
       targetWidth, targetHeight); 
     Image resized = textImg.getScaledInstance((int) (textImg.getWidth() * scale), 
       (int) (textImg.getHeight() * scale), Image.SCALE_SMOOTH); 

     // Draw text image onto final image 
     finalImgG.drawImage(resized, 0, textYOffset, null); 
     return finalImg; 
    } 

    private static Font scaleFont(BufferedImage img, Font font, String text) { 
     Graphics2D g2D = img.createGraphics(); 
     g2D.setFont(font); 
     double scale = getScale(g2D.getFontMetrics().stringWidth(text), 
       g2D.getFontMetrics().getHeight(), img.getWidth(), 
       img.getHeight()); 
     return g2D.getFont().deriveFont(AffineTransform.getScaleInstance(scale, scale)); 
    } 

    private static double getScale(int width, int height, int targetWidth, int targetHeight) { 
     assert width > 0 && height > 0 : "width and height must be > 0"; 
     double scaleX = (double) targetWidth/width; 
     double scaleY = (double) targetHeight/height; 
     return scaleX > scaleY ? scaleY : scaleX; 
    } 

    private static BufferedImage createBackgroundImg(int width, int height, Color color) { 
     BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
     for (int x = 0; x < bufferedImage.getWidth(); x++) { 
      for (int y = 0; y < bufferedImage.getHeight(); y++) { 
       bufferedImage.setRGB(x, y, color.getRGB()); 
      } 
     } 
     return bufferedImage; 
    } 

    private static void writeImage(File destinationImage, 
      BufferedImage bufferedImage) { 
     try { 
      ImageIO.write(bufferedImage, "png", destinationImage); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     System.out.println("Image Saved"); 
    } 
} 
+0

ありがとう、それは私のためにうまくいくのですが、別の質問があります。私がバックグラウンドとしていくつかの画像で同じことをしなければならない場合、私は透明な背景で最初のスケール操作をしなければならないでしょうか?または別の方法がありますか? – SheenStvz

+0

@SheenStvzこの質問を確認するhttp://stackoverflow.com/questions/17271812/save-buffered-image-with-transparent-background –

0

ゲーム画面を特定の解像度に合わせるには、その最大限度をテストした後で、比率を事前に計算することが必要です。このような何かが(私はあなたのケースに私の実際のコードを変更):私のゲームでは

double calculateScaling(BufferedImage image, String text, Font font){ 

    //These are final to avoid accidental mending, since they are 
    //the base for our calculations. 
    //Belive me, it took me a while to debug the 
    //scale calculation when I made this for my games :P 

    /** 
    * imageWidth and imageHeight are the bounds 
    */ 
    final int imageWidth = image.getWidth(); 
    final int imageHeight = image.getHeight(); 

    Graphics2D g2 = image.createGraphics(); 
    FontMetrics fm = g2.getFontMetrics(font); 


    /** 
    * requestedStringWidthSize e requestedStringHeightSize are the measures needed 
    * to draw the text WITHOUT resizing. 
    */ 
    final int requestedStringWidthSize = fm.stringWidth(text); 
    final int requestedStringHeightSize = fm.getHeight(); 


    double stringHeightSizeToUse = imageHeight; 
    double stringWidthSizeToUse; 

    double scale = stringHeightSizeToUse/requestedStringHeightSize; 
    stringWidthSizeToUse = scale*requestedStringWidthSize; 

    /** 
    * Checking if fill in height makes the text go out of bound in width, 
    * if it does, it rescalates it to size it to maximum width. 
    */ 
    if(imageWidth < ((int)(Math.rint(stringWidthSizeToUse)))) { 
     stringWidthSizeToUse = imageWidth; 

     scale = stringWidthSizeToUse/requestedStringWidthSize; 
     //stringHeightSizeToUse = scale*requestedStringHeightSize; 
    } 

    g2.dispose(); //we created this to use fontmetrics, now we don't need it. 

    return scale; 
} 

、私は、実行時に重い計算を避けるために、フロートの代わりに、二重のように、スケールを格納しますが、あなたのためにそれだけで簡単ですスケーリング、そう?

ここで行う必要があることは、コードを調べてそれをあなたのものに実装することだけです。

私は助けてくれることを願っています。

よろしくお願いいたします。 :)

関連する問題