Disable Java Image

The same question as last time, but I will tell in more detail. I am currently rotating images using:

int rotateNum //in main class double rotationRequired = Math.toRadians(rotateNum); double locationX = img.getWidth(this) / 2; double locationY = img.getHeight(this) / 2; AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, locationX, locationY); AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR); g2d.drawImage(op.filter((BufferedImage)img, null), imgX, imgY, null); 

And then I actually rotate the image using:

 double deltaX = (double)(imgY - otherImg.imgY); double deltaY = (double)(imgX - otherImg.imgX); rotateNum = (int)(180 * Math.atan2(deltaY, deltaX) / Math.PI); 

My images vary in size. Smaller images are not cropped (which means cropping with white space), but larger ones are on the left or right side. Resizing images does not work, and I cut a white rectangle around the image using GIMP.

Sample images: Before (ignore the gray box on the left)

After: See Side Circumcision

+7
source share
4 answers

I guess this is not the size of the image, but its eccentricity: images that are more quadratic have less problem than images that are thicker or thinner.

I think your problem is that your center of rotation should not be [width / 2, height / 2] - it is not so simple. Instead, think of the image in the upper left of the large square, the length of the square side will be equal to the width or height of the image, whichever is greater. This is what rotates with every rotation of the image.

For example, see my answer here: stack overflow

+2
source

The problem is that the original image is not exactly quadratic. When you do an AffineTransform rotation with at.rotate (-rad, width / 2, height / 2), this is the same as:

 at.translate(width/2,height/2); at.rotate(rads); at.translate(-width/2,-height/2); 

So, when it executes the last line, it leads to the beginning. And if the width is greater than y (or vice versa), then the origin of the transformation will be transferred to a shorter distance than the side of a larger length.

For example, if your width is 30 and your height is 60, then the start point will be set to (-15, -30), from which the original value was set. Thus, when you translate it, say, 90 degrees, the image will end with a “width” of 60 and a “height” of 30, but according to the starting point, the original bottom of the image will be drawn at (-30.0), so it overflows AffineTransform at -15 along the X axis. Then this part of the image will be cut out.

To fix this, you can use the following code:

 double degreesToRotate = 90; double locationX =bufferedImage.getWidth() / 2; double locationY = bufferedImage.getHeight() / 2; double diff = Math.abs(bufferedImage.getWidth() - bufferedImage.getHeight()); //To correct the set of origin point and the overflow double rotationRequired = Math.toRadians(degreesToRotate); double unitX = Math.abs(Math.cos(rotationRequired)); double unitY = Math.abs(Math.sin(rotationRequired)); double correctUx = unitX; double correctUy = unitY; //if the height is greater than the width, so you have to 'change' the axis to correct the overflow if(bufferedImage.getWidth() < bufferedImage.getHeight()){ correctUx = unitY; correctUy = unitX; } int posAffineTransformOpX = posX-(int)(locationX)-(int)(correctUx*diff); int posAffineTransformOpY = posY-(int)(locationY)-(int)(correctUy*diff); //translate the image center to same diff that dislocates the origin, to correct its point set AffineTransform objTrans = new AffineTransform(); objTrans.translate(correctUx*diff, correctUy*diff); objTrans.rotate(rotationRequired, locationX, locationY); AffineTransformOp op = new AffineTransformOp(objTrans, AffineTransformOp.TYPE_BILINEAR); // Drawing the rotated image at the required drawing locations graphic2dObj.drawImage(op.filter(bufferedImage, null), posAffineTransformOpX, posAffineTransformOpY, null); 

Hope this helps.

+3
source

This is what java does, unfortunately. One way to solve it is to make the shape square so that there is no cropping during rotation.

This problem is highlighted in David’s book "Killing Java Programming", books_google_killer + game + programming + cropping + rotation , which is great if you want to do any programming of a java game (even if it's a little outdated).

Edit :: This conversion of the image into a square can either be done with the raw image through the image editing software, or through java itself. Perhaps turn your own spinning method, which can check for such collisions.

+1
source

Rotating an image can also affect image size. Here is the code I found on old Sun forums a long time ago (I forgot the original poster). It recalculates the size required to display the image at a given rotation angle:

 import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import java.io.*; import java.net.*; import javax.imageio.*; import javax.swing.*; public class RotateImage { public static void main(String[] args) throws IOException { URL url = new URL("https://blogs.oracle.com/jag/resource/JagHeadshot-small.jpg"); BufferedImage original = ImageIO.read(url); GraphicsConfiguration gc = getDefaultConfiguration(); BufferedImage rotated1 = tilt(original, -Math.PI/2, gc); BufferedImage rotated2 = tilt(original, +Math.PI/4, gc); BufferedImage rotated3 = tilt(original, Math.PI, gc); display(original, rotated1, rotated2, rotated3); } public static BufferedImage tilt(BufferedImage image, double angle, GraphicsConfiguration gc) { double sin = Math.abs(Math.sin(angle)), cos = Math.abs(Math.cos(angle)); int w = image.getWidth(), h = image.getHeight(); int neww = (int)Math.floor(w*cos+h*sin), newh = (int)Math.floor(h*cos+w*sin); int transparency = image.getColorModel().getTransparency(); System.out.println(transparency); // BufferedImage result = gc.createCompatibleImage(neww, newh, transparency); BufferedImage result = gc.createCompatibleImage(neww, newh, Transparency.TRANSLUCENT); Graphics2D g = result.createGraphics(); g.translate((neww-w)/2, (newh-h)/2); g.rotate(angle, w/2, h/2); g.drawRenderedImage(image, null); return result; } public static GraphicsConfiguration getDefaultConfiguration() { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gd = ge.getDefaultScreenDevice(); return gd.getDefaultConfiguration(); } public static void display(BufferedImage im1, BufferedImage im2, BufferedImage im3, BufferedImage im4) { JPanel cp = new JPanel(new GridLayout(2,2)); addImage(cp, im1, "original"); addImage(cp, im2, "rotate -PI/2"); addImage(cp, im3, "rotate +PI/4"); addImage(cp, im4, "rotate PI"); JFrame f = new JFrame("RotateImage"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setContentPane(cp); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); } static void addImage(Container cp, BufferedImage im, String title) { JLabel lbl = new JLabel(new ImageIcon(im)); lbl.setBorder(BorderFactory.createTitledBorder(title)); cp.add(lbl); } } 
+1
source

All Articles