2009-07-13 6 views
4

Java에서 큰 이미지 파일을로드하려고하는데 파일이 너무 크면 메모리 오류 메시지가 나타납니다. 이미 명령 줄 플래그로 힙 크기를 늘려 보았습니다.Java에서 큰 이미지를로드하는 방법

BufferedImage img = ImageIO.read(fileToOpen); 

그리고 파일이 TIFF 인 경우이 코드를 사용하고 있습니다 : 이미지가이 코드를 사용하여 오전 TIFF 이미지가 아닌 경우

:

나는 다음과 같은 방법으로 이미지를로드하고 :

BufferedImage img = JAI.create("fileload", 
    fileToOpen.getAbsolutePath()).getAsBufferedImage(); 

내 질문은 사실이 아래로 비등 : 어떻게 메모리 오류를받지 않고 (예를 들어 포토샵 등의) 이미지 조작 프로그램 수백 메가 바이트의로드 파일?

20MB jpeg가 메모리에로드하기 어려운 이유는 BufferedImage에로드 할 때 예를 들어 이미지를 압축되지 않은 방식으로 저장하기 때문입니다. 따라서 가능한 한 가지 해결책은 Image 클래스를 하위 클래스로 압축하지만 압축 된 형식으로 데이터를 저장하는 Java 클래스를 만드는 것입니다. 그러나 런타임 시스템이 그리는 동안 데이터의 압축을 풀어야하므로 속도 문제가 발생할 수 있습니다. 또 다른 옵션은 원시 압축되지 않은 데이터를 디스크에 캐시하고 거기에서 완벽하게 읽을 수 있지만 속도 문제는 계속됩니다.

큰 소년은 어떻게합니까? Photoshop에서 200MB의 JPEG를 메모리에로드하고 명백한 문제없이 모든 해상도를 그릴 수있는 방법은 무엇입니까?

: 압축되지 않은 RGBA 이미지의

답변

5

필요한 메모리 (최종 노트. 내가 같은 차원을 가지는 VolatileImage에 그 내용을 그려 내 BufferedImage를 얻을 후 때문에 속도 문제의 내 응용 프로그램에서이 크게 드로잉 속도를 증가) 너비 * 높이 * 4 바이트입니다. 이것에 따라 기억을 설정하십시오. 기본 JDK/DirectX/등의 크기 제한이있을 수 있습니다. 시스템.

큰 소년은 JPG 이미지의 구조를 악용하며 메모리에로드 할 필요가 없습니다. 아마도 그들은 매번 파일에서 직접 그릴 것입니다.

BufferedImage에는 휘발성 이미지와 비슷한 자동 가속 기능이 있습니다. 가속 우선 순위를 1로 설정하면 첫 번째 페인트가 최신 JDK에서 VRAM으로 이동합니다.

편집 나는 32 비트 시스템을 실행하고 있다고 가정합니다. 압축되지 않은 이미지가 1.4GB보다 큽니다. JVM 제한 때문에 메모리에서 처리 할 수 ​​없습니다. 이미지가 일회성 이미지가 아니라면 임시 원시 이미지에 압축을 풀고 무작위 파일 액세스를 사용하여 파일의 일부를 가져올 도구를 찾을 수 있습니다.

+0

답장을 보내 주셔서 감사합니다. 특히 가속 부분을 설정합니다. 누군가가 더 적절한 (내 경우) 대답이 –

+0

와 함께 제공되는 경우에 대한 정확한 투표 버튼을 예약 오전 대답을 수락하는 의미. 도움이되는 답변을 무료로 투표 할 수 있으며 SO 한도로 인해 이미 투표를 모두 사용하지 않은 경우를 제외하고 모든 답변에 대해 도움을 줄 수 있습니다. 또한 질문을 수정하는 옵션이 있으며 아마도 (또는 다른 사람이)보다 정확한 대답을 제시 할 수 있습니다. – akarnokd

+0

hehe 예 나는 그것을 의미했다. 나는 또한 투표 버튼을 의미했다. 내 대답은 답을 얻지 못한 채로 잠시 더 오래 노출되어 투표가 끝나기를 바란다. 너무 비 윤리적이지 않기를 바랍니다 : P –

3

트릭은 풀 사이즈 이미지를 다루지 않습니다. 이를 현재 해상도의 50x50 픽셀과 같은 관리 가능한 부분으로 분할하고 필요할 때 원본 파일에서 내용을 생성하십시오. 주어진 조각이 필요하지 않은 경우 (예 : 화면 꺼짐) 삭제 될 수 있습니다 (약한 참조는 완벽 할 수 있음).

+0

그러나 다시 : 조각을 생성하기 위해 이미지를 적어도 한 번 메모리에로드해야합니까? –

+0

일 필요는 없습니다. 신중하게 만들어진 이미지 디코더는 문제의 조각 영역을 디코딩하는 데 필요한 바이트 만 읽을 수 있습니다. –

0

해결책은 BigBufferedImage입니다. 메모리 제한보다 훨씬 큰 이미지를로드하고 저장할 수 있습니다. 트릭은, 그 버퍼가 파일베이스의 DataBuffer 구현으로 옮겨 놓을 수있는 것입니다. 이미지를 하드 드라이브에 저장합니다. RAM이 사용되지 않습니다. 이렇게하면 OutOfMemoryException을 방지 할 수 있습니다.

이미지 파일에서 BigBufferedImage 만들기 :

BigBufferedImage image = BigBufferedImage.create(
     inputFile, tempDir, TYPE_INT_RGB); 

빈 BigBufferedImage 만들기 : 큰 이미지는 read this article 처리에 대한 자세한 내용은

BigBufferedImage image = BigBufferedImage.create(
     tempDir, width, height, TYPE_INT_RGB); 

.

관련 문제