Solved

java.lang.OutOfMemoryError with jai

Posted on 2004-08-23
12
703 Views
Last Modified: 2008-02-01
I am loading an image into a renderedOP from a cgi call and udating it based on manipulation inputs (rotate, scale, etc).  After about 3 rotations, the system crashes with an outofmemory error.  This app wil eventually become an applet, so compiling with a larger vm memory size probably won't work as I've seen in other forums.  Those forums also suggest using JAI, but I already am and can't figure out how to avoid the error.
0
Comment
Question by:tigress298
  • 4
  • 3
  • 3
12 Comments
 
LVL 35

Expert Comment

by:TimYates
ID: 11872625
how big is the image?

can you post some code?
0
 

Author Comment

by:tigress298
ID: 11872781
The images are pretty large (about 30,000 pixels length and height each, for the full res image), but I don't know the exact sizes.  The user selects the res.

The code is a bit obfuscated, and I can't give the address of the actual images, but basicall I set up a query string in chipQuery() which I access from showChip() and create the image.  

public void showChip() {
        if (canvas.isVisible() == true) {
            String query = chipQuery();
            java.net.URL url;
            try {
                canvas.getDesktop().getMsgCenter().getMessageArea().setText(
                canvas.getDesktop().getMsgCenter().getMessageArea().getText() +
                "\nAccessing: "+ query);
                url = new java.net.URL(query);
            }
            catch (Exception e) {
                url = null;
                e.printStackTrace();
            }            
            if (url != null) {
                //canvas.getChip().setIcon(new javax.swing.ImageIcon(url));
                currentImage = null;
                currentImage = JAI.create("url", url);
                canvas.getChip().setIcon(new javax.swing.ImageIcon(
                    currentImage.getAsBufferedImage().getScaledInstance(
                    currentImage.getWidth(), currentImage.getHeight(), 0)));
            }
        }
    }

on rotation, which ultimately spawns the error, I set the rotation value in rotate(), and setup the parameter block for rotation in rotateChip()

 public void rotate(int angle) {
        int newAngle = angle;
        if (newAngle != currentRotation) {
            int difference = newAngle - currentRotation;
            rotateChip(difference);
            currentRotation = newAngle;
        }
    }

private void rotateChip(int angle) {
        if (canvas.isVisible() == true) {
            RenderedOp image;
            ParameterBlock pb = new ParameterBlock();
            pb.addSource(currentImage);
            pb.add((float)referencePoint.x);
            pb.add((float)referencePoint.y);
            pb.add((float)Math.toRadians((double)angle));
            pb.add(new InterpolationBilinear());
            image = JAI.create("Rotate", pb, null);
            canvas.getChip().setIcon(new javax.swing.ImageIcon(
                image.getAsBufferedImage().getScaledInstance(
                image.getWidth(), image.getHeight(), 0)));
            currentImage = image;
        }
    }  


Thanks.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 11872852
Could be simply too much to handle if it's too big. Why not try creating tiles of the image and rotating the tiles sequentially? That way you can reduce memory footprint and still get the result you need
0
 
LVL 35

Expert Comment

by:TimYates
ID: 11872885
I'm guessing it's the:

canvas.getChip().setIcon(new javax.swing.ImageIcon(
                image.getAsBufferedImage().getScaledInstance(
                image.getWidth(), image.getHeight(), 0)));

line which throws the exception?

Hmmm...  I *think* you will have to do this by overriding the paintComponent on a JPanel (instead of setting the image as an Icon to a JLabel), and only draw the area that you can see, by using AffineTransform on the Graphics2D object that you get in that function...  

That way, you won't be creating a new Image object each time you do a transformation...

That might help anyway...  I'm not at work at the moment, so I can't dig out much code, but here are some links that may be of some help:

http://javaalmanac.com/egs/java.awt.image/CreateTxImage.html
http://javaalmanac.com/egs/java.awt/TransformImage.html

Remember, override paintComponent (for a JPanel), not paint...

Tim
0
 
LVL 35

Expert Comment

by:TimYates
ID: 11872907
So, as (I think) CEHJ is saying, you will end up with a "stack" of transformations, and your original image...  Before you draw the image, add this stack of AffineTransforms to the Graphics2D object sequentially, then simply draw the image as normal...

Then you only create the image once (when you load it)
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 35

Accepted Solution

by:
TimYates earned 250 total points
ID: 11872911
You may *still* have problems getting an image that big into an applet though...
0
 

Author Comment

by:tigress298
ID: 11873054
How would I go about tiling the image?  

Also, the cgi call is based off the current viewer veriosn (java 1.1) which I'm revamping.  The current call includes among other things, the resLevel, the currentMode(rotate, scale, etc), a reference point (distance from the center of the image for translation), the dimensions of the expected image at the current resLevel, the viewable size (512 or 1024), and the rotation angle.  The cgi handled the image manipulation server side and passed back the image, but is VERY slow, so I'm having a hard time knowing what info to handle inside the applet with JAI, and what to let the server handle (and how to keep the differences reconciled).  Otherwise, loading the image once and handling all manipulations with JAI would be optimal.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 11873070
What i meant was rather than going straight from (using e.g. 180 degree rotation)

¡ ¡ ¡ ¡
¡ ¡ ¡ ¡

to

! ! ! !
! ! ! !

tile and go in steps, reassembling

1.

! ¡ ¡ ¡
¡ ¡ ¡ ¡

2.

! ! ¡ ¡
¡ ¡ ¡ ¡

etc.
0
 

Author Comment

by:tigress298
ID: 11873116
I stil don't know how to go about doing that, though I understand what you're doing.
0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 250 total points
ID: 11873160
Well i don't know JAI but i'd guess it'd have an easy method for tiling an image and you could always fall back on

http://java.sun.com/j2se/1.5.0/docs/api/java/awt/image/BufferedImage.html#getSubimage(int, int, int, int)
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Suggested Solutions

Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Video by: Michael
Viewers learn about how to reduce the potential repetitiveness of coding in main by developing methods to perform specific tasks for their program. Additionally, objects are introduced for the purpose of learning how to call methods in Java. Define …
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now