rotating and placing images by points OTHER than their upper left corner

I’ve looked at several tutorials, and they offer me no insight in how to do this.

Say I have a square BufferedImage, and I want to place it somewhere so its CENTER (not upper left corner) is at a given location on the underlying component, no matter its rotation. How do I accomplish this? I really don’t care to do explicit 2D math to figure out a false position where its upper left corner is to wind up.

Thanks in advance.

tone

Okay, that’s quite easy to change the position’s anchor to the center or any other arbitrary number. To center the image, just subtract half of the image’s width from the x-position and half of the height from the y-position. Here’s an example:

	public void paint(Graphics g) {
		g.drawImage(img, x-(img.getWidth()/2), y-(img.getHeight()/2), null);
	}

Now to rotate an image, it gets a little more complex. You first need to create a completely empty BufferedImage, with the same width/height of the orignal image and the same transparency (ex. TYPE_INT_ARGB). Then you obtain the Graphics2D object of the empty image by calling createGraphics() on it. You then create an AffineTransform object (located in the java.awt.geom package). Then you call rotate(double, double, double) on your AffineTransform object. The first parameter is your angle to rotate upon, in radians (convert degrees to radians with Math.toRadians(int)). The second parameter is your x-anchor to rotate on. The last parameter is your y-anchor to rotate on. The next step is to call setTransform(AffineTransform) on the Graphics2D object you obtained. The last step is to draw the orignal image onto the empty image at 0,0 (using the Graphics2D again).

Here’s the code to rotate:

public BufferedImage rotate(Image source, int angle) {
	int w = source.getWidth(null);
	int h = source.getHeight(null);
	BufferedImage image = new BufferedImage(w, h, source.getTransparency());
	Graphics2D g = image.createGraphics();

	AffineTransform geom = new AffineTransform();
	geom.rotate(Math.toRadians(angle), w/2, h/2);
	g.setTransform(geom);

	g.drawImage(source, 0, 0, null);
	g.dispose();

	return image;
}

Thanks. I think I just don’t “get” Java2D’s psychology.
I did this my own way:

 
public void drawImage(BufferedImage img, Vec2 origin, Point p, double scale, double rotDegrees) {
        Vec2 offset = origin.scale(-(scale *img.getWidth()), -(scale *img.getHeight()));
        offset.yawBy(-rotDegrees);
        Point offsetPoint = new Point((int)Math.round(offset.x), (int)Math.round(offset.y));
        offsetPoint.translate(p.x,p.y);

        AffineTransform x = AffineTransform.getTranslateInstance(offsetPoint.x, offsetPoint.y);
        x.scale(scale, scale);
        x.rotate(Math.toRadians(rotDegrees));

        g().drawImage(img, x, null);
    }

Well, whatever works for you.

You can either map the bitmap textures to the screen’s pixels, or the screen’s pixels to the bitmaps textures. Hardware prefers to map from its screen space to texture space (for obvious reasons).

I’dsuggest you to use float values for the scale factor and to makes it simplier to translate by using translate directly on Graphics:


 
public void drawImage(Graphics g, Component obs, BufferedImage img, Vec2 origin, Point p, double scale, double rotDegrees) {
        Graphics2D g2 = (Graphics2D)g;        
       // scale may fail if the scale factor is a quotient, i.e. 3/4 will lost precision or behave in an undeterminated way if not calculated with doubles or floats
       Vec2 offset = origin.scale(-((double)scale * (double)img.getWidth(obs)), -((double)scale * (double)img.getHeight(obs)));
        offset.yawBy(-rotDegrees);
        // use Graphics2D instances to make those transforms, that produces faster results
        Point offsetPoint = new Point((int)Math.round(offset.x), (int)Math.round(offset.y));
        /*offsetPoint.translate(p.x,p.y);*/
        g2.translate(p.x, p.y);

        AffineTransform x = AffineTransform.getScaleInstance(scale, scale);
        x.rotate(Math.toRadians(rotDegrees));

        // use an observer! updates are then more accurate
        g().drawImage(img, x, obs);
        // translate back to original coords!
        g2.translate(-offsetPoint.x, -offsetPoint.y);
    }

:smiley: