简体   繁体   中英

Efficient returns of Java BufferedImages

I want to collect some image proccessing methods I wrote over the years in one helper class. I just try to find out, how to be most efficient with methods, that take a BufferedImage as an argument and return a (maybe cool processed one) BufferedImage back to the caller. When I look at code examples here at stack overflow or in open projects I see a lot of different ways to handle the BufferedImages. I usually have

public BufferedImage doCoolStuff(BufferedImage sourceImage) {
        BufferedImage tmpImage = new BufferedImage(w,h,Type);
        tmpImage = processCoolStuff(sourceImage);
        return tmpImage;
}

On the other hand I saw construct like

public BufferedImage doCoolStuff(BufferedImage sourceImage) {
         BufferedImage tmpImage = new BufferedImage(w,h,Type);
         tmpImage = processCoolStuff(sourceImage);
         sourceImage = tmpImage;
         tmpImage.flush();
         return sourceImage;
}

Another variation would be one class variable BufferedImage operatedImage in the whole helper class, that is always reused in the single methods, so that after setting it to new BufferedImage(...) the GarbageCollector COULD remove old stuff.
So my question is, what is the most (memory-)efficient way to handle a BufferedImage in a Java Application from the first Instance (that should exist), over calling maybe a few processing methods with passing it as an argument and getting the proccessed ones back, until a image is then displayed. When reusing the mentioned helper class, it would be nice to know that the handling will not lead to memory leaks etc..:
Thanks in advance,
frankie
Edit: I see im not clear in the question. The situation I have in mind is, when creating new BufferedImage in a processing method seems to be neccessary (geometric changes etc.). So in my view a new BufferedImage will always be created for processing (be it in processCoolStuff() or in doCoolStuff). And the result BufferedImage must be passed back to the caller or the pointer to that instance. But can I rely on the GarbageCollector to remove the sourceImage from Memory then? Or could this sourceImage = tmpImage just solve the question. The flush() was not the best idea, I see.

The most efficient way you could implement doCoolStuff in you example is simply:

public BufferedImage doCoolStuff(BufferedImage sourceImage) {
    return processCoolStuff(sourceImage);
}

(which means that you could potentially just inline processCoolStuff or get rid of the method, as it doesn't really do anything, other than being a facade)...

Wether or not the garbage collector is able to re-claim the memory afterwards, depends on the client code that uses your methods. So in my understanding, you are trying to solve a (potential) problem at the wrong level here.

I have to thank all of you for reading the question and having a constructive contribution. And you all are right with your ideas and notes. Harald, as you noted, the "virtual method" processCoolStuff() is only a facade. Its just a placeholder that indicates, that there is something done with it. When I asked, I thought it would not matter what is done, just that something is done. When I saw Hiran Chauduris Answer, I noted, that it IS important what is done there. Of course, any processing, that could take the original BufferedImage and only paints on it or processes colors and so on, will not lead to the point of my question.

So I tried in my comments and the edit to be clearer, and try to state, that this "virtual method" is one that really needs a new BufferedImage, eg during an upscaling. What leads to something else I overlooked. You all think, if anew BufferedImage is created, it is done in processCoolStuff(). In my world, that was not the case, because this method was "only" a placeholder. So I did the creation of new BufferdImage in the doCoolStoff() Method. But as Andy said, I throw it away the next line. Senseless. I thank Joop for his hint, too. Yes, I try to dispose my Graphics Objects after use and in 80% I dont forget to do it (thanks for the hints on affine.., raster and JavaFX, too. I use them as needed).

What I really never knew or realized, is what user 16320675 stated, that a flush on a Image could influence two objects, that have handle on this one instance.

Regarding Haralds answer, the question is, if the client code has a allready allocated memory (because he passes a BufferedImage as argument), and if the Object is assigned after the call with the resultImage, can I rely on that the Memory of the startImage, all tmpImages beside the one that represents the memory of the returned image, are freed by the garbage collector (what should be the case since they are method-local). I was unsure in that question. And I saw that code on the internet (more than one time), were the incoming sourceImage was reassigned in the method where it was the argument and thought this adresses the memory management.

So, far I thank you all. You solved the question, and if if its only by making it clear to me where I should concentrate on when thinking about this memory management.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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