7

大きな画像(18000 x 18000)をアプリケーションにロードしたい。BufferedImageタイプで使用する場合int_rgb、ロードするには約1235mbのヒープメモリが必要です。これは非常に大量のメモリであり、エンドユーザーのRAMは少なくなる可能性があります(1GB以下)。

開発用PCで、MyEclipse IDEからイメージをロードすると、メモリが不足しますException。コードを実行可能jarにパックして、Eclipseの外部のPCで実行すると、例外がスローされます。

1235MBのメモリを使用せずに、バッファリングされた画像を使用してこのような大きな画像をアプリケーションにロードするにはどうすればよいですか?画像のセグメンテーションのように画像を小さな部分に分割するようなトリックはありますか?

私はこのスレッドをSOで見つけましたが、私には役に立ちませんでした。画像をに読み込んでから、クラスを使用してBufferedImage描画したいと思います。PanelGraphics

4

2 に答える 2

6

パッケージのImageReadParamを使用して、画像のフラグメントを読み取って表示できます。これは、画像全体を読み取らずにImageIOを使用して単一のフラグメントを読み取る方法を示す基本的な例です。ImageReadParam

import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.swing.*;

public class TestImageChunks {
    private static void createAndShowUI() {
        try {
            URL url = new URL(
                    "http://duke.kenai.com/wave/.Midsize/Wave.png.png");
            Image chunk = readFragment(url.openStream(), new Rectangle(150,
                    150, 300, 250));
            JOptionPane.showMessageDialog(null, new ImageIcon(chunk), "Duke", 
                    JOptionPane.INFORMATION_MESSAGE);
        } catch (IOException e) {
            JOptionPane.showMessageDialog(null, e.getMessage(), "Failure",
                    JOptionPane.ERROR_MESSAGE);
            e.printStackTrace();
        }
    }

    public static BufferedImage readFragment(InputStream stream, Rectangle rect)
            throws IOException {
        ImageInputStream imageStream = ImageIO.createImageInputStream(stream);
        ImageReader reader = ImageIO.getImageReaders(imageStream).next();
        ImageReadParam param = reader.getDefaultReadParam();

        param.setSourceRegion(rect);
        reader.setInput(imageStream, true, true);
        BufferedImage image = reader.read(0, param);

        reader.dispose();
        imageStream.close();

        return image;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowUI();
            }
        });
    }
}

結果は次のようになります。

ここに画像の説明を入力してください

于 2013-03-01T02:20:34.433 に答える
2

通常、次のようなことを行う必要があります。

  • 画像を管理可能なサイズの画像ファイルに分割し、アプリケーションとともにディスクに保存します。
  • この画像の特定の部分を表示する場合、ビューポートと重なる画像フラグメントのみをロードして表示します。
  • 画像をパンしながら、ロードおよび表示された画像フラグメントを適切に更新します。
  • 不要な画像フラグメントをGCに収集させるか、古い画像フラグメントを上書きするように新しい画像フラグメントをロードします。(これは、プールされたメモリバッファにロードされる同じサイズの画像フラグメントについて最後に議論します。)
于 2013-02-28T18:26:26.860 に答える