4

PNG 画像をロード (およびデコード) し、それらを Java で 1 次元配列に変換したいと考えています。ImageIO.read() を使用してこれを実行し、ピクセルを配列にコピーすることは明らかですが、2 倍のメモリ (ラスター + 最終配列) を消費し、必要以上の処理時間がかかります。

これについてどうすればよいですか?最悪の場合、PNG 仕様を自分で実装できますが、それはかなり複雑な作業のようです。理想的には、「プラグイン」できる PNG 実装が必要です。あまり理想的ではありませんが、(com.sun コードとは異なり) 理解しやすく、変更できる (そして許可される) PNG リーダーは問題ありません。

4

3 に答える 3

9

ピクセル データを配列として取得する場合は、 を使用ImageIO.read()して を取得してBufferedImageから、 を使用BufferedImage.getRaster().getDataBuffer()して を取得できますDataBuffer。そこから、BufferedImageをキャストする方法を決定するために、のタイプを確認する必要がありますDataBuffer。たとえば、TYPE_INT_RGB画像がある場合は、にキャストする必要があり、データを含むDataBufferIntを呼び出しDataBufferInt.getData()て取得できint[]ます。BufferedImageこの方法で得られるのはコピーではありません。.

ただし、これには大きな注意点がありImageIO.read()ます。多くの場合、必要なタイプの画像が得られません。たとえば、TYPE_CUSTOM を取得することがよくありますが、実際に必要なイメージ タイプにコピーする以外には何も役に立ちません。

そのImageIO.read()ため、幸運にも必要なImageIO.read()形式の画像が得られる場合にのみ、2 番目のコピーを作成せずに画像データを取得することができます。から利用可能なタイプを確認したい場合はImageIO、 を呼び出しImageIO.getImageReaders()Iterator、ストリームを読み取ることができると主張するすべてのリーダーを取得し、 を使用して、リーダーが読み取ることができる画像タイプをImageReader.getImageTypes(0)取得できます。Iteratorこのようにして、必要な画像タイプを提供するリーダーを見つけるかもしれませんが、息を止めないでください。

画像が巨大でない限り、コピーは実際にはかなり高速です。ただし、画像巨大な場合は、生の画像データを一度に1行ずつディスクに書き込むために使用する必要があるかもしれませんBufferedImage.getRGB()(ただし、圧縮して、 a を使用しますGZIPOutputStream)、元の画像をガベージコレクションし、新しいを作成しますBufferedImage最後にディスクから行を読み戻し、 を使用してそれらを新しいイメージに書き込みますBufferedImage.setRGB()。(私はほんの数日前にこれを行うために何かを書いたので、詳細はかなり新鮮です。そのための LGPL のソースはここにあります。)

于 2010-10-12T10:39:40.057 に答える
3

なぜ1D配列が必要なのですか?より大きな目的は何ですか?

その上で、推奨事項が決まります。

通常、PNGをメモリアクセス可能なビットマップにデコードし(正確にはそれをImageIO.read()返すBufferedImage)、そのピクセルに直接アクセスすることができます... 1D配列として(を使用してBufferedImage.getRaster().getDataBuffer())。

于 2010-10-12T09:39:03.343 に答える
0

Javaを使用するreadfully()

于 2010-10-12T10:01:25.137 に答える