rotating a bufferedimage

E

e4_java

public class object
{
int x,y
double angle
BufferedImage bi;
JFrame owner;

public void rotate(double angleIncrease)
{
angle += angleIncrease;

Graphics2D g2 = bi.createGraphics();
g2.rotate( Math.toRadians( angleIncrease ) ); // this should rotate
the image stored in bi

// ensure angle is between 0 and 360
if(angle > 360) angle-=360;
if(angle < 0) angle+=360;
}

public void paint(Graphics g)
{
g.drawImage( bi, x, y, owner );
}
}


the image shows up, but rotate doesn't work
calling the rotate method changes the angle value, but the next time
paint is called the image show up unrotated


also rotating the context the method paint draws to won't help because
there will be more than one image displayed on it; each at its own
angle


the buffered image is first produced like this if this makes a
diffence:

// load image from file using swing.ImageIcon
ImageIcon i = new ImageIcon("filename");

// create a blank buffered image with the deminsions of the imageicon
BufferedImage img = new BufferedImage( i.getWidth(), i.getHieght(),
BufferedImage.BufferedImage.TYPE_3BYTE_BGR );

// get the graphics context of the bufferedimage and paint the icon
on to it
Graphics2D g = img.createGraphics();
i.paintIcon( null, g, 0, 0 );
 
J

John McGrath

public class object

the image shows up, but rotate doesn't work

First, I should point out that you do not call your rotate() method
anywhere in the code that you posted.
public void rotate(double angleIncrease)
{
angle += angleIncrease;

Graphics2D g2 = bi.createGraphics();
g2.rotate( Math.toRadians( angleIncrease ) );
// this should rotate the image stored in bi

// ensure angle is between 0 and 360
if(angle > 360) angle-=360;
if(angle < 0) angle+=360;
}

Calling Graphics.rotate() will not have any effect on the image that the
Graphics context was created from (assuming that it actually *was* created
from an image). What it affects is how subsequent paint operations
performed using the Graphics context will be interpreted.

Also note that BufferedImage.createGraphics() creates a new Graphics
context, so doing a rotate() on one Graphics context will have no effect
on painting done with a different Graphics object, even if they were
created from the same BufferedImage.
 
E

e4_java

John McGrath said:
First, I should point out that you do not call your rotate() method
anywhere in the code that you posted.

there is other code that does call it
Calling Graphics.rotate() will not have any effect on the image that the
Graphics context was created from (assuming that it actually *was* created
from an image). What it affects is how subsequent paint operations
performed using the Graphics context will be interpreted.

Also note that BufferedImage.createGraphics() creates a new Graphics
context, so doing a rotate() on one Graphics context will have no effect
on painting done with a different Graphics object, even if they were
created from the same BufferedImage.

ok, then how do i get a Graphics2D that will effect the bufferedimage
it was created from or something else i can use to rotate the contents
of the image?
 
C

Chris Smith

e4_java said:
ok, then how do i get a Graphics2D that will effect the bufferedimage
it was created from or something else i can use to rotate the contents
of the image?

createGraphics does give you a Graphics object that affects the
BufferedImage. The problem is that you didn't actually DO anything.
Calling rotate() only changes the transformation applied to future
drawing operations.

What you can do instead is something like this:

BufferedImage img = getOriginalImage();
BufferedImage temp = new BufferedImage(
img.getWidth(), img.getHeight(), img.getType());

Graphics g2 = (Graphics2D) temp.createGraphics();
try
{
g2.rotate(...);
g2.drawImage(img);
}
finally
{
g2.dispose();
}

Now temp contains a rotated copy of img. If desired, you are free to
copy the new BufferedImage contents back over to img, but it may also
work (and will be cheaper) to simply start using the new object instead.

Note that rotate should be given both an angle and a point around which
to rotate; otherwise, you rotate about the origin (the upper left
corner), which is unlikely to be what you want.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
B

Babu Kalakrishnan

Chris said:
createGraphics does give you a Graphics object that affects the
BufferedImage. The problem is that you didn't actually DO anything.
Calling rotate() only changes the transformation applied to future
drawing operations.

What you can do instead is something like this:

BufferedImage img = getOriginalImage();
BufferedImage temp = new BufferedImage(
img.getWidth(), img.getHeight(), img.getType());

Graphics g2 = (Graphics2D) temp.createGraphics();
try
{
g2.rotate(...);
g2.drawImage(img);
}
finally
{
g2.dispose();
}

Now temp contains a rotated copy of img. If desired, you are free to
copy the new BufferedImage contents back over to img, but it may also
work (and will be cheaper) to simply start using the new object instead.

Note that rotate should be given both an angle and a point around which
to rotate; otherwise, you rotate about the origin (the upper left
corner), which is unlikely to be what you want.

I can see a couple of problems with the above approach. If you want the
entire area of the image to be painted with a rotation angle, the size
of the BufferedImage will need to be larger than that of the image.
(Otherwise you would lose the corners). Of course you can compute the
actual size required, but once you make the BufferedImage bigger, you'll
also need to ensure that the rest of the pixels (on which painting
doesn't take place) are made transparent so that it doesn't interfere
with something else that may be painted in that region of the parent.
(Cannot achieve this by setting clip bounds because all clip rectangles
have to be aligned to the X-Y axis)

BK
 
C

Chris Smith

Babu Kalakrishnan said:
I can see a couple of problems with the above approach. If you want the
entire area of the image to be painted with a rotation angle, the size
of the BufferedImage will need to be larger than that of the image.
(Otherwise you would lose the corners).

Right, but I'm not sure what you'd want in that case. If the original
image has transparent corners or the rotation is by some multiple of
PI/2, then the task makes a lot more sense. Otherwise, you're right: to
be really correct, you'd need both dimensions of the target image to be
at least the size of the diagonal of the original image to be safe.
Of course you can compute the
actual size required, but once you make the BufferedImage bigger, you'll
also need to ensure that the rest of the pixels (on which painting
doesn't take place) are made transparent so that it doesn't interfere
with something else that may be painted in that region of the parent.
(Cannot achieve this by setting clip bounds because all clip rectangles
have to be aligned to the X-Y axis)

Assuming Java 2 (which was already being assumed in my code), you
certainly can create a non-axis-aligned clipping shape.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
E

e4_java

thanks for your help but i resoluted the issue by adding the image to
the sceen using a AffineTransform that rotates the image and the
translates it to the point where it sould appear.

unfornatly, this process is very memory/processor intesive so i can
see it flashing so i had to have it write to a bufferedimage first,
then to the screen.

only, this include wastfully, drawing the whole thing twice and
rotating the image even if no change to its angle occur. so i was
wondering about any ways to imporve performance. (i was thinking is
there a way to force the graphics of paint to not show up on screen
until its operations are complete?)
 
B

Babu Kalakrishnan

e4_java said:
thanks for your help but i resoluted the issue by adding the image to
the sceen using a AffineTransform that rotates the image and the
translates it to the point where it sould appear.

unfornatly, this process is very memory/processor intesive so i can
see it flashing so i had to have it write to a bufferedimage first,
then to the screen.

only, this include wastfully, drawing the whole thing twice and
rotating the image even if no change to its angle occur. so i was
wondering about any ways to imporve performance. (i was thinking is
there a way to force the graphics of paint to not show up on screen
until its operations are complete?)

Why not optimize the writing process (to the BufferedImage) by not
starting from scratch everytime, but only repainting the regions that
have become dirty because an image has undergone a rotation ? Yes you'll
need to perform some computations to determine this - but if the number
of images you have are high and the ones that undergoes a rotation are
comparitively small, this should save you a lot of time.

BK
 

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,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top