Why does BufferedImage require so much memory beyond the size of the data array?

I am trying to determine how many heaps any given TYPE_INT_ARGB BufferedImage will use so that for a program that does some image I can set a reasonable maximum heap based on the size of the image that we feed it.

As a test, I wrote the following program, which I then used to determine the smallest maximum heap at which it would work without OutOfMemoryError :

 import java.awt.image.BufferedImage; public class Test { public static void main(String[] args) { final int w = Integer.parseInt(args[0]); final int h = Integer.parseInt(args[1]); final BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); System.out.println((4*w*h) >> 20); } } 

(The printed value is the expected size of the int[] in which the BufferedImage pixel data is stored.) I expected to find that the required maximum heap is something like x + c , where x is the size of the data array and c is a constant consisting from the sizes of the loaded classes, the BufferedImage object, etc. This is what I found instead (all values ​​are in MB):

  4 * w * h min max heap
 ----- ------------
   5 -
  10 15
  20 31
  40 61
  80 121
 160,241

1.5x well suited for observation. (Note that I did not find a minimum for a 5 MB image.) I do not understand what I see. What are these extra bytes?

+4
source share
3 answers

In further research, the problem is that the old generation in the heap cannot expand sufficiently to accommodate the image data array, despite the fact that the heap has enough free memory.

For more information on how to expand the old generation, see this question .

+1
source

It seems that the error in the Oracle VM appeared somewhere between 1.6.0_16 and 1.6.0_20. You can even reduce the problem by allocating an int array, since the problem is not only related to BufferedImage.

Since 1.6.0_16, I need a bunch of at least 413 MB to allocate an int array with 100,000,000 elements that seem reasonable. Starting from 1.6.0_20, a heap of at least 573 MB is required for the same operation, although after allocating an array, only 400,000,000 bytes are actually used.

+4
source

Use BigBufferedImage instead of BufferedImage. It saves the image on your hard drive and you don’t need to worry about heap size or physical memory limit . It can store a maximum of 2,147,483,647 pixels (or 46.340 x 46.340 pixels).

Create az empty BigBufferedImage:

  BigBufferedImage image = BigBufferedImage.create( tempDir, width, height, type); 

Load an existing image in BigBufferedImage:

  BigBufferedImage image = BigBufferedImage.create( imagePath, tempDir, type); 

Display part of image:

  part = image.getSubimage(x, y, width, height); 

For more information on large image processing, read this article .

0
source

All Articles