简体   繁体   English

BufferedImage的像素访问-内存泄漏?

[英]Pixel access of BufferedImage - memory leak?

I want to build histograms from several images. 我想从多个图像构建直方图。 To perform this process, I get access to the DataBufferByte I recognize that the GC doesn't free the memory after building the histogram. 为了执行此过程,我可以访问DataBufferByte我知道在构建直方图后GC不会释放内存。 What is wrong with this code? 此代码有什么问题?

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;
import javax.imageio.ImageIO;


public class Histogram {

    HashMap<Color,AtomicInteger> histogram;

    public Histogram() {
        histogram = new HashMap<>();
    }

    public void build(BufferedImage image){

        int pixelLength = 3;

        byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();

        int red, green, blue;
        Color color;
        for ( int pixel = 0; pixel <= pixels.length - pixelLength; pixel+= pixelLength ) {

            blue= ((int) pixels[pixel] & 0xff); // blue
            green= (((int) pixels[pixel + 1] & 0xff) ); // green
            red = (((int) pixels[pixel + 2] & 0xff) ); // red
            color = new Color(red, green, blue);
            if(histogram.containsKey(color)){
                histogram.get(color).incrementAndGet();
            }
            else{
                histogram.put(color, new AtomicInteger(1));
            }
        }
        pixels = null;    
    }

    public static void main(String[] args) {
        String pathImage = "C://testjpg";
        try {
            for (int j = 0; j < 5000; j++) {
                BufferedImage i = ImageIO.read(new File(pathImage));

                Histogram h = new Histogram();

                h.build(i);
                i.flush();

            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }    
    }
}

thanks for your support :) 谢谢你的支持 :)

The GC does not run automatically and recalls the memory only when it needs it. GC不会自动运行,仅在需要时才调用内存。 You can force it using System.gc(), but be careful to not do it too often, else it will slow down your program. 您可以使用System.gc()强制执行此操作,但请注意不要经常执行此操作,否则会减慢程序速度。

Your code runs fine, and here is what I've tested: 您的代码运行良好,这是我测试过的内容:

public static void buildColorHistogram(BufferedImage image)
{
final int pixelLength = 3;

byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();

for (int pixel=0 ; pixel < pixels.length; pixel+=pixelLength)
    {
    final int blue = pixels[pixel] & 0xff ; // blue
    final int green= pixels[pixel + 1] & 0xff ; // green
    final int red  = pixels[pixel + 2] & 0xff ; // red
    Color color = new Color(red, green, blue) ;
        if ( histogram.containsKey(color) )
            histogram.get(color).incrementAndGet() ;
        else
            histogram.put(color, new AtomicInteger(1)) ;
    }

pixels = null ;
}

Be careful that some color images have also an alpha channel, which means that pixelLength will be 4 instead of 3. 请注意,某些彩色图像也具有Alpha通道,这意味着pixelLength将为4而不是3。

Do you empty out (flush) the histogram when you're done with it? 完成处理后,是否清空(刷新)直方图? Because there are 16 millions combinations/triplets of color. 因为有1600万种颜色的组合/三元组。

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

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