簡體   English   中英

在Java中處理圖像時提高性能

[英]Improving performance when processing images in Java

我正在編寫一個程序,其中包括一個圖像文件夾(通常約2000個jpeg圖像)調整它們的大小,並將它們添加到圖像的時間軸。 結果如下:

在此輸入圖像描述

這樣做很好,但是我這樣做的方式似乎非常低效。 處理這些圖像的代碼如下所示:

public void setTimeline(Vector<String> imagePaths){

    int numberOfImages = imagePaths.size();     

    JLabel [] TotalImages = new JLabel[numberOfImages];
    setGridPanel.setLayout(new GridLayout(1, numberOfImages, 10, 0));

    Dimension image = new Dimension(96, 72);

    if (imagePaths != null){
        for(int i = 0; i <numberOfImages; i++){
            TotalImages[i] = new JLabel("");
            TotalImages[i].setPreferredSize(image);

            ImageIcon tempicon = new ImageIcon(imagePaths.elementAt(i));
            Image tempimage = tempicon.getImage();

            Image newimg = tempimage.getScaledInstance(96, 72,  java.awt.Image.SCALE_SMOOTH);
            ImageIcon newIcon = new ImageIcon(newimg);
            TotalImages[i].setIcon(newIcon);

            setGridPanel.add(TotalImages[i]);
        }
    }
}

可以看出,此代碼循環遍歷每個圖像路徑,將其添加到標簽並將其添加到面板 - 完全按照正確的輸出執行。

但是,這樣做的時間很長。 對於2000張圖像通常大約需要5分鍾(取決於機器)。 我想知道是否有任何方法可以通過使用不同的技術來改善這種性能?

任何幫助是極大的贊賞。

保存縮放的實例並直接加載它們。 硬盤空間很便宜。 這不會影響生成拇指的初始成本,但任何后續出現都將是閃電般快速的。

拿一個圖像文件夾

使用tempimage.getScaledInstance(96, 72, java.awt.Image.SCALE_SMOOTH);進程tempimage.getScaledInstance(96, 72, java.awt.Image.SCALE_SMOOTH);

  • 使用JTable ,功能降低,你也可以使用JList

對於2000張圖像通常約為5分鍾

Image.getScaledInstance是簡單的異步,確保快速和性能,然后你必須將圖像加載到Background任務

  • 優勢第一部分圖像可立即使用

  • dis_advantage需要為用戶提供不正確的加載狀態,非常了解SwingEvent Dispatch Thread

我建議看一下Runnable#Thread ,並輸出put到DefaultTableModel ,注意這個輸出必須包裝到invokeLater

另一個也是最復雜的方法是使用SwingWorker ,但也需要非常好的JavaSwing知識

要添加到mKorbel的優秀答案,我肯定會使用后台線程,例如SwingWorker。 這可能不會使程序更快,但它看起來會快得多,而且可以產生重大影響。 就像是:

// use List<String> not Vector<String> so you can use Vector now, or change your 
// mind and use ArrayList later if desired
// pass dimensions and components in as parameters to be cleaner
public void setTimeLine2(List<String> imagePaths, Dimension imgSize,
     JComponent imgDisplayer) {

  if (imagePaths != null && imgSize != null && imgDisplayer != null) {

     // are you sure you want to set the layout in here?
     imgDisplayer.setLayout(new GridLayout(1, 0, 10, 0));

     // create your SwingWorker, passing in parameters that it will need
     ImageWorker imgWorker = new ImageWorker(imagePaths, imgSize,
           imgDisplayer);
     imgWorker.execute(); // then ask it to run doInBackground on a background thread
  } else {
     // TODO: throw exception
  }
}

private class ImageWorker extends SwingWorker<Void, ImageIcon> {
  private List<String> imagePaths;
  private JComponent imgDisplayer;
  private int imgWidth;
  private int imgHeight;

  public ImageWorker(List<String> imagePaths, Dimension imgSize,
        JComponent imgDisplayer) {
     this.imagePaths = imagePaths;
     this.imgDisplayer = imgDisplayer;
     imgWidth = imgSize.width;
     imgHeight = imgSize.height;
  }

  // do image creation in a background thread so as not to lock the Swing event thread
  @Override
  protected Void doInBackground() throws Exception {
     for (String imagePath : imagePaths) {
        BufferedImage bImg = ImageIO.read(new File(imagePath));
        Image scaledImg = bImg.getScaledInstance(imgWidth, imgHeight,
              Image.SCALE_SMOOTH);
        ImageIcon icon = new ImageIcon(scaledImg);
        publish(icon);
     }
     return null;
  }

  // but do all Swing manipulation on the event thread
  @Override
  protected void process(List<ImageIcon> chunks) {
     for (ImageIcon icon : chunks) {
        JLabel label = new JLabel(icon);
        imgDisplayer.add(label);
     }
  }
}

使用瓷磚。 這意味着,除了操作未在屏幕上顯示的圖像之外,您只能在必須在屏幕上顯示圖像時進行操作。

您需要保持時間軸的邏輯位置以及顯示的圖像。 當用戶將光標移動到先前隱藏的位置時,您可以計算下一個需要顯示的圖像。 如果圖像尚未處理,則處理它們。 這與Web瀏覽器用於性能的技術相同。

  • 您可以做的第一件事是異步添加圖像,而不是嘗試一次添加所有圖像。 像你一樣循環遍歷它們,將它們添加到面板並每隔幾張圖像渲染一次,這樣用戶就不需要等待很長的初始化時間。

  • 重用圖像對象。 我們會想到一個flyweight模式,並且可能會將屏幕重繪限制為僅在異步加載中添加新圖像的部分。

  • 如果您將來可能會重新繪制相同的圖像(或重新加載相同的文件夾),您可能需要考慮緩存某些圖像對象,並可能將已調整大小的縮略圖保存到文件中(許多照片查看器會執行此操作,將隱藏文件或文件夾中的縮略圖版本和一些有用的元數據存儲起來,這樣他們就可以在下次更快地重新加載它們。

你可以做些什么來使它更快是通過制作4個線程,並讓他們同時計算圖像。 我不知道vm是否會將它們分散在多個cpu核心上。 需要考慮的因為這會增加多核PC上的perfotrmace

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM