Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 防止BuffereImage抛出OfMemoryError_Java_Out Of Memory_Bufferedimage - Fatal编程技术网

Java 防止BuffereImage抛出OfMemoryError

Java 防止BuffereImage抛出OfMemoryError,java,out-of-memory,bufferedimage,Java,Out Of Memory,Bufferedimage,是否可以通过逐字节创建BuffereImage来防止BuffereImage抛出内存错误异常 我正在使用此方法裁剪图像: public static void cropImage(File originalImage, File to, int x1, int y1, int x2, int y2) { try { BufferedImage source = ImageIO.read(originalImage); String mimeType =

是否可以通过逐字节创建BuffereImage来防止BuffereImage抛出内存错误异常

我正在使用此方法裁剪图像:

public static void cropImage(File originalImage, File to, int x1, int y1, int x2, int y2) {
    try {
        BufferedImage source = ImageIO.read(originalImage);

        String mimeType = "image/jpeg";
        if (to.getName().endsWith(".png")) {
            mimeType = "image/png";
        }
        if (to.getName().endsWith(".gif")) {
            mimeType = "image/gif";
        }
        int width = x2 - x1;
        int height = y2 - y1;

        // out
        BufferedImage dest = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Image croppedImage = source.getSubimage(x1, y1, width, height);
        Graphics graphics = dest.getGraphics();
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0, 0, width, height);
        graphics.drawImage(croppedImage, 0, 0, null);
        ImageWriter writer = ImageIO.getImageWritersByMIMEType(mimeType).next();
        ImageWriteParam params = writer.getDefaultWriteParam();
        writer.setOutput(new FileImageOutputStream(to));
        IIOImage image = new IIOImage(dest, null, null);
        writer.write(null, image, params);
        writer.dispose();
        source = null;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }

}
我的MaxPermSize为512m,如果有人上传16000x1000图像,我将在以下位置收到OutOfMemoryError:
BuffereImage source=ImageIO.read(originalImage)

这里是我的自我解决方案。 现在,当上传一个文件时,我会检查它是否是一个图像,在不读取所有文件的情况下获取图像大小,并检查它是否太大

public static boolean isImage(String fileName){
    Pattern pattern = Pattern.compile("([^\\s]+(\\.(?i)(png|jpg|jpeg|gif|bmp))$)");
    Matcher matcher = pattern.matcher(fileName);
    return matcher.matches();
}

public static Dimension getImageDimension(File file){
    ImageInputStream in = null;
    try{
        in = ImageIO.createImageInputStream(file);
        final Iterator<ImageReader> readers = ImageIO.getImageReaders(in);
        if (readers.hasNext()) {
            ImageReader reader = readers.next();
            try {
                reader.setInput(in);
                return new Dimension(reader.getWidth(0), reader.getHeight(0));
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                reader.dispose();
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (in != null) try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return null;
}

public static boolean isImageTooBig(File file){
    boolean isImage = isImage(file.getName());
    if(!isImage) return false;
    Dimension dim = getImageDimension(file);
    int maxW = Integer.parseInt((String) Play.configuration.get("app.upload.image.maxW"));
    int maxH = Integer.parseInt((String) Play.configuration.get("app.upload.image.maxH"));
    if(dim.getWidth() > maxW) return true;
    if(dim.getHeight() > maxH) return true;
    return false;
}
公共静态布尔isImage(字符串文件名){
Pattern Pattern=Pattern.compile(([^\\s]+(\\.(?i)(png | jpg | jpeg | gif | bmp))$);
Matcher Matcher=pattern.Matcher(文件名);
返回matcher.matches();
}
公共静态维度getImageDimension(文件){
ImageInputStream in=null;
试一试{
in=ImageIO.createImageInputStream(文件);
最终迭代器读取器=ImageIO.getImageReaders(in);
if(readers.hasNext()){
ImageReader=readers.next();
试一试{
reader.setInput(in);
返回新维度(reader.getWidth(0)、reader.getHeight(0));
}捕获(IOE异常){
e、 printStackTrace();
}最后{
reader.dispose();
}
}
}捕获(IOE异常){
e、 printStackTrace();
}最后{
如果(in!=null),请尝试{
in.close();
}捕获(IOE异常){
e、 printStackTrace();
}
}
返回null;
}
公共静态布尔值isImageTooBig(文件){
布尔isImage=isImage(file.getName());
如果(!isImage)返回false;
维度dim=getImageDimension(文件);
intmaxw=Integer.parseInt((String)Play.configuration.get(“app.upload.image.maxW”);
intmaxh=Integer.parseInt((String)Play.configuration.get(“app.upload.image.maxH”);
if(dim.getWidth()>maxW)返回true;
if(dim.getHeight()>maxH)返回true;
返回false;
}

如果您总是只对图像的一小部分感兴趣,您可以通过仅加载该区域来保留一些内存(您可以提前大致计算需要多少内存,以避免在大多数情况下出现OOME):

//输入与原始代码相同
ImageInputStream in=ImageIO.createImageInputStream(原始图像);
缓冲图像源;
试一试{
迭代器读卡器=ImageIO.getImageReaders(in);
if(readers.hasNext()){
ImageReader=readers.next();
试一试{
reader.setInput(in);
ImageReadParam param=reader.getDefaultReadParam();
参数设置震源区(x1,y1,宽度,高度);
//源大约为每像素的宽度*高度*字节
source=reader.read(0,参数);
} 
最后{
reader.dispose();
}
}
} 
最后{
in.close();
}
//使用旧代码存储源代码。。。

PS:永久发电机的大小通常与您看到的OOME没有多大关系。映像数据是在堆上分配的,因此您需要增加堆大小(-Xmx512m例如)。我需要完整映像和缩略图为什么?你问题中的代码总是在阅读后裁剪图像。这将创建与裁剪相同的结果,内存减少(至少50%),因为我有一个图库,可以显示裁剪后的缩略图,还有一个页面可以显示完整的图像。
// Same inputs as your original code

ImageInputStream in = ImageIO.createImageInputStream(originalImage);
BufferedImage source;

try {
    Iterator<ImageReader> readers = ImageIO.getImageReaders(in);

    if (readers.hasNext()) {
        ImageReader reader = readers.next();

        try {
            reader.setInput(in);
            ImageReadParam param = reader.getDefaultReadParam();
            param.setSourceRegion(x1, y1, width, height);

            // Source will be roughly width * height * bytes per pixel
            source = reader.read(0, param); 
        } 
        finally {
            reader.dispose();
        }
    }
} 
finally {
    in.close();
}

// Use your old code to store source...