2012-11-24 4 views
2

나는 재미로 부분적으로 프로그램을 작성하고 있는데, 부분적으로는 인쇄용 카테고리로 나누고 싶은 디지털 사진을 다루는 데 도움이된다. 주요 개념은 사진을 단일 열에 표시하고 각 그림 옆에 범주 이름과 함께 일련의 확인란을 포함해야한다는 것입니다. 나는 필요한 체크 박스를 확인하고, "go!" 버튼을 클릭하면 선택한 확인란에 따라 그림이 하위 폴더로 복사됩니다.대용량 jpg 처리하기

이제는 한 가지를 제외하고는 거의 모든 것이 완료되었습니다. 문제의 사진은 각각 7 ~ 8MB 크기의 대형 jpg이며 약 700 장이 있습니다. 한번에 모두로드하려고하면 당연히 많은 양의 메모리와 시간이 필요합니다. 그렇다면이 문제에 대한 좋은 해결책이 있습니까? 저의 두 가지 생각은 다음과 같습니다.

1) 사진을 한 번에 10 장씩로드하고 다음/이전 버튼을 어딘가에 있습니다. 나는 불필요한 요소를 추가하기 때문에이 아이디어를 좋아하지 않는다. 2) 스크롤하여 새로운 사진을로드하고 과거 스크롤 한 사진을 언로드합니다. 나는이 아이디어를 정말 좋아한다.

후자의 아이디어를 구현하는 방법에 관해 누군가가 올바른 방향으로 나를 가리킬 수 있습니까? 나는 단지 하나의 구글 관련 link을 찾았지만, 도움이된다고 말할 수는 없다. 코드의 일부분이 약간 혼란 스럽다.

+0

* "대형 jpg, 각 약 7-8MB"* 압축에 따라 다양한 최종 픽셀 크기가 발생할 수 있습니다. 어떤 종류의 WxH가 이미지입니까? –

+0

@ 앤드류 톰슨 (AntrewThompson), 약 2600 * 3900 및 그 반대로 –

답변

2

섬네일이 충분하면이 answer에 간단한 리샘플링 접근법이 포함되어 있으며 몇 가지 단점이 있습니다. 그렇지 않은 경우이 answer은 최근 이미지를 표시하고 캐싱하는 일반적인 방법에 대해 간략하게 설명합니다.

두 경우 모두 Booleanrenderer/editorJTable이며 기본값은 JCheckBox입니다. CheckOne이 그 예입니다.

+0

링크를 가져 주셔서 감사합니다. 가장 유용한 두 번째 버전을 발견했습니다. Swing을 처음 접했을뿐 아니라 JTable에 대해서도 생각조차하지 않았습니다. –

+0

'JTable'을 사용하면 기본 렌더러는 썸네일에 대한'Icon' 및'ImageIcon'을 인식합니다. – trashgod

1

모든 사진에 대해 thumnails를 만들어야합니다. thumnails를 메모리에 보관할 수 있습니다. 많은 시간이 필요할 수 있습니다.

그런 다음 당신은 앞자리가 준비되어 있습니다. 또는 미리보기 이미지가 모두 메모리에 맞지 않습니다. 그런 경우 : 30-40을로드하고 스크롤하는 동안 스크롤 방향을 결정하고 다음 묶음을 별도의 스레드에로드하십시오.

로딩이 사용자가 스크롤보다 느린 경우
는, 당신은 당신이 적은 RAM을 사용하는 모든 이미지를 축소 할 수 같은 "아직로드 그림"

+0

+1 축소판 그림을 캐싱하는 것이 좋겠지 만 또 다른 문제입니다.) – MadProgrammer

+0

일반적인 UI 대기 이미지 아이콘이 여기에 나와 있습니다 (http://stackoverflow.com/a/11092120/230513). – trashgod

+0

@AlexWien 네, 스크롤하는 동안 어떤 종류의 로딩은 제가 성취하려고하는 것입니다. –

0

의 기본 자리 표시 자 이미지를 DISPALY. 예 : 이 코드는 모든 이미지를 200x200로 축소합니다. 그렇게하면 100MB에 1000 개의 이미지를 저장할 수 있습니다. 그들은 당신이 대신 ImageIcons의 각 이미지에 대한 빈 JPanel의를 사용해야하고 당신이 그 JPanel의의 페인트 메소드를 오버라이드 (override) 가시가 같은 동적 이미지를로드하려면

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); 
    } 
} 

. paint 메서드는 JPanel가 가시적 인 경우에만 호출됩니다. 따라서 가장 간단한 해결책은 항상 페인트 방법으로 디스크에서 이미지를로드 한 다음 화면에 그려주는 것입니다.

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); 
    } 
} 
+0

코드 스 니펫에 감사드립니다. 두 번째 문제를 해결하기 위해 노력하고 있습니다. 문제는 이미지를 다시로드 할 때 청취자가있는 디렉토리를 재검색하고 JLabels을 많이 추가한다는 것입니다. ImageIcons로서의 이미지. JLabel은 별도의 클래스로 작성됩니다. 그 클래스의 paint()를 재정의하고 JPanel을 확장했지만 paint()가 여전히 호출되지 않는다고 가정했습니다. 그것을 대체 할 수있는 가장 적절한 장소는 어디입니까? –

0

"한 번 사용해서 버려야하는"종류의 프로그램 인 경우이 문제를 해결하기 위해 노력하지 않아도됩니다. 명령 줄을 사용하여 각 그림에 대한 축소판을 생성하고 내 프로그램에서 생성 된 축소판을 사용합니다. 메모리에 700 개의 미리보기 이미지를 보관할 수 있어야합니다.

이것이 옵션이 아니라면, 나는 JTable으로 시작할 것입니다.모든 이미지를 메모리에로드 할 필요없이 TableModel을 만들 수 있습니다. 이미지 수를 알아야합니다. JTable은 그 순간에 볼 수있는 이미지 만 렌더링하려고합니다. 주의해야 할 점은 렌더러가 이미지를로드하는 순간에 이미지를로드하는 것이 너무 늦을 수 있습니다. 몇 MB의 크기로 이미지를로드해야 할 때 JTable이 원활하게 실행되지 않는다고 상상해보십시오. 하지만 이것은 작업자 스레드로 채워지는 캐시를 사용하여 해결할 수 있습니다. 따라서 렌더러가 5 번째 이미지를 요청하면 5 개의 이전 이미지와 5 개의 다음 이미지를 캐시에로드합니다.

사진을 복사 할 때이 아이콘을 복사하면 디렉토리의 이미지 수가 변경되므로 TableModel에 영향을 줄 수 있습니다. 그것을 고려해야합니다!

+0

저는이 프로그램으로 무언가를 배우려고 노력하고 있습니다. 그래서 그것이 의도했던대로 그것을 시도하고 구축하기를 원한다고 생각합니다. JTable에 대한 팁을 주셔서 감사합니다. –