| From | Sent On | Attachments |
|---|---|---|
| Nidel, Mike | Jul 17, 2008 10:22 am | |
| Daniele Romagnoli | Jul 18, 2008 6:52 am | |
| Nidel, Mike | Jul 18, 2008 7:03 am | |
| Simone Giannecchini | Jul 21, 2008 2:05 am | |
| Nidel, Mike | Jul 21, 2008 7:29 am | |
| Simone Giannecchini | Jul 23, 2008 5:24 pm | |
| Nidel, Mike | Jul 23, 2008 8:17 pm |
| Subject: | RE: OutOfMemoryError reading with MrSIDImageReader | |
|---|---|---|
| From: | Nidel, Mike (mike...@lmco.com) | |
| Date: | Jul 21, 2008 7:29:46 am | |
| List: | net.java.dev.imageio-ext.dev | |
I disagree about the default implementation of readAsRenderedImage(), for the reason that I think ImageIO was originally built to handle image formats like PNG, JPG, BMP etc that do not easily scale to large imagery. So all of the plugins built into the JRE don't have a special RenderedImage implementation because they all work in immediate mode. Going back to the JAI ImageCodec implementations for formats like TIFF, you could acquire a RenderedImage implementation for that format. The same is true for the JAI ImageIO tools TIFF ImageReader -- readAsRenderedImage() returns an implementation that does the right thing regarding tiling.
Each of our own custom formats has its own implementation of RenderedImage returned by the ImageReader, and many of them subclass PlanarImage because it provides some inheritable infrastructure. On top of this layer of software (ImageReader and RenderedImage), we also have a layer called ImageSource that abstracts a few additional things, particularly the access to metadata. This layer performs part of the wrapper functionality you're talking about and is pluggable so that you can have a special implementation of ImageSource for each image type if needed. Since only ImageSource deals with ImageReaders in my libraries, I don't have to provide a wrapper implementation of ImageReader itself.
Anyway, I suspect that we will have to just agree to disagree, since I don't think it makes sense to limit the RenderedImage interface -- that normally allows non-immediate tile access -- by binding it to a BufferedImage, which does not.
Right now I have a simple subclass of PlanarImage that wraps the ImageReader and implements getTile() using the ImageReadParam. We'll see if it solves the problem.
Mike
________________________________
From: Simone Giannecchini [mailto:simb...@gmail.com] Sent: Monday, July 21, 2008 5:06 AM To: de...@imageio-ext.dev.java.net Subject: Re: OutOfMemoryError reading with MrSIDImageReader
Ciao Mike, our implementation for the readAsRenderedImage method is the default one, which menas that we fallback on the read method which does return a RenderedImage, by means, as you correctly pointed out,of a BufferedImage. Using bufferedimages to read large raster data is ofcourse impractical since the immediate model is not really suited for that since it tries to load everything in memory. As you might imagine one of our goals is to work with very large images, therefore we are sensble to memory problems like the one you reported, anyway I think that the best way to implement readAsRenderedImage, at least in the various specific plugin is to fallback on the immediate model implementation of the RenderedImage since, IMHO that's the reference model for ImageIO plugins. I think that if we would do something different we might confuse people and deviate from what ImageIO has been built for.
Now, all this is more or less useless for you, but I have to write it for the records of the mailing list :-). I understand your requirements and I have a solution/suggestion to propose. What you basically need is an ImageReaderDecorator (or wrapper? :-) )class which wraps an ImageReader and overrides the calls to readAsRenderedImage reusing the getTile calls in a deferred fashion. While at it, one could also add the capability to do tile caching and multithreaded loading in a very similar fashion to what the ImageRead operation does but in a simple way.
I have been thinking about doing something similar this for a while, so if you have some code that you want to share, we would be glad to add that to the imageio-ext codebase and give a hand.
Ciao, Simone.
On Fri, Jul 18, 2008 at 4:04 PM, Nidel, Mike <mike...@lmco.com> wrote:
I think a reply within 24 hours is pretty good, so no apology needed :)
I hadn't thought about the JAI ImageRead operation, but a solution that uses that would be very similar to implementing a RenderedImage, in the sense that it would require inserting another layer between my existing code and your code. That's OK, it's just not ideal. In the case of ImageRead, I would need a hard dependency on JAI ImageIO tools, which I very much want to avoid (for a few reasons). So given a choice between implementing my OWN RenderedImage wrapper for your ImageReader and implementing a solution that uses ImageRead (which ultimately returns a RenderedImage too), I would choose the first since there's no required dependency.
Essentially a possible GDALRenderedImage could do something like the following:
public Raster getTile(int tileX, int tileY) { Rectangle area = getTileRect(tileX, tileY); // do the math to figure out the tile region ImageReadParam param = new ImageReadParam(); param.setSourceRegion(area); // get only the area for the tile Raster result = myImageReader.readRaster(myImageIndex, param); return result; }
Does this sound right? The rest of the operations would have a default or standard implementation perhaps, just to pass through to the ImageReader.
Mike
________________________________
From: Daniele Romagnoli [mailto:dany...@gmail.com] Sent: Friday, July 18, 2008 9:53 AM To: de...@imageio-ext.dev.java.net Subject: Re: OutOfMemoryError reading with MrSIDImageReader
Mike, sorry for the late reply.
Did you considered the choice of using the JAI-ImageRead operation? It leverages on the Deferred Execution Model which allows to load data only when really needed. In such a case a getTile method will exactly get only the required part of data from the underlying gdal reader.
Anyway I will investigate on the implementation of the readAsRenderedImage method.
Regards, Daniele
On Thu, Jul 17, 2008 at 7:22 PM, Nidel, Mike <mike...@lmco.com> wrote:
I reported earlier that I had been having memory problems when reading MrSID. Here is an example portion of the stack trace:
java.lang.OutOfMemoryError at sun.misc.Unsafe.allocateMemory(Native Method) at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:99) at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:288) at
it.geosolutions.imageio.gdalframework.GDALImageReader.readDatasetRaster( GDALImageReader.java:430) at
it.geosolutions.imageio.gdalframework.GDALImageReader.readDatasetRaster( GDALImageReader.java:325) at
it.geosolutions.imageio.gdalframework.GDALImageReader.read(GDALImageRead er.java:958) at
javax.imageio.ImageReader.readAsRenderedImage(ImageReader.java:1560)
I dug in a bit further and realized that our application assumes that a RenderedImage implementation is available to delay reading of actual pixels. But as the stack trace shows, readAsRenderedImage isn't implemented in GDALImageReader or MrSIDImageReader. So the default implementation in ImageReader gets called which just passes through to ImageReader.read() (which IS implemented in GDALImageReader).
The problem with this is that read() returns a BufferedImage which means that the entire extent of the image is read into memory. For large images this is a problem.
I suppose the GDAL ImageReaders are intended to be used by decoding a single BufferedImage for each subregion/tile/block of the image. This is certainly feasible but it doesn't match the expectation of my existing application, to which the ImageIO-ext library is just a plugin. Right now we use RenderedImage.getTile() for pixel access.
Do you have a recommended solution for this? Is there any alternative to just putting an extra layer in between my app and GDAL/ImageIO-ext to convert getTile(x,y) requests to read() calls?
thanks,
Mike
--------------------------------------------------------------------- To unsubscribe, e-mail: dev-...@imageio-ext.dev.java.net For additional commands, e-mail: dev-...@imageio-ext.dev.java.net
--
------------------------------------------------------- Eng. Daniele Romagnoli Software Engineer
GeoSolutions S.A.S. Via Carignoni 51 55041 Camaiore (LU) Italy
phone: +39 0584983027 fax: +39 0584983027 mob: +39 328 0559267
-------------------------------------------------------
-- ------------------------------------------------------- Eng. Simone Giannecchini President /CEO GeoSolutions S.A.S. Via Carignoni 51 55041 Camaiore (LU) Italy
phone: +39 0584983027 fax: +39 0584983027 mob: +39 333 8128928
-------------------------------------------------------





