I'm trying to get a list of all english fonts and print some strings with them.
This is the code I use to create the images of the strings:
public static BufferedImage imageForString (String str, Font font) {
font = new Font(font.getName(), font.getStyle(), 400); //Can't trust people to size their own font -_-
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
int width = fm.stringWidth(str);
int height = fm.getHeight();
g2d.dispose();
try {
img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
} catch (Exception e) {
System.err.println("Problem printing: " + str + " " + "with font: " + font);
e.printStackTrace();
}
g2d = img.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.setFont(font);
fm = g2d.getFontMetrics();
g2d.setColor(Color.BLACK);
g2d.drawString(str, 0, fm.getAscent());
g2d.dispose();
return img;
}
I'm trying to print every letter of the alphabet separately in every font the system has that is capable of displaying english text. That's obviously not working because I keep getting exceptions thrown on the line I put the try/catch block around.
I'm using this to get a list of all fonts the system has (apparently it includes other languages?):
public static final Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
Here's the exception being thrown:
Problem printing: ' with font: java.awt.Font[family=Al Bayan,name=AlBayan,style=plain,size=400]
java.lang.IllegalArgumentException: Width (0) and height (601) cannot be <= 0
at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:999)
at java.awt.image.BufferedImage.<init>(BufferedImage.java:326)
at HashMaker.imageForString(HashMaker.java:48)
at HashMaker.getImgs(HashMaker.java:69)
at HashMaker.main(HashMaker.java:83)
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Coordinate out of bounds!
at sun.awt.image.IntegerInterleavedRaster.getDataElements(IntegerInterleavedRaster.java:201)
at java.awt.image.BufferedImage.getRGB(BufferedImage.java:911)
at ImageUtils.colIsWhite(ImageUtils.java:23)
at ImageUtils.parseImage(ImageUtils.java:40)
at Letter.<init>(Letter.java:24)
at HashMaker.main(HashMaker.java:85)`
It's not just the single quote, the exception is also thrown on latin characters such as a 'J'
Related
Java 8 and Mac OS (High Sierra) here. I have the following class TextOverlayer that reads an image off the file system and needs to overlay some red text onto the image, and then save that "overlayed" image as a different file on the file system:
public class TextOverlayer implements ImageObserver {
public static void main(String[] args) throws IOException {
// Instantiate a TextOverlayer and read a source/input image from disk
TextOverlayer textOverlayer = new TextOverlayer();
BufferedImage bufferedImage = ImageIO.read(Paths.get("/User/myuser/pix/sourceImage.jpg").toFile());
// Lay some text over the image at specific coordinates
BufferedImage drawn = textOverlayer.drawText(bufferedImage, "Some text");
// Write the overlayed image to disk
File outputfile = new File("/User/myuser/pix/targetImage.jpg");
ImageIO.write(drawn, "jpg", outputfile);
}
private BufferedImage drawText(BufferedImage old, String text) {
int w = old.getWidth() / 3;
int h = old.getHeight() / 3;
BufferedImage img = new BufferedImage(
w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.drawImage(old, 0, 0, w, h, this);
g2d.setPaint(Color.red);
g2d.setFont(new Font("Serif", Font.BOLD, 20));
FontMetrics fm = g2d.getFontMetrics();
int x = img.getWidth() - fm.stringWidth(text) - 5;
int y = fm.getHeight();
g2d.drawString(text, x, y);
g2d.dispose();
return img;
}
#Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
return false;
}
}
When this runs, no errors are thrown and the targetImage.jpg is successfully written to disk, except its just an image of a small black box. I would have expected targetImage.jpg to be the exact same as sourceImage.jpg, just with some extra text added to it at the desired coordinates (within the image).
Any ideas where I'm going awry?
You don't need the ImageObserver and you likely can't write an image with an alpha channel to a JPEG file with the included writers.
This works:
public class TextOverlayer {
public static void main(String[] args) throws IOException {
// Instantiate a TextOverlayer and read a source/input image from disk
TextOverlayer textOverlayer = new TextOverlayer();
BufferedImage bufferedImage = ImageIO.read(Paths.get("/User/myuser/pix/sourceImage.jpg").toFile());
// Lay some text over the image at specific coordinates
BufferedImage drawn = textOverlayer.drawText(bufferedImage, "Some text");
// Write the overlayed image to disk
File outputfile = new File("/User/myuser/pix/targetImage.jpg");
boolean result = ImageIO.write(drawn, "jpg", outputfile);
if (!result) {
System.out.println("FAILED");
}
}
private BufferedImage drawText(BufferedImage old, String text) {
int w = old.getWidth();
int h = old.getHeight();
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.drawImage(old, 0, 0, w, h, null);
g2d.setPaint(Color.red);
g2d.setFont(new Font("Serif", Font.BOLD, 20));
FontMetrics fm = g2d.getFontMetrics();
int x = img.getWidth() - fm.stringWidth(text) - 5;
int y = fm.getHeight();
g2d.drawString(text, x, y);
g2d.dispose();
return img;
}
}
I am trying to calculate image center(to add water marks)following - add-water-to-image and the results shows negative x, for some of the images, here is the math part:
int centerX = (sourceImage.getWidth() - (int) rect.getWidth()) / 2;
int centerY = sourceImage.getHeight() / 2;
and the entire function:
public void addTextWatermark(String text, File sourceImageFile, File destImageFile, int textSize) {
try {
BufferedImage sourceImage = ImageIO.read(sourceImageFile);
Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();
// initializes necessary graphic properties
AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f);
g2d.setComposite(alphaChannel);
g2d.setColor(Color.BLACK.darker());
//Font(fontName, fontStyle, foneSize)
g2d.setFont(new java.awt.Font("Arial", Font.BOLD, textSize));
FontMetrics fontMetrics = g2d.getFontMetrics();
//text - input text , g2d - Graphics2D
Rectangle2D rect = fontMetrics.getStringBounds(text, g2d);
// calculates the coordinate where the String is painted
int centerX = (sourceImage.getWidth() - (int) rect.getWidth()) / 2;
int centerY = sourceImage.getHeight() / 2;
// paints the textual watermark
g2d.drawString(text, centerX, centerY);
ImageIO.write(sourceImage, "png", destImageFile);
g2d.dispose();
} catch (IOException ex) {
System.out.println(ex.getMessage().toString());
}
}
1-Is there a way to ensure the math will work for all images?
2-Is there a diffrence between jpg and png in this calclation?
Thanks.
edit
The image sizes that was causeing it were:
1-to big(3000*3000).
2-to small(60*60).
With textSize(g2d.setFont(new java.awt.Font("Arial", Font.BOLD, textSize));) - 32 or less.
So I found 2 ways to handle this issue:
1- if x or y are smaller then 0 I have resize the image using resize-image
2- if the watermark is to small just increase text size - g2d.setFont(new java.awt.Font("Arial", Font.BOLD, textSize));
Thanks for all the help #jon Skeet.
Is there any java library that can be used to extract each character from a true type font (.ttf)?
Each character of the font, I want to:
Convert it to the image
Extract its code (ex: Unicode value)
Anyone can help to show me some tips on above purpose?
P.S: I want to figure out, how such this app made: http://www.softpedia.com/progScreenshots/CharMap-Screenshot-94863.html
This will convert a String to a BufferedImage:
public BufferedImage stringToBufferedImage(String s) {
//First, we have to calculate the string's width and height
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR);
Graphics g = img.getGraphics();
//Set the font to be used when drawing the string
Font f = new Font("Tahoma", Font.PLAIN, 48);
g.setFont(f);
//Get the string visual bounds
FontRenderContext frc = g.getFontMetrics().getFontRenderContext();
Rectangle2D rect = f.getStringBounds(s, frc);
//Release resources
g.dispose();
//Then, we have to draw the string on the final image
//Create a new image where to print the character
img = new BufferedImage((int) Math.ceil(rect.getWidth()), (int) Math.ceil(rect.getHeight()), BufferedImage.TYPE_4BYTE_ABGR);
g = img.getGraphics();
g.setColor(Color.black); //Otherwise the text would be white
g.setFont(f);
//Calculate x and y for that string
FontMetrics fm = g.getFontMetrics();
int x = 0;
int y = fm.getAscent(); //getAscent() = baseline
g.drawString(s, x, y);
//Release resources
g.dispose();
//Return the image
return img;
}
I think there isn't a way to get all the characters, you have to create a String or a char array where you store all the chars you want to convert to image.
Once you have the String or char[] with all keys you want to convert, you can easily iterate over it and convert call the stringToBufferedImage method, then you can do
int charCode = (int) charactersMap.charAt(counter);
if charactersMap is a String, or
int charCode = (int) charactersMap[counter];
if charactersMap is a char array
Hope this helps
I want to append bold text on image, only selected text should be bold.
String word="This is dummy text, this should be BOLD"
final BufferedImage image = ImageIO.read(new File(Background));
Graphics g = image.getGraphics();
g.drawString(word, curX, curY);
g.dispose();
ImageIO.write(image, "bmp", new File("output.bmp"));
You want to use an AttributedString and pass its iterator to drawString
static String Background = "input.png";
static int curX = 10;
static int curY = 50;
public static void main(String[] args) throws Exception {
AttributedString word= new AttributedString("This is text. This should be BOLD");
word.addAttribute(TextAttribute.FONT, new Font("TimesRoman", Font.PLAIN, 18));
word.addAttribute(TextAttribute.FOREGROUND, Color.BLACK);
// Sets the font to bold from index 29 (inclusive)
// to index 33 (exclusive)
word.addAttribute(TextAttribute.FONT, new Font("TimesRoman", Font.BOLD, 18), 29,33);
word.addAttribute(TextAttribute.FOREGROUND, Color.BLUE, 29,33);
final BufferedImage image = ImageIO.read(new File(Background));
Graphics g = image.getGraphics();
g.drawString(word.getIterator(), curX, curY);
g.dispose();
ImageIO.write(image, "png", new File("output.png"));
}
output.png:
You can set a Font on the Graphics object before you draw the String like this:
Font test = new Font("Arial",Font.BOLD,20);
g.setFont(test);
If you only want one word bold you'll have to call drawString twice, and set the font to bold only the second time.
Maybe this one will help - curX,curY should be updated after the first drawString probably, otherwise it will look quite nasty. :)
String word="This is text, this should be ";
final BufferedImage image = ImageIO.read(new File(Background));
Graphics g = image.getGraphics();
g.drawString(word, curX, curY);
Font f = new Font("TimesRoman", Font.Bold, 72);
g.setFont(f);
String word="BOLD";
g.drawString(word, curX, curY);
g.dispose();
ImageIO.write(image, "bmp", new File("output.bmp"));
I need print two words: "A" and "B" using java 2D
font size = 100;
"A" font family: Bodoni MT Poster Compressed
"B" font family: Arial
I writed below codes to do it:
BufferedImage image = new BufferedImage(400, 300, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
{//fill bg color
g.setColor(new Color(255,255,255));
g.fillRect(0, 0, image.getWidth(), image.getHeight());
}
int FONT_SIZE=100;//set font size
{//print A
g.setColor(new Color(0,0,0));
g.setFont(new Font("Bodoni MT Poster Compressed", Font.PLAIN ,FONT_SIZE));
g.drawString("A",0,FONT_SIZE);
}
{//print B
g.setColor(new Color(0,0,0));
g.setFont(new Font("Arial", Font.PLAIN ,FONT_SIZE));
g.drawString("B",FONT_SIZE,FONT_SIZE);
}
g.dispose();
I get the result image:
but I need like this (make by PhotoShop):
I think the question at g.drawString("B",FONT_SIZE,FONT_SIZE);
How can I get the font X offset width?
thanks for help :)
After you do the setFont, declare a variable like
FontMetrics fm = g.getFontMetrics();
int strA = fm.stringWidth("A"),
strB = fm.stringWidth("B"),
strH = fm.getHeight();
Now that you have all the dimensions of the letters, set their positions (px is distance from the left edge to the letter, py from the top to the baseline of the font)
int px = ..., py = ...
g.drawString ("A", px, py);
And similarly for "B". Hope that helps, - M.S.