java - 我一直在用 Java 将一个非常大的二进制文件转换为 PNG

标签 java image binary png chunks

上下文

我正在尝试将二进制文件(这是一个原始内存文件,从 QEmu 监视器的 pmemsave 指令转储)转换为具有 RGB 颜色的 PNG 文件。这意味着 PNG 文件的 1 像素中每 3 个字节等于红-绿-蓝颜色。

我的想法如下:

content in binary file: 10001000 10100010 11000101 # and so on...
convert to RGB color in 1 pixel of PNG file: #88a2c5

在我的想象中,这个程序的工作流程是这样的:

# define the chunk size is 128MB
CHUNK_SIZE = 134217728 

# create new png file
png.new("dest.png", format=RGB)

# open file for writing content
png.open_for_read()

while not end of source file: 
  data = source.read(CHUNK_SIZE)
  # another process...
  png.append(data)

png.save_on_disk()

问题

我认为使用 javax 中的 ImageIO 可以很容易地做到这一点。但我的源文件非常大(大小几乎 2.1GB),因此 ImageIO.write 方法也无法处理。默认情况下,此方法不支持分块(如果目标文件中存在内容,它将销毁该内容)。

如何解决这个问题?我真的很高兴能够拥有任何具有 Java 现代功能的解决方案(例如 stream 或其他东西)

最佳答案

下面的代码使用 pngj 2.1.2.1

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import ar.com.hjg.pngj.FilterType;
import ar.com.hjg.pngj.ImageInfo;
import ar.com.hjg.pngj.PngWriter;

public class RGB1 {

public static void main(String[] args) throws IOException {

    final int CHUNK_SIZE = 134217728;
    final int SIDE = 5; // Dimensions hard coded to square 5 X 5, please change as needed

    byte[] buf = new byte[CHUNK_SIZE];

    int br, i,j,row=0;
    int[] arr = new int[SIDE*3];// 3 Bytes per pixel

    FileInputStream fileInputStream=new FileInputStream("C:\\Don\\source.bin");
    OutputStream os = new FileOutputStream("C:\\Don\\dest.png");

    ImageInfo imi = new ImageInfo(SIDE, SIDE, 8, false);

    PngWriter pngw = new PngWriter(os, imi);
    pngw.setCompLevel(9);// maximum compression
    pngw.setFilterType(FilterType.FILTER_ADAPTIVE_FAST); 
    //Please Refer https://github.com/leonbloy/pngj/blob/master/src/main/java/ar/com/hjg/pngj/FilterType.java

    br = fileInputStream.read(buf);
    j=0; 
    System.out.println("Bytes Read: " + br);
    while(br>0)
    {
        for(i=0;i<br;i++)
        {
            arr[j++] = buf[i] & 0xFF;

            if(j==SIDE*3)
            {
                pngw.writeRowInt(arr);

                j=0;
                row++;
                if(row==SIDE) break;
            }

        }
        if(row==SIDE) break;
        br = fileInputStream.read(buf);
        System.out.println("Bytes Read: " + br);
    }

    pngw.end();

    System.out.println("Done.");
    fileInputStream.close();

}

}

关于java - 我一直在用 Java 将一个非常大的二进制文件转换为 PNG,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77016985/

相关文章:

java - 空闲标记 : freemarker. core.InvalidReferenceException

image - 使用 VueJs 复制或下载生成的 QR (vue-qrcode) 代码

java - 如何将带符号的十进制值转换为 32 位小端二进制字符串?

binary - 在 Perforce 中交换文件

php - BINARY 数据没有插入到从 BINARY(20) 列提取的 mysql 中?

java - for-each 不适用于表达式类型

java - Jersey JAXB 如何为 List 实现 MessageBodyWriter

java - 在 Java 中从 HTTPS URL 下载图像

java - Xml 到 Json 到 xml 可逆转换 json-lib

javascript - 带有图像的命运之轮(无 Canvas )