简体   繁体   English

java ImageIO.read()中的内存泄漏

[英]Memory leak in java ImageIO.read()

I am utilizing ImageIO.read(). 我正在使用ImageIO.read()。 The class which is called by the main method of the original App is this: 由原始App的main方法调用的类是:

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

}

I am using the above in conjunction with this other class JpegReader, which I actually found on StackOverflow as an answer, but I forgot the name of the author to quote him. 我正在使用上面的这个其他类JpegReader,我实际上在StackOverflow上找到了答案,但我忘了引用他的作者的名字。

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

I am using sanselan-0.97-incubator.jar. 我正在使用sanselan-0.97-incubator.jar。

If I run this program 31 times approximately, I will get a java heap space error, so I suspect I have a memory leak. 如果我大约运行这个程序31次,我将得到一个java堆空间错误,所以我怀疑我有内存泄漏。

Please help me find the memory leak or suggest how to fix the issue. 请帮我查找内存泄漏或建议如何解决问题。

Also let me know if the jar file I'm using is OKAY, or maybe it's outdated. 如果我正在使用的jar文件是OKAY,或者它已经过时了,请告诉我。 I had some issues locating a sanselan jar file. 我在查找sanselan jar文件时遇到了一些问题。

Thanks in advance. 提前致谢。

I have got the same memory issue with this code (JPEGReader). 我有这个代码(JPEGReader)相同的内存问题。 After a few trials, I found that calling reader.dispose() can solve this issue. 经过几次试验,我发现调用reader.dispose()可以解决这个问题。

I give the method that I have modified. 我给出了我修改过的方法。 Hope it is helpful to you. 希望它对你有所帮助。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM