Java Forum / General / October 2005
JAI - Reduce memory requirements for TIF --> JPEG translation
carl.manaster@gmail.com - 21 Oct 2005 16:56 GMT Hi,
I'm using the following code, copied off the internet, to translate a TIF file to JPEG format. It works, but runs out of memory on one of my machines. I can "solve" that by giving Java more memory at launch, but this is running in a context where I don't have easy access to those parameters, so I would prefer to reduce the memory requirements for the function. I'm still reading up on JAI and it's a lot to take in at one time; I'd appreciate any pointers to more memory-efficient ways to go about this. Thanks!
Peace, --Carl
public static void main(String[] args) { final String path = "//images//sample"; RenderedImage image = JAI.create("fileload", path + ".tif"); WritableRaster raster = image.copyData(null); writeJpegFile(path + ".jpg", image, raster); }
private static void writeJpegFile( String filename, RenderedImage image, WritableRaster raster) { BufferedImage bi = new BufferedImage( image.getColorModel(), raster, true, null);
BufferedImage bi2 = new BufferedImage( bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g2 = bi2.createGraphics(); g2.drawImage(bi, 0, 0, null); PlanarImage pi = PlanarImage.wrapRenderedImage(bi2); JAI.create( "FileStore", pi, filename, "JPEG", new JPEGEncodeParam()); }
Andrew Thompson - 21 Oct 2005 17:48 GMT > I'm using the following code, copied off the internet, to translate a > TIF file to JPEG format. It works, but runs out of memory on one of my > machines. I can "solve" that by giving Java more memory at launch, but > this is running in a context where I don't have easy access to those > parameters, What context is that?
An 'all-permissions' Webstart application or applet can have memory set for them. As can an application launched from the command line (or a 'double clickable call to java/javaw').
What is this context in which you can write images but not set memory levels ..a servlet? ..trusted applet?
carl.manaster@gmail.com - 21 Oct 2005 18:19 GMT Hi, Andrew,
>What context is that? It's a servlet, running on (or in?) tomcat, on a machine that has other things going on and where I don't have a sense of what resources are available or how much contention there is for them. I'm a programmer, don't know much about sys admin.
And I have bigger-picture requirements - the jpeg translation is just a small part of a bigger program; I need memory for other parts of that program as well. If I can reduce the memory requirements here, I'd prefer that to just throwing memory at the problem.
Peace, --Carl
Andrew Thompson - 22 Oct 2005 05:17 GMT >>What context is that? > > It's a servlet, ... Thanks for clarifying. That explains to me why you need this.
I notice Andrey is helping you with the technical side of it. You would be hard pressed to find better help, when it comes to image manipulation, so I'll..
'Hush up, and listen..'
Andrey Kuznetsov - 21 Oct 2005 18:40 GMT > I'm using the following code, copied off the internet, to translate a > TIF file to JPEG format. It works, but runs out of memory on one of my [quoted text clipped - 4 lines] > time; I'd appreciate any pointers to more memory-efficient ways to go > about this. Thanks! you consume too much memory because you creates WriteableRaster and 2 BufferedImages.
You can avoid it and make it much shorter: wrap your _first_ RenderedImage into PlanarImage and use appropriate JAI OP to make it GRAY. then save it.
 Signature Andrey Kuznetsov http://uio.imagero.com Unified I/O for Java http://reader.imagero.com Java image reader http://jgui.imagero.com Java GUI components and utilities
carl.manaster@gmail.com - 21 Oct 2005 20:16 GMT Hi, Andrey,
Thank you for the help. When I use the code below, I get
Only 1, or 3-band byte data may be written.
which I believe is what originally led me to create the second BufferedImage. Maybe this isn't the "appropriate JAI OP" you had in mind?
Thanks, --Carl
private static void writeJpegFile2( String filename, RenderedImage image, WritableRaster raster) {
BufferedImage bi = new BufferedImage( image.getColorModel(), raster, true, null);
Graphics2D g = bi.createGraphics(); g.drawImage(bi, 0, 0, null); PlanarImage pi = PlanarImage.wrapRenderedImage(bi);
ComponentColorModel cm = new ComponentColorModel( ColorSpace.getInstance(ColorSpace.CS_GRAY), false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT); ParameterBlock pb = new ParameterBlock(); pb.addSource(pi).add(cm); RenderedOp ro = JAI.create("ColorConvert", pb);
JAI.create("FileStore", ro, filename, "JPEG", new JPEGEncodeParam()); }
Andrey Kuznetsov - 21 Oct 2005 20:36 GMT > Thank you for the help. When I use the code below, I get > [quoted text clipped - 3 lines] > BufferedImage. Maybe this isn't the "appropriate JAI OP" you had in > mind? appropriate JAI OP may be "bandcombine".
You should anyway look at JAI documentation. more info about JAI (and also mailing list) you can find at http://jai.dev.java.net
 Signature Andrey Kuznetsov http://uio.imagero.com Unified I/O for Java http://reader.imagero.com Java image reader http://jgui.imagero.com Java GUI components and utilities
carl.manaster@gmail.com - 21 Oct 2005 21:46 GMT Thanks, Andrey,
> You should anyway look at JAI documentation. I am, I am. But it's an ocean of information and I want only a teaspoon or so to solve my immediate problem. So I appreciate the help of people like you who can get directly to the answer. Case in point: last week I wanted to split TIF images by page; since JAI was required for all my work with TIFs up to this point, it seemed natural that JAI would do this. It was a reasonable assumption for a newbie, but a wrong one. You steered me away from JAI (for that), and I got to learn the ugly innards of TIF files. I could have floundered in the JAI ocean for weeks before coming to that realization on my own. So, thanks for the help.
Peace, --Carl
Andrey Kuznetsov - 21 Oct 2005 21:50 GMT > which I believe is what originally led me to create the second > BufferedImage. anyway you don't need WritableRaster and second BufferedImage. Just draw your first RenderedImage into BufferedImage wrap it in PlanarImage and save
 Signature Andrey Kuznetsov http://uio.imagero.com Unified I/O for Java http://reader.imagero.com Java image reader http://jgui.imagero.com Java GUI components and utilities
Roedy Green - 22 Oct 2005 00:31 GMT >anyway you don't need WritableRaster and second BufferedImage. >Just draw your first RenderedImage into BufferedImage wrap it in PlanarImage >and save you speak with a crisp confidence. Would you care to share some thoughts on how you went about developing your experitise?
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Andrew Thompson - 22 Oct 2005 05:22 GMT >>anyway you don't need WritableRaster and second BufferedImage. >>Just draw your first RenderedImage into BufferedImage wrap it in PlanarImage >>and save > > you speak with a crisp confidence. Would you care to share some > thoughts on how you went about developing your experitise? I read that and was not sure what you meant.
One possible answer is "Andey wrote an image library". [ I do not know whether that qualifies as something that develops the 'expertise', or whether you would be assuming that someone who wrote a library should already *have* the expertise, but.. ]
How about a simpler answer? "Using them a lot."
Roedy Green - 22 Oct 2005 05:41 GMT >> you speak with a crisp confidence. Would you care to share some >> thoughts on how you went about developing your experitise? > >I read that and was not sure what you meant. He might have said something like:
1. I was give a very complicated image processing task by some Russian pornographers and told my dog would meet an untimely end if I failed. So I wrote a set of tiny test programs to exercise each class until I learned its peculiarities before I started gluing them together. My notes about the peculiarities of each class are posted at xxxx.
2. I read this terrific book....
3. I found this incredibly good tutorial...
4. I learned the classes in this order, gradually adding complexity...
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Andrey Kuznetsov - 22 Oct 2005 09:19 GMT Roedy,
>>anyway you don't need WritableRaster and second BufferedImage. >>Just draw your first RenderedImage into BufferedImage wrap it in [quoted text clipped - 3 lines] > you speak with a crisp confidence. Would you care to share some > thoughts on how you went about developing your experitise? My answer is based on his code. With suggested changes code looks like this:
public static void main(String[] args) { final String path = "//images//sample"; RenderedImage image = JAI.create("fileload", path + ".tif"); writeJpegFile(path + ".jpg", image); }
private static void writeJpegFile( String filename, RenderedImage image) {
BufferedImage bi2 = new BufferedImage( image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g2 = bi2.createGraphics(); g2.drawImage(image, 0, 0, null); PlanarImage pi = PlanarImage.wrapRenderedImage(bi2); JAI.create( "FileStore", pi, filename, "JPEG", new JPEGEncodeParam()); }
 Signature Andrey Kuznetsov http://uio.imagero.com Unified I/O for Java http://reader.imagero.com Java image reader http://jgui.imagero.com Java GUI components and utilities
Andrey Kuznetsov - 22 Oct 2005 09:40 GMT BTW if you use JAI only to save image, you may better use ImageIO - in this case you don't need even PlanarImage and can save BufferedImage direct.
 Signature Andrey Kuznetsov http://uio.imagero.com Unified I/O for Java http://reader.imagero.com Java image reader http://jgui.imagero.com Java GUI components and utilities
carl.manaster@gmail.com - 24 Oct 2005 17:45 GMT Hi, Andrey,
Thank you for the code. Unfortunately, TYPE_BYTE_GRAY leaves me with a pure black jpeg. When I substitute TYPE_USHORT_GRAY, I get back "Only 1, or 3-band byte data may be written." So obviously I need to keep playing.
Peace, --Carl
Andrey Kuznetsov - 25 Oct 2005 19:51 GMT > Thank you for the code. Unfortunately, TYPE_BYTE_GRAY leaves me with a > pure black jpeg. When I substitute TYPE_USHORT_GRAY, I get back "Only > 1, or 3-band byte data may be written." So obviously I need to keep > playing. You should take TYPE_INT_RGB for color images and TYPE_BYTE_GRAY for grayscale images. The question is - what type has your original image?
 Signature Andrey Kuznetsov http://uio.imagero.com Unified I/O for Java http://reader.imagero.com Java image reader http://jgui.imagero.com Java GUI components and utilities
Andrey Kuznetsov - 25 Oct 2005 19:59 GMT BTW for RenderedImage you should use another drawImage form - drawRenderedImage();
 Signature Andrey Kuznetsov http://uio.imagero.com Unified I/O for Java http://reader.imagero.com Java image reader http://jgui.imagero.com Java GUI components and utilities
Roedy Green - 22 Oct 2005 00:34 GMT On 21 Oct 2005 08:56:06 -0700, carl.manaster@gmail.com wrote or quoted
>I'm using the following code, copied off the internet, to translate a >TIF file to JPEG format. It works, but runs out of memory on one of my [quoted text clipped - 4 lines] >time; I'd appreciate any pointers to more memory-efficient ways to go >about this. Thanks! Others will give you more specific advice based on your code. Here is some general advice for problems of this sort.
First, make sure you are not packratting, gradually accumulating objects you no longer need. You need a profiler to determine this, or you can do crude measures of memory availability as you progress.
see http://mindprod.com/jgloss/packratting.html http://mindprod.com/jgloss/profiler.html
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|