JAI - Reduce memory requirements for TIF --> JPEG translation

C

carl.manaster

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());
}
 
A

Andrew Thompson

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?
 
C

carl.manaster

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
 
A

Andrey Kuznetsov

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!

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.
 
C

carl.manaster

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());
}
 
A

Andrey Kuznetsov

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?

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
 
C

carl.manaster

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
 
A

Andrey Kuznetsov

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
 
R

Roedy Green

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?
 
R

Roedy Green

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!

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
 
A

Andrew Thompson

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..'
 
A

Andrew Thompson

Roedy said:
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."
 
R

Roedy Green

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...
 
A

Andrey Kuznetsov

Roedy,
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());
}
 
A

Andrey Kuznetsov

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.
 
C

carl.manaster

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
 
A

Andrey Kuznetsov

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?
 
A

Andrey Kuznetsov

BTW for RenderedImage you should use another drawImage form -
drawRenderedImage();
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top