如何有效地从png流/文件中读取位图和元数据?

时间:2012-12-28 23:34:20

标签: image bitmap png metadata

我需要使用[PNGJ](http://code.google.com/p/pngj/)库从PNG输入流解码位图和元数据。问题是解码元数据会推进流然后我无法使用 bitmap = BitmapFactory.decodeStream()。

我自己创建位图是可以的但是如果我需要比如使用插值来缩放位图,我宁愿使用BitmapFactory。要使用它,每次我必须使用PNGJ获取元数据和BitmapFactory来获取位图时,我必须创建一个InputStream副本。从单个PNGJ调用返回元数据和位图会很好(至少对于最常见的ARGB_8888格式)。

简而言之,我必须复制Java库使用的流,这看起来像是浪费。返回位图将是一种解决方案。

    // register an auxilary chunk name 
    PngChunk.factoryRegister(ThumbNailProvider.chunkID, chunkPROP.class); 

    // reader for the stream
    PngReader pngr = new PngReader(inStream, "debug label PNG reader");
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    PngWriter pngw = new PngWriter(outputStream, pngr.imgInfo);

    // copy pre-data chunks
    pngw.copyChunksFirst(pngr, ChunkCopyBehaviour.COPY_ALL_SAFE);

    // copy image data
    for (int row = 0; row < pngr.imgInfo.rows; row++) {
        ImageLine l1 = pngr.readRow(row);
        pngw.writeRow(l1, row);
    }

    // copy after-data chunks
    pngw.copyChunksLast(pngr, ChunkCopyBehaviour.COPY_ALL); 

    pngr.end(); // close inStream but not its copy
    pngw.end(); // close out stream

    // save a copy of the stream for Java Libraries;
    data.inputStream = new ByteArrayInputStream(outputStream.toByteArray());



    // read the chunk
    ChunksList chunkList = pngr.getChunksList();
    PngChunk chunk = chunkList.getById1(L2ThumbNailProvider.chunkID);
    if (chunk != null) {
    ... 
    }

1 个答案:

答案 0 :(得分:1)

这就是拥有两个独立的流消费者的问题,比如Class1.parse(inputStream)Class2.decode(inputStream),我们希望他们使用相同的单个流;它没有简单优雅的解决方案(eg),如果我们无法控制消费者如何吃流。

简单的解决方案,但不是非常优雅 - 并且可能不切实际 - 是:关闭并重新打开流(如果我们从网络流中读取则不可行),缓冲内存中的完整流内容或临时文件。

在具体案例中,我能想到的替代方案是:

1)让PNGJ使用和解码数据并自己创建位图,用setPixels()填充像素。除了其他不便之外,还需要您进行适当的颜色转换。

2)使用PngReader作为InputFilterStream,以便它只解析元数据并将完整的流传递给使用者。目前,如果不对PNGJ代码进行调整,这是不可能的。我将介绍一下,如果实现此功能,我将在此处发布。