当前位置: 首页 > 知识库问答 >
问题:

在Java中转换任何文件到PNG

宇文修文
2023-03-14

我想将任何文件转换为PNG,并逆转这个过程,所有Java。

我想为图像使用一个int-RGB表单,并且文件中的字节是RGB整数中的一个字节。这应该会产生一个图像。

我只通过将字节存储为红色来实现这一点,但我不知道如何同时使用绿色和蓝色。

这是我目前使用的代码,它只使用红色,工作正常:

public static void fileToImage(String sourceFile, String imageFile) throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream(sourceFile));
    int size = ((int) Math.sqrt(dis.available())) + 2;
    BufferedImage image = new BufferedImage(size,size, BufferedImage.TYPE_INT_RGB);
    for (int y = 0; y < size; y++) {
        for (int x = 0; x < size; x++) {
            int red = dis.read(); // I'm using only red
            int green = 0; // default
            int blue = 0; // default
            int rgb = (0xFF << 24) | ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | (blue & 0xFF);
            image.setRGB(x, y, rgb);
        }
    }
    dis.close();
    ImageIO.write(image, "png", new File(imageFile));
}

public static void imageToFile(String imageFile, String outputFile) throws IOException {
    BufferedImage image = ImageIO.read(new File(imageFile));
    DataOutputStream dos = new DataOutputStream(new FileOutputStream(outputFile));
    for (int y = 0; y < image.getHeight(); y++) {
        for (int x = 0; x < image.getWidth(); x++) {
            int rgb = image.getRGB(x, y);
            int red = (rgb >> 16) & 0xFF;
            int green = (rgb >> 8) & 0xFF;
            int blue = rgb & 0xFF;
            dos.write(red); // I'm using only red
        }
    }
    dos.close();
}

编辑:好的,所以我已经修改了代码,这里是:

public static void fileToImage(String sourceFile, String imageFile) throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream(sourceFile));
    int size = ((int) Math.sqrt(dis.available())) + 2;
    BufferedImage image = new BufferedImage(size,size, BufferedImage.TYPE_INT_RGB);
    for (int y = 0; y < size; y++) {
        for (int x = 0; x < size; x++) {
            int red = dis.read();
            int green = dis.read();
            int blue = dis.read();
            int rgb = (0xFF << 24) | ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | (blue & 0xFF);
            image.setRGB(x, y, rgb);
        }
    }
    dis.close();
    ImageIO.write(image, "png", new File(imageFile));
}

public static void imageToFile(String imageFile, String outputFile) throws IOException {
    BufferedImage image = ImageIO.read(new File(imageFile));
    DataOutputStream dos = new DataOutputStream(new FileOutputStream(outputFile));
    for (int y = 0; y < image.getHeight(); y++) {
        for (int x = 0; x < image.getWidth(); x++) {
            int rgb = image.getRGB(x, y);
            int red = (rgb >> 16) & 0xFF;
            int green = (rgb >> 8) & 0xFF;
            int blue = rgb & 0xFF;
            dos.write(red);
            dos.write(green);
            dos.write(blue);
        }
    }
    dos.close();
}

这确实“有效”,但并不完全符合预期。在生成的PNG中有大量的黑色空间,因为我认为图像的“大小”是错误的。因此,当将PNG翻译回原始文件时,它会比原始文件大很多。

编辑:我现在遇到的问题是:例如,如果我使用fileToImage方法将包含以下内容的文本文件转换为PNG:hello world!然后我用imageToFile把它转换回来,输出是:hello world!SSSSSSSSS(S代表“空间”,共15个)

编辑:仍然不能解决这个问题。这是我正在使用的:

private static final int NAN = -1;

private static int readByte(DataInputStream dis) throws IOException {
    int b;
    try {
        b = dis.readByte();
    } catch (EOFException e) {
        b = NAN;
    }
    return b;
}

public static void fileToImage(String sourceFile, String imageFile) throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream(sourceFile));
    int size = ((int) Math.sqrt(dis.available())) + 2;
    BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
    for (int y = 0; y < size; y++) {
        boolean finished = false;
        for (int x = 0; x < size; x++) {
            int alpha = 3;
            int red = readByte(dis);
            int green = readByte(dis);
            int blue = readByte(dis);
            if (red == NAN) {
                alpha--;
                red = 0;
            }
            if (green == NAN) {
                alpha--;
                green = 0;
            }
            if (blue == NAN) {
                alpha--;
                blue = 0;
            }
            int rgb = ((alpha & 0xFF) << 24) | ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | (blue & 0xFF);
            image.setRGB(x, y, rgb);
            if (alpha < 3) {
                finished = true;
                break;
            }
        }
        if (finished) break;
    }
    dis.close();
    ImageIO.write(image, "png", new File(imageFile));
}

public static void imageToFile(String imageFile, String outputFile) throws IOException {
    BufferedImage image = ImageIO.read(new File(imageFile));
    DataOutputStream dos = new DataOutputStream(new FileOutputStream(outputFile));
    for (int y = 0; y < image.getHeight(); y++) {
        boolean finished = false;
        for (int x = 0; x < image.getWidth(); x++) {
            int rgb = image.getRGB(x, y);
            int alpha = (rgb >> 24) & 0xFF;
            int red = (rgb >> 16) & 0xFF;
            int green = (rgb >> 8) & 0xFF;
            int blue = rgb & 0xFF;
            if (alpha == 0) {
                finished = true;
                break;
            }
            if (alpha >= 1) dos.write(red);
            if (alpha >= 2) dos.write(green);
            if (alpha == 3) dos.write(blue);
        }
        if (finished) break;
    }
    dos.close();
}

共有2个答案

经俊茂
2023-03-14

您的代码似乎将连续的3个字节转换为一个像素。因为只有1/3的文件是彩色的,其余的2/3是空的。

要解决这个问题,只需将文件大小除以3。

int size = ((int) Math.sqrt(dis.available()/3)) + 2;
丌官子安
2023-03-14

我想你只需要稍微调整一下内环。一个小助手方法将使这件事更容易使用,虽然我确信我的草图有点难看:

int myReadByte(DataInputStream dis) {
    int b;
    try {
        b = dis.readByte():
    } catch (EOFException e) {
        b = 0;
    }
    return b;
}

现在有了这个助手。。。

for (int x = 0; x < size; x++) {
        int red = myReadByte(dis);
        int green = myReadByte(dis);
        int blue = myReadByte(dis);
        int rgb = (0xFF << 24) | ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | (blue & 0xFF);
        image.setRGB(x, y, rgb);

for (int x = 0; x < image.getWidth(); x++) {
        int rgb = image.getRGB(x, y);
        int red = (rgb >> 16) & 0xFF;
        int green = (rgb >> 8) & 0xFF;
        int blue = rgb & 0xFF;
        dos.write(red);
        dos.write(green);
        dos.write(blue);
    }
 类似资料:
  • 我用APKTool反向设计了一个Android应用程序,得到了一个。Smali文件作为源代码输出。我转换了。Smali文件和应用程序。Java文件。我成功地编辑了。Java文件,但现在我想把它们转换回。这样我就可以用新的重新编译应用程序了。Smali文件。当我离开的时候。Java文件,它没有重新编译,并给出了一些错误。我找不到任何关于编译的信息。Java到。所以我希望你们能帮我。 提前谢谢你。

  • 我有一个。ost文件脱机Outlook数据文件,我想提取该文件中的数据,如电子邮件、附件等。 为此,我没有为ost文件获得任何直接解析器,所以我可以提取其中的数据。我有代码从. pst文件中提取数据。 因此,根据我的要求,我想转换。ost文件到。java中的pst文件。感谢任何人的帮助。 我正在尝试下面的代码,但它给了我一个例外,我没有得到任何解决方案。 例外情况:

  • 我是java新手,fo试图将fo文件转换为pdf。我从这个链接复制了java,但我得到以下错误: 改变。。。log4j:WARN找不到记录器(org.apache.fop.util.ContentHandlerFactoryRegistry)的appender。log4j:警告请正确初始化log4j系统。线程“main”java中出现异常。lang.NoClassDefFoundError:org

  • 问题内容: 如何将文件转换为二进制文件?我的项目只需要它。我需要通过二进制文件加密文件。 问题答案: 如果您要访问ACTUAL BINARY形式,则读入文件并将每个字节转换为二进制表示形式… 编辑: 以下是一些代码,可将字节转换为带有位的字符串: 如果要访问文件中的字节,则只需使用以下代码(在第一种情况下也可以使用此代码): 要使用这两段代码,您现在可以遍历每个字节并使用以下位创建一个String

  • 问题内容: @Before可能会有一些重复的问题建议,我不认为可能是这种情况,请先阅读本章,我会尽量简短。标题给出了基本思路。 这是一个XML示例(案例1): 这是一个XML示例(案例2): 我从Google借用了这种XML,无论如何,我的对象并不总是相同的,有时还有像case2这样的额外元素。现在,我想从两种情况下生成这样的CSV: 这第一行是标头,它也应包含在csv中。我今天有一些有用的指向s

  • 问题内容: 我有一个.mwb格式的数据库。我想在日食中使用它,所以我需要将其转换为.sql格式。如果有人知道如何使用任何工具来做到这一点。我认为我的sql工作台可以做到这一点,但不知道该怎么做。 问题答案: 在菜单中单击“数据库”,然后单击“正向工程”(快捷键CTRL + G)。 更新: 您的.mwb文件是专有格式,还包含Workbench中图形表示的信息。生成的.sql文件是一个脚本,您的MyS