为什么编辑PNG文件导致tEXt消失?

时间:2018-11-20 05:08:42

标签: png

这里真的需要一些建议。

我正试图手动将tEXt块添加到现有的PNG文件中,只是出于学习目的。

在经过仔细编辑图像后,例如,从图像上删除一小部分或旋转并保存,我的tEXt块不见了。也许我的代码的某些部分出错了,一​​些评论将不胜感激。

byte[] RAWFILEBYTES = new byte[(int) pngFile.length()];
            FileInputStream ins = new FileInputStream(pngFile);

        for (int i = 0; i < RAWFILEBYTES.length; i++) {
            RAWFILEBYTES[i] = (byte) ins.read();
        }

        byte[] size = {(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0e};
        byte[] crc32 = new byte[4];
        String chunkNameAndKey = "tEXtGreeting";
        String value = "hello";

        //Declaring size equal to the length of chunk name + key value pair
        byte[] tEXtAndValue = new byte[chunkNameAndKey.getBytes().length + 1 + value.getBytes().length];

        //Forming byte array of chunk name and key value pair
        System.arraycopy(chunkNameAndKey.getBytes(), 0, tEXtAndValue, 0, chunkNameAndKey.getBytes().length);
        tEXtAndValue[chunkNameAndKey.getBytes().length] = (byte) 0x00; //Follow specification key pair value separate by null
        System.arraycopy(value.getBytes(), 0, tEXtAndValue, chunkNameAndKey.getBytes().length + 1, value.getBytes().length);

        //Calculating checksum comprise of chunk name and value
        //E.g. tEXtGreeting[null]hello
        Checksum checksum = new CRC32();
        checksum.update(tEXtAndValue, 0, tEXtAndValue.length);

        //Convert checksum result to 4 bytes according to PNG.
        ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
        buffer.putLong(checksum.getValue());   
        System.arraycopy(buffer.array(), buffer.array().length - 4, crc32, 0, 4);

        //Entire tEXt chunk comprise of size, chunk name, key-value pair and CRC in order.
        byte[] textChunkArr = new byte[4 + tEXtAndValue.length + 4];
        System.arraycopy(size, 0, textChunkArr, 0, size.length);
        System.arraycopy(tEXtAndValue, 0, textChunkArr, size.length, tEXtAndValue.length);
        System.arraycopy(crc32, 0, textChunkArr, size.length + tEXtAndValue.length, crc32.length);

        byte[] byte_array = new byte[RAWFILEBYTES.length + textChunkArr.length];

        //Place the text chunk directly before IEND chunk.
        System.arraycopy(RAWFILEBYTES, 0, byte_array, 0, RAWFILEBYTES.length - 12);
        System.arraycopy(textChunkArr, 0, byte_array, RAWFILEBYTES.length - 12, textChunkArr.length);
        System.arraycopy(RAWFILEBYTES, RAWFILEBYTES.length - 12, byte_array, RAWFILEBYTES.length - 12 + textChunkArr.length, 12);

        try (FileOutputStream fos = new FileOutputStream("final2_file.png")) {
            fos.write(byte_array);
        }

总而言之,我要做的是,在IEND块之前直接创建并手动插入一个tEXt块。

0 个答案:

没有答案