有没有办法将 BufferedImage 转换为 X11 Pixmap?看起来 JNA 有
com.sun.jna.platform.unix.X11.Pixmap
,但我找不到将任何内容转换为该格式的方法。
XPM 格式非常简单。您确实需要创建一个颜色图,如果图像不使用 IndexColorModel,则需要检查图像的每个像素。
import java.io.IOException;
import java.io.Writer;
import java.nio.file.Path;
import java.nio.file.Files;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.stream.IntStream;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import javax.imageio.ImageIO;
// Reference: https://en.wikipedia.org/wiki/X_PixMap
public class XPixmapConverter {
public void convertToXPixmap(BufferedImage image,
Writer destination)
throws IOException {
int width = image.getWidth();
int height = image.getHeight();
int[] rgbValues;
if (image.getColorModel() instanceof IndexColorModel ic) {
int size = ic.getMapSize();
rgbValues = IntStream.range(0, size).map(ic::getRGB).toArray();
} else {
Set<Integer> rgb = new HashSet<>();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
rgb.add(image.getRGB(x, y));
}
}
rgbValues = rgb.stream().mapToInt(Integer::intValue).toArray();
}
int colorCount = rgbValues.length;
String allChars =
"abcdefghijklmnopqrstuvwxyz" +
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"0123456789.-";
int charsPerPixel = (int)
Math.ceil(Math.log(colorCount) / Math.log(allChars.length()));
destination.write("/* XPM */\n");
destination.write("static char * image[] = {\n");
destination.write("\"" + width + " " + height + " "
+ colorCount + " " + charsPerPixel + "\",\n");
Map<Integer, String> pixelReps = new HashMap<>();
int[] charIndices = new int[charsPerPixel];
StringBuilder builder = new StringBuilder(charsPerPixel);
for (int i = 0; i < colorCount; i++) {
int rgb = rgbValues[i];
builder.setLength(0);
for (int j = 0; j < charsPerPixel; j++) {
builder.append(allChars.charAt(charIndices[j]));
}
for (int j = 0; j < charsPerPixel; j++) {
if (++charIndices[j] < allChars.length()) {
break;
}
charIndices[j] = 0;
}
String pixelRep = builder.toString();
pixelReps.put(rgb, pixelRep);
boolean transparent = (rgb >>> 24) == 0;
destination.write("\"" + pixelRep + " c "
+ (transparent ? "None" :
String.format("#%06x", rgb & 0xffffff))
+ "\",\n");
}
for (int y = 0; y < height; y++) {
destination.write("\"");
for (int x = 0; x < width; x++) {
destination.write(pixelReps.get(image.getRGB(x, y)));
}
destination.write("\"");
if (y < height - 1) {
destination.write(",");
}
destination.write("\n");
}
destination.write("};");
}
public void convertToXPixmap(BufferedImage image,
Path destination)
throws IOException {
try (Writer writer = Files.newBufferedWriter(destination)) {
convertToXPixmap(image, writer);
}
}
public static void main(String[] args)
throws IOException {
XPixmapConverter converter = new XPixmapConverter();
for (String arg : args) {
Path source = Path.of(arg);
Path dest = Path.of(arg + ".xpm");
BufferedImage img = ImageIO.read(source.toFile());
converter.convertToXPixmap(img, dest);
System.out.println("Wrote \"" + dest + "\".");
}
}
}