[ACCEPTED]-How to read an image from stream?-png
The Java APIs for reading and manipulating 48 images aren't really stream-based in the 47 way you seem to think. The ImageInputStream
is just a convenience 46 wrapper that allows reading byte
s and other 45 primitive types from different inputs (RandomAccessFile
s, InputStream
s 44 etc).
I've been thinking about creating an 43 API for reading "pixel streams", to 42 allow chaining of processing filters without 41 using much memory. But the need has never 40 been serious enough to be worth the effort. Feel 39 free to hire me, if you like to hear more 38 ideas or have a working implementation. ;-)
Still, as 37 I see it, you have multiple options to achieve 36 your ultimate goal, to be able to process 35 large images:
Use
BufferedImage
as is, and theImageIO
API to 34 read an image in smaller parts to conserve 33 memory. This will be quite efficient for 32 some formats, less efficient for other formats, due 31 to the implementation (i.e. the default 30JPEGImageReader
will read the entire image in native memory 29 before handing smaller region over to the 28 Java heap, but thePNGImageReader
might be okay).Something 27 along the lines of:
ImageInputStream stream = ImageIO.createImageInputStream(input); ImageReader reader = ImageIO.getImageReaders(stream).next(); // TODO: Test hasNext() reader.setInput(stream); int width = reader.getWidth(0); int height = reader.getHeight(0); ImageReadParam param = reader.getDefaultReadParam(); for (int y = 0; y < height; y += 100) { for (int x = 0; x < width; x += 100) { param.setSourceRegion(new Rectangle(x, y, 100, 100)); // TODO: Bounds check // Read a 100 x 100 tile from the image BufferedImage region = reader.read(0, param); // ...process region as needed... } }
Read the entire image 26 at once, into an memory mapped buffer. Feel 25 free to try some experimental classes I've made for this purpose 24 (using
nio
). Reading will be slower than reading 23 to a pure memory image, and processing will 22 also be slower. But if you are doing computations 21 on smaller regions of the image at a time, it 20 could be about as fast as in-memory with 19 some optimizations. I've read > 1 GB 18 images into a 32 MB JVM using these classes 17 (real memory consumption is of course far 16 greater).Again, here's an example:
ImageInputStream stream = ImageIO.createImageInputStream(input); ImageReader reader = ImageIO.getImageReaders(stream).next(); // TODO: Test hasNext() reader.setInput(stream); int width = reader.getWidth(0); int height = reader.getHeight(0); ImageTypeSpecifier spec = reader.getImageTypes(0).next(); // TODO: Test hasNext(); BufferedImage image = MappedImageFactory.createCompatibleMappedImage(width, height, spec) ImageReadParam param = reader.getDefaultReadParam(); param.setDestination(image); image = reader.read(0, param); // Will return same image as created above // ...process image as needed...
Some 15 formats, like uncompressed TIFF, BMP, PPM 14 etc, keeps the pixels in the file in a way 13 that it would be possible to memory-map 12 them directly to manipulate them. Requires 11 some work, but should be possible. TIFF 10 also supports tiles that might be of help. I'll 9 leave this option as an exercise, feel free 8 to use the classes I linked above as a starting 7 point or inspiration. ;-)
JAI may have something 6 that can help you. I'm not a big fan, due 5 to it's many unresolved bugs and lack of 4 love and development by Oracle. But worth 3 checking out. I think they have support for tileable 2 and disk-based
RenderedImage
s as well. Again, I'll leave 1 this option for you to explore further.
The memory problem is surely related not 23 with the decoding process itself but with 22 storing the full image in memory as a BufferedImage
. It 21 is possible to read a PNG image progressively, but:
This 20 is only marginally related to the organization 19 in "chunks", more so with the 18 fact that PNG files are encoded line-by-line, and 17 so they can be -in principle- read line-by-line.
The 16 above assumption breaks in the case of interlaced 15 PNGs - but one should not expect to have 14 huge PNG images stored in interlaced format
While 13 some PNG libraries allow for progressive 12 (line-by-line) decoding (eg: libpng), the standard 11 Java API does not give you that.
I was faced 10 with that problem and I ended up coding 9 my own Java library: PNGJ. It's quite mature, it 8 allows reading PNG images line by line, minimizing 7 memory consumption, and write them in the 6 same way (Even interlaced PNGs can be read, but 5 in this case the memory problem will not 4 go away.) If you only need to do some "local" image 3 processing (modify each pixel value depending 2 on the current value and the neighbours, and 1 write it back) this should help.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.