2013-10-07 28 views
5

ImageIO.read() işlevini kullanıyorum. Orijinal App ana yöntemle denir sınıf şudur:Java'da bellek sızıntısı ImageIO.read()

import java.awt.*; 
import javax.swing.*; 
import java.io.File; 
import java.awt.image.BufferedImage; 
import java.awt.event.*; 
import javax.swing.JPanel; 

class ImageGenerator extends JPanel{ 

JpegReader jpeg; 

public ImageGenerator(Aplicacion a){ 
    jpeg = new JpegReader(); 
    loadImage(); 

} 


private void loadImage(){ 
    String path = "C:\\image.jpg"; 
    image = new BufferedImage(100,100, BufferedImage.TYPE_INT_RGB); //in case error 
    try{ 
     image = jpeg.readImage(new File(path)); 
    }catch(Exception e){ 
     System.err.println(e.getMessage()); 
    } 
} 
public void paint(Graphics g){ 

    Graphics2D g2 = (Graphics2D) g; 
    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
      RenderingHints.VALUE_INTERPOLATION_BICUBIC); 
    g2.drawImage(image, 0, 0, 1000, 800, null); 
} 

} 

ben gerçekten cevap olarak StackOverflow'daki bulunan bu diğer sınıf JpegReader ile birlikte yukarıda kullanıyorum ama unuttum ona alıntı yapmak için yazarın adı.

import java.awt.image.BufferedImage; 
import javax.imageio.*; 
import javax.imageio.stream.ImageInputStream; 
import java.awt.color.*; 
import java.awt.image.*; 
import java.io.File; 
import java.io.IOException; 
import java.util.Iterator; 
import java.util.ArrayList; 
import org.apache.sanselan.Sanselan; 
import org.apache.sanselan.common.byteSources.ByteSource; 
import org.apache.sanselan.common.byteSources.ByteSourceFile; 
import org.apache.sanselan.ImageReadException; 
import org.apache.sanselan.formats.jpeg.JpegImageParser; 
import org.apache.sanselan.formats.jpeg.segments.UnknownSegment; 
public class JpegReader { 

public static final int COLOR_TYPE_RGB = 1; 
public static final int COLOR_TYPE_CMYK = 2; 
public static final int COLOR_TYPE_YCCK = 3; 

private int colorType = COLOR_TYPE_RGB; 
private boolean hasAdobeMarker = false; 

public BufferedImage readImage(File file) throws IOException, ImageReadException { 
    colorType = COLOR_TYPE_RGB; 
    hasAdobeMarker = false; 

    ImageInputStream stream = ImageIO.createImageInputStream(file); 
    Iterator<ImageReader> iter = ImageIO.getImageReaders(stream); 
    while (iter.hasNext()) { 
     ImageReader reader = iter.next(); 
     reader.setInput(stream); 

     BufferedImage image; 
     ICC_Profile profile = null; 
     try { 
      image = reader.read(0); 
     } catch (IIOException e) { 
      System.out.println("Hello"); 
      colorType = COLOR_TYPE_CMYK; 
      checkAdobeMarker(file); 
      profile = Sanselan.getICCProfile(file); 

      WritableRaster raster = (WritableRaster) reader.readRaster(0, null); 
      if (colorType == COLOR_TYPE_YCCK) 
       convertYcckToCmyk(raster); 
      if (hasAdobeMarker) 
       convertInvertedColors(raster); 
      image = convertCmykToRgb(raster, profile); 
      System.out.println("Hello"); 
     }finally { 
      try { 
       System.out.println("facebook"); 
       stream.close(); 
      } catch (IOException ioex) { 
       //omitted. 
      } 
     } 

     return image; 
    } 

    return null; 
} 

public void checkAdobeMarker(File file) throws IOException, ImageReadException { 
    JpegImageParser parser = new JpegImageParser(); 
    ByteSource byteSource = new ByteSourceFile(file); 
    @SuppressWarnings("rawtypes") 
    ArrayList segments = parser.readSegments(byteSource, new int[] { 0xffee }, true); 
    if (segments != null && segments.size() >= 1) { 
     UnknownSegment app14Segment = (UnknownSegment) segments.get(0); 
     byte[] data = app14Segment.bytes; 
     if (data.length >= 12 && data[0] == 'A' && data[1] == 'd' && data[2] == 'o' && data[3] == 'b' && data[4] == 'e') 
     { 
      hasAdobeMarker = true; 
      int transform = app14Segment.bytes[11] & 0xff; 
      if (transform == 2) 
       colorType = COLOR_TYPE_YCCK; 
     } 
    } 
} 

public static void convertYcckToCmyk(WritableRaster raster) { 
    int height = raster.getHeight(); 
    int width = raster.getWidth(); 
    int stride = width * 4; 
    int[] pixelRow = new int[stride]; 
    for (int h = 0; h < height; h++) { 
     raster.getPixels(0, h, width, 1, pixelRow); 

     for (int x = 0; x < stride; x += 4) { 
      int y = pixelRow[x]; 
      int cb = pixelRow[x + 1]; 
      int cr = pixelRow[x + 2]; 

      int c = (int) (y + 1.402 * cr - 178.956); 
      int m = (int) (y - 0.34414 * cb - 0.71414 * cr + 135.95984); 
      y = (int) (y + 1.772 * cb - 226.316); 

      if (c < 0) c = 0; else if (c > 255) c = 255; 
      if (m < 0) m = 0; else if (m > 255) m = 255; 
      if (y < 0) y = 0; else if (y > 255) y = 255; 

      pixelRow[x] = 255 - c; 
      pixelRow[x + 1] = 255 - m; 
      pixelRow[x + 2] = 255 - y; 
     } 

     raster.setPixels(0, h, width, 1, pixelRow); 
    } 
} 

public static void convertInvertedColors(WritableRaster raster) { 
    int height = raster.getHeight(); 
    int width = raster.getWidth(); 
    int stride = width * 4; 
    int[] pixelRow = new int[stride]; 
    for (int h = 0; h < height; h++) { 
     raster.getPixels(0, h, width, 1, pixelRow); 
     for (int x = 0; x < stride; x++) 
      pixelRow[x] = 255 - pixelRow[x]; 
     raster.setPixels(0, h, width, 1, pixelRow); 
    } 
} 

public static BufferedImage convertCmykToRgb(Raster cmykRaster, ICC_Profile cmykProfile) throws IOException { 
    if (cmykProfile == null) 
     cmykProfile = ICC_Profile.getInstance(JpegReader.class.getResourceAsStream("/ISOcoated_v2_300_eci.icc")); 

    if (cmykProfile.getProfileClass() != ICC_Profile.CLASS_DISPLAY) { 
     byte[] profileData = cmykProfile.getData(); 

     if (profileData[ICC_Profile.icHdrRenderingIntent] == ICC_Profile.icPerceptual) { 
      intToBigEndian(ICC_Profile.icSigDisplayClass, profileData, ICC_Profile.icHdrDeviceClass); // Header is first 

      cmykProfile = ICC_Profile.getInstance(profileData); 
     } 
    } 

    ICC_ColorSpace cmykCS = new ICC_ColorSpace(cmykProfile); 
    BufferedImage rgbImage = new BufferedImage(cmykRaster.getWidth(), cmykRaster.getHeight(), BufferedImage.TYPE_INT_RGB); 
    WritableRaster rgbRaster = rgbImage.getRaster(); 
    ColorSpace rgbCS = rgbImage.getColorModel().getColorSpace(); 
    ColorConvertOp cmykToRgb = new ColorConvertOp(cmykCS, rgbCS, null); 
    cmykToRgb.filter(cmykRaster, rgbRaster); 
    return rgbImage; 
} 
static void intToBigEndian(int value, byte[] array, int index) { 
    array[index] = (byte) (value >> 24); 
    array[index+1] = (byte) (value >> 16); 
    array[index+2] = (byte) (value >> 8); 
    array[index+3] = (byte) (value); 
} 
} 

Sanselan-0.97-incubator.jar kullanıyorum.

Bu programı yaklaşık 31 kez çalıştırırsam, bir java yığın alanı hatası alıyorum, dolayısıyla bir bellek sızıntısı olduğundan şüpheleniyorum.

Lütfen bellek sızıntısını bulmamda veya sorunu nasıl gidereceğiniz konusunda öneride bulunmama yardımcı olun. Kullanmakta olduğum jar dosyası OKAY veya belki modası geçmişse bana da bildirin. Bir sansel kavanozu dosyasını bulmak için bazı sorunlar vardı.

Şimdiden teşekkürler.

+0

Yığın boyutunun artmasıyla ilgili ne var? bir dizi görüntü yüklemesi çok fazla bellek alır – Sage

+0

Tüm görüntüleri bir kerede yüklemiyorum. Onları sırayla yüklüyorum. Yeni bir görüntü yüklediğimde, önceki görüntülere ihtiyacım olmamalı. Bu yüzden bir şekilde, önceki görüntülerin hala bellekte tutulmadığı sonucuna varıyorum. Gerçi bu bir hipotez. – ThePrince

+0

Tek bir görüntü bu hataya neden olacak kadar büyük değil. Sanırım önceki görüntüleri koruyor. – ThePrince

cevap

3

Bu kod ile aynı bellek sorunum var (JPEGReader). Birkaç denemeden sonra, reader.dispose() işlevinin bu sorunu çözebileceğini buldum.

Değiştirdiğim yöntemi veriyorum. Umarım size yardımcı olur.

public BufferedImage readImage(File file) throws IOException, ImageReadException { 
    colorType = COLOR_TYPE_RGB; 
    hasAdobeMarker = false; 

    ImageInputStream stream = ImageIO.createImageInputStream(file); 
    try{ 
     Iterator<ImageReader> iter = ImageIO.getImageReaders(stream); 
     while (iter.hasNext()) { 
      ImageReader reader = iter.next(); 
      reader.setInput(stream); 

      BufferedImage image; 
      ICC_Profile profile = null; 
      try { 
       image = reader.read(0); 
      } catch (IIOException e) { 
       colorType = COLOR_TYPE_CMYK; 
       checkAdobeMarker(file); 
       profile = Sanselan.getICCProfile(file); 
       WritableRaster raster = (WritableRaster) reader.readRaster(0, null); 
       if (colorType == COLOR_TYPE_YCCK) 
        convertYcckToCmyk(raster); 
       if (hasAdobeMarker) 
        convertInvertedColors(raster); 
       image = convertCmykToRgb(raster, profile); 
       return image; 
      } 
      finally { 
       reader.dispose(); 
      } 
     } 
     return null; 
    } 
    finally { 
     if (stream != null){ 
      stream.close(); 
     } 
    } 
}