[英]Processing huge amount of large jpgs
我正在編寫一個程序,部分只是為了好玩,部分是為了幫助我處理一堆我想分成幾類進行打印的數字圖片。 主要思想是它應該在單個列中顯示圖片,並在每張圖片旁邊有一組帶有類別名稱的復選框。 我選中所需的復選框,按“開始!” 按鈕,圖片將被復制到子文件夾中,具體取決於所選的復選框。
現在,一切都差不多完成了——除了一件事。 有問題的圖片是大jpg,每個大約7-8MB,大約有700張。 如果我嘗試一次加載它們,自然地,將它們全部加載需要大量內存和時間。 那么,有沒有好的解決辦法呢? 我的兩個想法如下。
1) 一次加載 10 張圖片並在某處設置下一個/上一個按鈕。 我不喜歡這個想法,因為它添加了不需要的元素。 2) 使應用程序在滾動到新圖片時加載新圖片並卸載滾動過去的圖片。 我真的喜歡這個主意。
有人可以指出我正確的方向,至於我如何實施后一個想法嗎? 我只在 Google 上找到了一個相關鏈接,但我不能說它對我有幫助,我對代碼的某些部分感到有些困惑。
您必須為所有圖片創建縮略圖,您可以將縮略圖保存在內存中。 那可能需要很多時間。
那么你要么准備好解決問題。 否則縮略圖將無法全部放入內存中。 如果是這種情況:您加載 30-40 個,並在滾動期間檢測滾動方向,然后在單獨的線程中加載下一組。
如果加載速度比用戶滾動速度慢,那么您會為此類“尚未加載的圖片”顯示默認的占位符圖像
您可以縮小所有圖像以使用更少的 RAM。 例如,此代碼將所有圖像縮小到 200x200。 這樣你就可以在 100MB 中容納 1000 張圖片。
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import java.io.File;
public class Scroll extends JPanel {
public static void main(String[] args) throws Exception {
JFrame frame = new JFrame();
JPanel panel = new Scroll();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
for(int i = 0; i < 10; i++) {
JPanel buttonPanel = new JPanel();
JRadioButton b1 = new JRadioButton("button 1");
JRadioButton b2 = new JRadioButton("button 2");
JRadioButton b3 = new JRadioButton("button 3");
ButtonGroup group = new ButtonGroup();
group.add(b1);
group.add(b2);
group.add(b3);
buttonPanel.add(b1);
buttonPanel.add(b2);
buttonPanel.add(b3);
BufferedImage buffer = new BufferedImage(200,200,BufferedImage.TYPE_INT_RGB);
Graphics2D g = buffer.createGraphics();
BufferedImage image = ImageIO.read(new File("image.jpg"));
g.scale(buffer.getWidth()*1.0/image.getWidth(),
buffer.getHeight()*1.0/image.getHeight());
g.drawImage(image, 0, 0, null);
g.dispose();
JLabel imageLabel = new JLabel(new ImageIcon(buffer));
JSplitPane splitPane = new JSplitPane();
splitPane.add(imageLabel, JSplitPane.LEFT);
splitPane.add(buttonPanel, JSplitPane.RIGHT);
panel.add(splitPane);
}
JScrollPane spane = new JScrollPane(panel);
frame.add(spane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,600);
frame.setVisible(true);
}
}
如果您想在圖像變得可見時動態加載它們,您必須為每個圖像使用空的 JPanel 而不是 ImageIcons,然后覆蓋這些 JPanel 的paint方法。 只有在 JPanel 可見時才會調用paint方法。 因此,最簡單的解決方案是始終在paint方法中從磁盤加載圖像,然后將其繪制到屏幕上。
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import java.io.File;
public class Scroll extends JPanel {
public static void main(String[] args) throws Exception {
JFrame frame = new JFrame();
JPanel panel = new Scroll();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
for(int i = 0; i < 10; i++) {
JPanel buttonPanel = new JPanel();
JRadioButton b1 = new JRadioButton("button 1");
JRadioButton b2 = new JRadioButton("button 2");
JRadioButton b3 = new JRadioButton("button 3");
ButtonGroup group = new ButtonGroup();
group.add(b1);
group.add(b2);
group.add(b3);
buttonPanel.add(b1);
buttonPanel.add(b2);
buttonPanel.add(b3);
JPanel imagePanel = new JPanel() {
{
BufferedImage image = ImageIO.read(new File("image.jpg"));
setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
image.flush();
}
@Override
public void paint(Graphics g) {
try {
BufferedImage image = ImageIO.read(new File("image.jpg"));
g.drawImage(image, 0, 0, null);
image.flush();
} catch(Exception e) {
}
}
};
JSplitPane splitPane = new JSplitPane();
splitPane.add(imagePanel, JSplitPane.LEFT);
splitPane.add(buttonPanel, JSplitPane.RIGHT);
panel.add(splitPane);
}
JScrollPane spane = new JScrollPane(panel);
frame.add(spane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,600);
frame.setVisible(true);
}
}
如果這是一個“使用一次就扔掉”的程序,我不會費心去解決這個問題。 我會使用命令行為每張圖片生成縮略圖,並在我的程序中使用這些生成的縮略圖。 在內存中保留 700 個縮略圖應該是可行的。
如果這不是一個選項,我會從JTable
開始。 您可以創建一個TableModel
而不必將所有圖像加載到內存中。 您只需要知道圖像計數。 JTable
只希望渲染當時可見的圖像。 警告可能是在渲染器要求它們的那一刻加載圖像可能為時已晚。 我可以想象,當您必須加載幾 MB 大小的圖像時, JTable
將無法順利運行。 但這可能可以通過使用填充有工作線程的緩存來解決。 因此,如果渲染器請求第 5 個圖像,您還將前 5 個圖像和 5 個下一個圖像加載到緩存中。
另請注意,如果您正在移動圖片 iso 復制它們,這可能會影響您的TableModel
因為您目錄中的圖像數量將發生變化。 一定要考慮到這一點!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.