2

次のステートメントを使用して、画像のピクセルをバイト配列に保持しています。

bytePixels = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();

次に、画像の縮小バージョンを作成し、このバイト配列を使用してImageIconに配置する必要があります。元の画像は巨大である可能性があるため、次のように新しいBufferedImageを作成することに注意してください。

public Icon getImageIcon(int newWidth, int newHeight) throws IOException {
  BufferedImage image = ImageIO.read(originalImageFile);
  BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, this.getType());
  Graphics2D g = resizedImage.createGraphics();
  g.drawImage(image, 0, 0, newWidth, newHeight, null);
  g.dispose();

  return new ImageIcon(resizedImage);
}

元の画像が大きい場合、OutOfMemoryErrorが発生する可能性が高いため、オプションではありません。

だから私の質問は:バイト配列の元のピクセルを使用して、より小さなサイズのImageIconを取得するための(メモリに関して)最も効率的な方法は何ですか?

4

2 に答える 2

1

OutOfMemory エラー、それは奇妙です。デフォルトの JVM ヒープ サイズは非常に大きいです。ほとんどの場合、100 MB を超えています。バッファリングされた画像、100 MB のピクセルあたり 4 バイトは次のようになります。

100 000 000 = x * 4 bytes
          x = 25 000 000 pixels

これは、ほぼ 5000 * 5000 ピクセルの画像を使用していることを意味します。次のコマンド ライン引数を使用して、最大ヒープ サイズを拡大してみてください。

java -XmX400M YourClass

また、バイト配列を使用してピクセルを保存しません。ただし、単純に BufferedImage として、この方法で画像データがメモリ内に 2 回存在しないことを確認できます。

于 2012-03-13T16:51:53.163 に答える
1

Scaled ImageGUI で使用する前にピクセル サイズを小さくする目的で使用します。Java Advanced Imaging (JAI)を探している実際のコードについては、 Image#getScaledInstance(int width, int height, int tips)を使用できます。

get に問題はありません。このコードを使用して、および/またはプロファイルOutOfMemoryErrorのパフォーマンスをテストできます。JVMJProfiler

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import java.io.ByteArrayOutputStream;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;

class ImageCacheTest {

    private JLabel imageLabel;
    private Dimension halfScreenSize;
    private Random random;
    private JProgressBar memory;
    private Font bigFont = new Font("Arial", Font.BOLD, 30);
    private int count = 0;
    private int startMem = 0;
    private int maxMem = 0;
    private int peakMem = 0;
    private int useMem = 0;

    ImageCacheTest() {
        startMem = ((int) Runtime.getRuntime().freeMemory());
        maxMem = ((int) Runtime.getRuntime().freeMemory());
        peakMem = ((int) Runtime.getRuntime().freeMemory());
        JPanel p = new JPanel(new BorderLayout(4, 4));
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        halfScreenSize = new Dimension(d.width / 2, d.height / 2);
        //halfScreenSize = new Dimension(d.width - 11, d.height - 101);
        //halfScreenSize = new Dimension(4000, 3000);
        random = new Random();
        imageLabel = new JLabel(new ImageIcon(convertToFromBytes(getImage())));
        memory = new JProgressBar(0, (int) Runtime.getRuntime().maxMemory());
        memory.setPreferredSize(new Dimension(200, 30));
        p.add(imageLabel, BorderLayout.CENTER);
        p.add(memory, BorderLayout.SOUTH);
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setContentPane(p);
        f.pack();
        f.setVisible(true);
        Runnable r = new Runnable() {

            @Override
            public void run() {
                while (true) {
                    try {
                        imageLabel.setIcon(new ImageIcon(convertToFromBytes(getImage())));
                        memory.setValue((int) Runtime.getRuntime().freeMemory());
                        useMem = ((int) Runtime.getRuntime().freeMemory());
                        Thread.sleep(300);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(ImageCacheTest.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        };
        Thread t = new Thread(r);
        t.start();
    }

    public BufferedImage getImage() {
        GradientPaint gp = new GradientPaint(0f, 0f, new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128)),
                (float) halfScreenSize.width, (float) halfScreenSize.width, new Color(random.nextInt(128), random.nextInt(128), random.nextInt(128)));
        BufferedImage bi = new BufferedImage(halfScreenSize.width, halfScreenSize.height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = bi.createGraphics();
        g2d.setPaint(gp);
        g2d.fillRect(0, 0, halfScreenSize.width, halfScreenSize.height);
        g2d.setFont(bigFont);
        g2d.setColor(Color.BLACK);
        if (maxMem < ((int) Runtime.getRuntime().freeMemory())) {
            maxMem = ((int) Runtime.getRuntime().freeMemory());
        }
        if (peakMem > ((int) Runtime.getRuntime().freeMemory())) {
            peakMem = ((int) Runtime.getRuntime().freeMemory());
        }
        useMem = ((int) Runtime.getRuntime().freeMemory()) - useMem;
        g2d.drawString("" + ++count, 20, 100);
        g2d.drawString("JVM memory status --->  ", 20, 195);
        g2d.drawString("tot. memory --->  " + ((int) Runtime.getRuntime().totalMemory()), 20, 240);
        g2d.drawString("max. memory --->  " + ((int) Runtime.getRuntime().maxMemory()), 20, 270);
        g2d.drawString("free on startUp --->  " + startMem, 20, 300);
        g2d.drawString("max free memory --->  " + maxMem, 20, 350);
        g2d.drawString("min free memory --->  " + peakMem, 20, 380);
        g2d.drawString("act free memory --->  " + ((int) Runtime.getRuntime().freeMemory()), 20, 410);
        g2d.drawString("usage of memory --->  " + useMem, 20, 450);
        return bi;
    }

    /** Not entirely sure this method is necessary for indicating 'no cache',
    but since the claim was specific to byte arrays, we'll do it. */
    public Image convertToFromBytes(BufferedImage image) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "png", baos);
            return Toolkit.getDefaultToolkit().createImage(baos.toByteArray());
        } catch (Exception e) {
            return null;
        }
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                ImageCacheTest ict = new ImageCacheTest();
            }
        };
        SwingUtilities.invokeLater(r);
    }
}
于 2012-03-13T18:17:06.290 に答える