This looks like Java behavior not specific to SimpleITK. In the line:
this.series = filter.execute(this.series);
the variable this.series now points to a new memory location and the old one is still around waiting to be garbage collected (assuming no-one else is pointing at that memory location). You can request collection using System.gc(), but this is just a request and the memory may not be released till later on.
Possibly someone in the community with more Java expertise can comment more about Java memory management.
even using System.gc() right after the filter, memory continues basically the same.
A question, was it expected that a series that occupies 118MB in disk would occupy 570MB in memory?
I mean, I don’t understand why it takes up almost 6 times more space.
As I said and as the documentation says, calling System.gc() is requesting/hinting to Java to invoke the garbage collector, it isn’t directly invoking it. I don’t know if there is a way to force immediate garbage collection which is why I asked for input from the community.
This is more of a Java issue, so possibly ask on in a forum dedicated to the language.
Also the SimpleITK library is a native library for JAVA, and that adds an additional layer of complexity to the memory management.
This article looks interesting:
How are you measuring memory allocation for the application? Just because the application has memory allocated does not mean that it is physically occupying the memory on the computer. This can happen when large libraries are mapped to memory and not physically loaded into memory ( SimpleITK is a large library ).
The result of JProfiler are way too different from task manager and
resource monitor.
I think the JProfiler is not considering the jni lib heap memory (.dll).
To estimate the size of the image in memory, it is the number of pixels multiplied by the size of the pixel type. What are these values and your results?
the method getItkLightVersionID is a enum method that returns de pixelID light version, basically map the higher bits version to the lower 8 bits version, keeping the sign (signed or unsigned) and type (scalar, vector or label).
The method you are using is simply coercing the values into uint8 so values that were originally negative and values that were greater than 255 are not represented correctly. You can read the image with the original intensity range, linearly rescale the intensities to [0,255] and then cast to uint8 and the image will look OK, but you will be loosing information that was contained in the original image.
There is no magic, you cannot directly fit the same amount of information into less memory (this isn’t a compressed representation of the values).
I managed to reproduce what you told me but it’s still not 100%, some layers are too white, see the layer scroll function and the jump in brightness. This doesn’t happen in other viewers even using default values for wcww.