android 如何读写VP8L和ALPH块或Webp图像

vq8itlhq  于 2023-01-07  发布在  Android
关注(0)|答案(1)|浏览(223)

我正在尝试these classes写在纯java代码,用于编码的动画网页从静态图像列表。它是基于Google's Webp container specification。我试图修改代码,以修复一些错误。现在
问题:如果图像包含VP8L,则编码器不会生成有效的动画WEBP图像(它的空白图像与2.5MB的大小,提供2个图像与输入图像的大小)。如果我设置的质量,而压缩WEBP到100以下,然后它读取块为RIFF-WEBP-VP8X-ICCP-ALPH-VP8的顺序。它创建了一个动画图像与固体黑色背景。它可能会下降透明的背景数据,但它在每一帧都有动画效果。
用于写入ANMF块的代码:

// ANMF chunk
private void writeAnmf(WebpChunk chunk) throws IOException {

   write(new byte[] { 'A', 'N', 'M', 'F' });
   writeUInt32(chunk.payload.length + 24);

   writeUInt24(chunk.x); // 3 bytes (3)
   writeUInt24(chunk.y); // 3 bytes (6)
   writeUInt24(chunk.width); // 3 bytes (9)
   writeUInt24(chunk.height); // 3 bytes (12)
   writeUInt24(chunk.duration); // 3 bytes (15)

   BitSet bs = new BitSet(6);
   bs.set(1, chunk.useAlphaBlending);
   bs.set(0, chunk.disposeToBackgroundColor);
   write(bitSetToBytes(bs, 1)); // 1 byte (16)

   if (chunk.isLossless) {
      write(new byte[] { 'V', 'P', '8', 'L' }); // 4 bytes (20)
      Log.d(Tag,"writting vp8l ; isLossLess");
   } else {
      Log.d(Tag,"writting vp8 ; Lossy");
      write(new byte[] { 'V', 'P', '8', ' ' });
   }
   writeUInt32(chunk.payload.length-16h); // 4 bytes (24)
   write(chunk.payload);

}
// ANIM chunk
private WebpChunk readVp8x() throws IOException {
        int chunkSize = readUInt32();
        if (chunkSize != 10)
            throw new IOException("Expected 10 bytes for VP8X.");

        WebpChunk chunk = new WebpChunk(WebpChunkType.VP8X);

        byte[] flags = new byte[4];
        read(flags, 4);
        BitSet bs = BitSet.valueOf(flags);

        chunk.hasIccp = bs.get(0);
        chunk.hasAnim = bs.get(1);
        chunk.hasExif = bs.get(2);
        chunk.hasXmp = bs.get(3);
        chunk.hasAlpha = bs.get(4);

        chunk.width = readUInt24();
        chunk.height = readUInt24();

        debug(String.format("VP8X: size = %dx%d", chunk.width, chunk.height));
        return chunk;
    }

读取VP8L块的代码:

private WebpChunk readVp8l() throws IOException {
        Log.d(Tag,"readVp8l() body ");
        int chunkSize = readUInt32();

        WebpChunk chunk = new WebpChunk(WebpChunkType.VP8L);
        chunk.isLossless = true;
        chunk.payload = readPayload(chunkSize);

        debug(String.format("VP8L: bytes = %d", chunkSize));
        return chunk;
    }

将字节写入输出流的函数

private void write(byte[] bytes, int length) throws IOException {
        _outputStream.write(bytes, length);
        _offset += length;
    }

它读取块为RIFF [大小] WEBP-〉VP8X-ICCP-ALPH-VP8L,写入为RIFF [大小] WEBP-〉VP8X-ANIM-ANMF(第一帧),然后ANMF用于其余帧。这些代码出了什么问题?

vm0i2vca

vm0i2vca1#

通过更多检查找到解决方案。阅读ALPH:我们需要将Alpha数据(Alpha BitStream)存储在某个地方,以便在写入帧时使用。写入ANMF:在写ANMF时,在写ANMF元数据之后,我们需要分别写ALPH头〉比特流长度〉比特流。2我们还必须把这个长度加到ANMF块大小上。3 ALPH块必须在VP 8/VP 8L块之前写。

private void writeAnmf(WebpChunk chunk) throws IOException {
        write(new byte[] { 'A', 'N', 'M', 'F' });

        int alphSize = 0;
        if(chunk.alphaData != null){
            alphSize = 8+chunk.alphaData.length;
        }

        writeUInt32(chunk.payload.length + 24 + alphSize);

        writeUInt24(chunk.x); // 3 bytes (3)
        writeUInt24(chunk.y); // 3 bytes (6)
        writeUInt24(chunk.width); // 3 bytes (9)
        writeUInt24(chunk.height); // 3 bytes (12)
        writeUInt24(chunk.duration); // 3 bytes (15)

        BitSet bs = new BitSet(8);
        bs.set(0, true);
        bs.set(1, chunk.disposeToBackgroundColor);
        write(bitSetToBytes(bs, 1)); // 1 byte (16)

        if (chunk.alphaData != null){
            write(new byte[] { 'A', 'L', 'P', 'H' }); // 4
            writeUInt32(chunk.alphaData.length); // 4
            write(chunk.alphaData);
            Log.e("WebpDemo","ALPH ");
        }

        if (chunk.isLossless)
            write(new byte[] { 'V', 'P', '8', 'L' }); // 4 bytes (20)
        else
            write(new byte[] { 'V', 'P', '8', ' ' });

        writeUInt32(chunk.payload.length); // 4 bytes (24)
        write(chunk.payload);

    }

相关问题