2010-03-30 5 views
6

이미지를 (JLabel 내에서) ImageIcon으로 읽고 표시하는 응용 프로그램을 작성 중이므로 응용 프로그램이 jpeg 및 비트 맵을 지원할 수 있어야합니다.Java : 이미지 읽기 및 ImageIcon으로 표시

jpegs의 경우 ImageIcon 생성자에 파일 이름을 직접 전달하는 것이 좋습니다 (심지어 두 개의 대형 jpeg를 표시하는 경우에도). ImageIO.read를 사용하여 이미지를 얻은 다음 이미지를 ImageIcon 생성자에 전달하면 두 번째 이미지를 읽을 때 (이전과 같은 이미지를 사용하여) OutOfMemoryError (Java 힙 공간)를 가져옵니다.

비트 맵의 ​​경우 파일 이름을 ImageIcon에 전달하여 읽으려고하면 아무 것도 표시되지 않지만 ImageIO.read로 이미지를 읽은 다음 ImageIcon 생성자에서이 이미지를 사용하면 문제가 없습니다.

다른 포럼 게시물을 읽는 중 두 가지 방법이 서로 다른 형식으로 동일하게 작동하지 않는 이유는 자바의 비트 맵 호환성 문제와 관련이 있습니다. 그러나 내 문제를 해결할 수있는 방법이 있습니다. OutOfMemoryError가없는 비트 맵과 jpeg 모두 동일한 방법?

(내가 힙 크기 가능하면 증가하는 것을 피하기 싶습니다!)

을 OutOfMemoryError가이 선으로 트리거 :

img = getFileContentsAsImage(file); 

과 방법을 정의하는 것입니다 :

public static BufferedImage getFileContentsAsImage(File file) throws FileNotFoundException { 
    BufferedImage img = null; 
    try { 
    ImageIO.setUseCache(false); 
    img = ImageIO.read(file); 
    img.flush(); 
    } catch (IOException ex) { 
    //log error 
    } 
return img; 
} 

스택 추적은 다음과 같습니다.

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space 
     at java.awt.image.DataBufferByte.<init>(DataBufferByte.java:58) 
     at java.awt.image.ComponentSampleModel.createDataBuffer(ComponentSampleModel.java:397) 
     at java.awt.image.Raster.createWritableRaster(Raster.java:938) 
     at javax.imageio.ImageTypeSpecifier.createBufferedImage(ImageTypeSpecifier.java:1056) 
     at javax.imageio.ImageReader.getDestination(ImageReader.java:2879) 
     at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:925) 
     at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:897) 
     at javax.imageio.ImageIO.read(ImageIO.java:1422) 
     at javax.imageio.ImageIO.read(ImageIO.java:1282) 
     at framework.FileUtils.getFileContentsAsImage(FileUtils.java:33) 
+0

OutOfMemoryError를 트리거하는 샘플 코드를 게시하십시오. – Thomas

답변

3

ImageIO.read()은 압축되지 않은 BufferedImage을 반환하기 때문에 메모리가 부족합니다. 크기가 매우 크고 ImageIcon에 의해 참조되기 때문에 힙에 유지됩니다. 그러나 Toolkit.createImage에 의해 반환되는 이미지는

당신은 Toolkit.createImage를 사용하여 BMP를 읽을 수 없습니다 (당신은 여전히 ​​메모리에 압축되지 않은 남아있을 수있는 경우에도 (. 민간 ByteArrayImageSource 클래스를 사용하여) 자신의 압축 된 형식에 남아 당신은 아마 밖으로 실행됩니다 힙 공간 다시)하지만 당신이 할 수있는 압축되지 않은 이미지를 읽고 그것을 압축 된 형식으로 바이트 배열에 저장합니다.

public static ImageIcon getPNGIconFromFile(File file) throws IOException { 
    BufferedImage bitmap = ImageIO.read(file); 
    ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 
    ImageIO.write(bitmap, "PNG", bytes); 
    return new ImageIcon(bytes.toByteArray()); 
} 

그런 식으로 비 압축 비트 맵을 메모리에 보유해야하는 유일한 방법은로드 또는 렌더링 할 때입니다.

+0

화려한! 이것은 완벽하게 작동합니다. 비트 맵 파일을 사용할 때이 메서드는 formatName으로 "PNG"를 사용하는 것만으로 왜 관심을 갖지 않습니까? – 11helen

+0

Toolkit에서 읽을 수있는 형식이어야하며 ImageIO 플러그인이 있어야합니다. GIF가 잘 작동 할 수 있지만 (품질은 저하 될 수 있으므로 8bpp로 제한됩니다.) JPEG도 작동합니다 (사진 형식 이미지는 JPEG 형식 일 가능성이 높으므로 이미 잘 작동합니다). – finnw

0

시도해 보셨습니까?

ImageIcon im = new ImageIcon(Toolkit.getDefaultToolkit().createImage("filename")); 
+0

비트 맵에서는 작동하지 않지만 두 개의 큰 jpeg에서는 실패합니다. "Image Fetcher 0"스레드의 예외 java.lang.OutOfMemoryError : Java 힙 공간 at java.awt.image.DataBufferInt. java.awt.image.DirectColorModel.createCompatibleWritableRaster (DirectColorModel.java:1015)에서 java.awt.image.Raster.createPackedRaster (Raster.java:458)에서 (DataBufferInt.java:41) 하는 sun.awt에서 . image.ImageRepresentation.createBufferedImage (ImageRepresentation.java:230) at sun.awt.image.ImageRepresentation.setPixels (ImageRepresentation.java:470) ... – 11helen

0

실제로 메모리가 부족하지는 않습니까? 내 말은, 만약 당신이 말을하면, -Xmx1g java를 실행하면 오류가 발생합니까?