Java ImageIO.read()中的内存泄漏 [英] Memory leak in java ImageIO.read()

查看:125
本文介绍了Java ImageIO.read()中的内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用ImageIO.read().原始App的main方法调用的类是:

I am utilizing ImageIO.read(). The class which is called by the main method of the original App is this:

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

}

我将上述内容与其他类JpegReader结合使用,我实际上是在StackOverflow上找到它作为答案的,但我忘记了引用他的作者姓名.

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.

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.

I am using sanselan-0.97-incubator.jar.

如果我大约运行31次此程序,则会收到Java堆空间错误,因此我怀疑内存泄漏.

If I run this program 31 times approximately, I will get a java heap space error, so I suspect I have a memory leak.

请帮助我查找内存泄漏或建议如何解决此问题.

Please help me find the memory leak or suggest how to fix the issue.

也请让我知道我使用的jar文件是否正常,或者是否已过时.在查找sanselan jar文件时遇到一些问题.

Also let me know if the jar file I'm using is OKAY, or maybe it's outdated. I had some issues locating a sanselan jar file.

谢谢.

推荐答案

此代码(JPEGReader)遇到了相同的内存问题.经过几次试验,我发现调用reader.dispose()可以解决此问题.

I have got the same memory issue with this code (JPEGReader). After a few trials, I found that calling reader.dispose() can solve this issue.

我给出了我修改过的方法.希望对您有帮助.

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

这篇关于Java ImageIO.read()中的内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆