3

私は 13255 個の画像を持っています。それぞれの幅は 240 x 240 ピクセルで、最大サイズは 15,412 バイト、最小サイズは 839 バイトです。

フォルダーをループして、それぞれを File[] に追加しようとしています。各画像の配列を取得したら、それらを BufferedImage[] 内に配置し、ループして、個々の画像で構成されるより大きな単一の画像に描画できるようにします。

各画像は次の形式で名前が付けられます。

画像 xy.png

ただし、 java.lang.OutOfMemoryError: Java heap space エラーが発生し続けます。理由がわかりません。Eclipse のターゲットの末尾にパラメーターを追加して、JVM で使用できるメモリのサイズを変更しようとしました。以下は私が使用したものです:

IDE's\eclipse-jee-juno-SR2-win32-x86_64\eclipse\eclipse.exe -vmargs -Xms64m -Xmx1024m

IDE's\eclipse-jee-juno-SR2-win32-x86_64\eclipse\eclipse.exe -vmargs -Xms64m -Xmx4096m

どちらも効果はありません。また、[コントロール パネル] -> [プログラム] -> [Java] に移動し、そこで使用できるメモリの量を変更しました。

ここに私が書いた方法があります:

public static void merge_images() throws IOException {
        int rows = 115; 
        int cols = 115;
        int chunks = rows * cols;

        System.out.println(chunks);

        int chunkWidth, chunkHeight;
        int type;
        // fetching image files
        File[] imgFiles = new File[chunks];

        int count = 0;
        for (int j = 1; j <= 115; j++) {
            for (int k = 1; k <= 115; k++) {
                imgFiles[count] = new File("G:\\Images\\Image " + j
                        + "-" + k + ".png");
                count++;
            }
        }
        System.out.println(imgFiles.length);

        // creating a buffered image array from image files
        BufferedImage[] buffImages = new BufferedImage[chunks];
        for (int i = 0; i < chunks; i++) {
            buffImages[i] = ImageIO.read(imgFiles[i]);
            System.out.println(i);
        }
        type = buffImages[0].getType();
        chunkWidth = buffImages[0].getWidth();
        chunkHeight = buffImages[0].getHeight();

        // Initializing the final image
        BufferedImage finalImg = new BufferedImage(chunkWidth * cols,
                chunkHeight * rows, type);

        int num = 0;
        for (int i = 0; i < rows; i++) {
            for (int k = 0; k < cols; k++) {
                finalImg.createGraphics().drawImage(buffImages[num], null,
                        chunkWidth * k, chunkHeight * i);
                num++;
            }
        }
        System.out.println("Image concatenated.....");
        ImageIO.write(finalImg, "png", new File("fusions.png"));
        System.out.println("Image Saved, Exiting");
    }

印刷ラインはこちら

for (int i = 0; i < chunks; i++) {
            buffImages[i] = ImageIO.read(imgFiles[i]);
            System.out.println(i);
}

常に 7320 ポイント付近で停止します。

これが正確なコンソール出力です

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.awt.image.DataBufferByte.<init>(Unknown Source)
    at java.awt.image.ComponentSampleModel.createDataBuffer(Unknown Source)
    at java.awt.image.Raster.createWritableRaster(Unknown Source)
    at javax.imageio.ImageTypeSpecifier.createBufferedImage(Unknown Source)
    at javax.imageio.ImageReader.getDestination(Unknown Source)
    at com.sun.imageio.plugins.png.PNGImageReader.readImage(Unknown Source)
    at com.sun.imageio.plugins.png.PNGImageReader.read(Unknown Source)
    at javax.imageio.ImageIO.read(Unknown Source)
    at javax.imageio.ImageIO.read(Unknown Source)
    at main.merge_images(main.java:48)
    at main.main(main.java:19)

私が間違っているアイデアは大歓迎です。

よろしく、

ジェイミー

4

5 に答える 5

4

すべてのチャンク イメージをメモリに保持する必要はありません。次のように、それらを 1 つずつ読み取り、最終ループで最終イメージに描画できます。

for (int i = 0; i < rows; i++) {
    for (int k = 0; k < cols; k++) {
        BufferedImage buffImage = ImageIO.read(imgFiles[num]);
        finalImg.createGraphics().drawImage(buffImage, null,
                chunkWidth * k, chunkHeight * i);
        num++;
    }
}

これにより、メモリの少なくとも半分が節約されます。

于 2013-05-15T21:05:42.000 に答える
0

-Xmx1024m またはより大きな値を指定して JVM を実行してみてください。この値はヒープ サイズです。

java -Xmx1024m -jar app.jar

また、IDE でこの値を増やすこともできます。

于 2013-05-15T21:03:17.803 に答える
0

hoaz が指摘したように (どうもありがとう) 必要以上の手順を踏んでいました。私の解決策は次のとおりです。

public static void merge_images() throws IOException {
        int rows = 115; // we assume the no. of rows and cols are known and each
                        // chunk has equal width and height
        int cols = 115;
        int chunks = rows * cols;

        System.out.println(chunks);

        // fetching image files
        File[] imgFiles = new File[chunks];

        int count = 0;
        for (int j = 1; j <= 115; j++) {
            for (int k = 1; k <= 115; k++) {
                imgFiles[count] = new File("G:\\Images\\Image " + j
                        + "-" + k + ".png");
                count++;
            }
        }

        // Initializing the final image
        BufferedImage finalImg = new BufferedImage(240 * cols,
                240 * rows, 13);

        int num = 0;
        for (int i = 0; i < rows; i++) {
            for (int k = 0; k < cols; k++) {
                BufferedImage buffImage = ImageIO.read(imgFiles[num]);
                finalImg.createGraphics().drawImage(buffImage, null,
                        240 * k, 240 * i);
                num++;
            }
        }
        System.out.println("Image concatenated.....");
        ImageIO.write(finalImg, "png", new File("fusions.png"));
        System.out.println("Image Saved, Exiting");
    }

基本的に、私が行ったことは BufferedImage[] を削除し、代わりに、最終的なイメージを構築しているときに、ネストされた for ループ中に新しい BufferedImage を作成することです。変数を使用するのではなく、画像の境界と各画像のタイプをハードコーディングしました。

正しい方向に向けてくれてありがとう。

よろしく

ジェイミー

于 2013-05-15T21:33:41.860 に答える