[QUOTE=schlingel]BTW: Das von Google veröffentlichte Icon-Pack kanntest du?[/QUOTE]Ja, dass kannte ich. Aber das da haben mir die Icons teilweise nicht gefallen. Außerdem sind es auch nicht atemberaubend viele, sodass ich eh noch andere gebraucht hätte. Und das war ja auch nicht die Problemstellung. Ich hatte ja oben genanntes Font gefunden, dass mir eigentlich gefallen hatte. Problem war eben nur, dass es nur ein Font ist. Aber das habe ich jetzt ja auch gelöst (s.u.).
Warum nicht…
Quellcode
[spoiler]```package font2img;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.awt.image.RGBImageFilter;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.imgscalr.Scalr;
import org.imgscalr.Scalr.Method;
import org.imgscalr.Scalr.Mode;
public class IconCreator {
private static final String iconFont = "iconfont.ttf";
private static final int defaultSize = 32;
private static final Color defaultColor = Color.BLACK;
// ------------------------
// Private Attributes
private final String icon;
// ------------------------
// Constructors
public IconCreator(final int integer) {
this((char) integer);
}
public IconCreator(final char character) {
this(Character.toString(character));
}
public IconCreator(final String icon) {
this.icon = icon;
}
// ------------------------
// Public Methods
public void toFile(final String file) throws IOException, FontFormatException {
toFile(file, defaultSize, defaultColor);
}
public void toFile(final String file, final int size) throws IOException, FontFormatException {
toFile(file, size, defaultColor);
}
public void toFile(final String file, final Color color) throws IOException, FontFormatException {
toFile(file, defaultSize, color);
}
public void toFile(final String file, final int size, final Color color) throws IOException, FontFormatException {
if ((file == null) || !file.endsWith(".png")) {
throw new IllegalArgumentException("file has to be a .png-file! Invalid file=" + file);
}
final BufferedImage image = createImg(this.icon, size, color);
ImageIO.write(image, "PNG", new File(file));
}
// ------------------------
// Private Methods
private static BufferedImage createImg(final String text, final int size, final Color color) throws FontFormatException, IOException {
final int internalSize = size * 8;
final Color background = createBackground(color);
final Font font = loadFont(iconFont, internalSize);
// calculate the size of the text
final FontUtil util = new FontUtil(font, internalSize, text);
final int width = util.getWidth();
final int height = util.getHeight();
final int xOffset = (int) ((internalSize - width) / 2.0);
final int yOffset = (int) ((internalSize - height) / 2.0);
final BufferedImage image = createImage(internalSize);
final Graphics2D g = createGraphics(image, background);
g.setColor(color);
g.setFont(util.getFont());
setRenderingHints(g);
final int x = xOffset;
final int y = height - yOffset - (int) (internalSize / 7.5);
g.drawString(text, x, y);
final Image transparent = makeColorTransparent(image, background);
final BufferedImage result = Scalr.resize(toBufferedImage(transparent), Method.QUALITY, Mode.FIT_EXACT, size, Scalr.OP_ANTIALIAS);
return result;
}
private static Color createBackground(final Color color) {
return new Color(255 - color.getRed(), 255 - color.getGreen(), 255 - color.getBlue());
}
private static Graphics2D createGraphics(final BufferedImage image, final Color background) {
final Graphics2D g = (Graphics2D) image.getGraphics();
g.setColor(background);
g.fillRect(0, 0, image.getWidth(), image.getHeight());
return g;
}
private static BufferedImage createImage(final int size) {
return new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
}
private static Font loadFont(final String name, final double size) throws FontFormatException, IOException {
Font font = Font.createFont(Font.TRUETYPE_FONT, IconCreator.class.getResourceAsStream(name));
font = font.deriveFont((float) size);
return font;
}
private static Image makeColorTransparent(final Image image, final Color color) {
final ImageFilter filter = new RGBImageFilter() {
// the color we are looking for... Alpha bits are set to opaque
public int markerRGB = color.getRGB() | 0xFF000000;
@Override
public final int filterRGB(final int x, final int y, final int rgb) {
if ((rgb | 0xFF000000) == this.markerRGB) {
// Mark the alpha bits as zero - transparent
return 0x00FFFFFF & rgb;
}
else {
// nothing to do
return rgb;
}
}
};
final ImageProducer ip = new FilteredImageSource(image.getSource(), filter);
final Image result = Toolkit.getDefaultToolkit().createImage(ip);
return result;
}
private static BufferedImage toBufferedImage(final Image src) {
final int w = src.getWidth(null);
final int h = src.getHeight(null);
final int type = BufferedImage.TYPE_INT_ARGB; // other options
final BufferedImage dest = new BufferedImage(w, h, type);
final Graphics2D g2 = dest.createGraphics();
setRenderingHints(g2);
g2.drawImage(src, 0, 0, null);
g2.dispose();
return dest;
}
private static void setRenderingHints(final Graphics2D graphics) {
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
}
// ------------------------
// Private Class
private static final class FontUtil {
private final Font font;
private final int width;
private final int height;
public FontUtil(final Font font, final int size, final String text) {
final BufferedImage buffer = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
final Graphics2D temp = buffer.createGraphics();
setRenderingHints(temp);
FontRenderContext context = temp.getFontRenderContext();
Rectangle2D bounds = font.getStringBounds(text, context);
int width = (int) bounds.getWidth();
int height = (int) bounds.getHeight();
Font tempFont = font.deriveFont((float) size - 1);
while ((width > size) || (height > size)) {
context = temp.getFontRenderContext();
bounds = tempFont.getStringBounds(text, context);
width = (int) bounds.getWidth();
height = (int) bounds.getHeight();
tempFont = tempFont.deriveFont((float) tempFont.getSize() - 1);
}
this.font = tempFont;
this.width = width;
this.height = height;
}
public Font getFont() {
return this.font;
}
public int getWidth() {
return this.width;
}
public int getHeight() {
return this.height;
}
}
}
Zur erwähnen wäre noch, dass eine Version der [Scalr](http://www.thebuzzmedia.com/software/imgscalr-java-image-scaling-library/)-Bibliothek im Classpath liegen sollte, da ich in Zeile 108 diese nutze, um das Bild auf die gewünschte Größe zu verkleinern.
Die Nutzung ist ansonsten denkbar einfach:
```new IconCreator('a').toFile("C:\\myIcon.png", 32, Color.Green);```
Generiert das Zeichen, dass im Font (einstellbar über die Konstante `iconFont` in der Klasse `IconCreator`) "a" entspricht in der Größe 32x32 Pixel in grün in die Datei "C:\\myIcon.png". Die Datei muss immer eine png-Datei sein, sonst gibts ne Fehlermeldung. Die font-datei muss neben der Klasse liegen, da über ein simples "getResources" drauf zugegriffen wird.
Bei größeren Bildern (>1024) kann die Generierung etwas dauern, da ich das Bild intern erst auf ein 8faches hochskaliere, um nachher ne vernünftige Qualität zu haben. (Kann bestimmt optimiert werden).
Ich weiß, man könnte noch ein paar Sachen verbessern, aber für mich reicht es so, darum bekommt ihr auch nur diese Version. Fühlt euch frei sie für was auch immer zu gebrauchen. Fehler dürft ihr gerne ausbessern. Falls ihr den Code produktiv verwendet wäre ein Hinweis auf mich als Original-Autor wünschenswert aber nicht zwingend ;).
Ich werde obigen Code nicht pflegen oder in irgendeiner Weise Support dafür geben. Kommentare sind natürlich trotzdem gerne gesehen. :)
Hoffe damit zukünftigen Suchenden einen Hinweise gegeben zu haben. ;P