将 BufferedImage 转换为 Pixmap

问题描述 投票:0回答:1

有没有办法将 BufferedImage 转换为 X11 Pixmap?看起来 JNA 有

com.sun.jna.platform.unix.X11.Pixmap
,但我找不到将任何内容转换为该格式的方法。

java x11 jna
1个回答
0
投票

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 + "\".");
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.