RotatableImageIcon.java
By hansl - July 22nd, 2008
/* * An ImageIcon class with rotation. * * Hans Liss <Hans@Liss.pp.se> 2006 * * ... with a grateful nod to Karl Lager for his illuminating * text "A Fast Algorithm For Rotating Bitmaps". * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * */ import java.awt.*; import java.awt.image.*; import javax.swing.*; import java.net.*; public class RotatableImageIcon extends ImageIcon { private boolean isInitialized=false; private Graphics ibG=null; private BufferedImage iconBuffer=null; private int iw; private int ih; private int nw; private int nh; private int maxx; private int minx; private int maxy; private int miny; private WritableRaster iconRaster; private int[] iconPixels; private BufferedImage iconBuffer2=null; private WritableRaster iconRaster2; private int[] iconPixels2; private ImageIcon rotatedIcon=null; RotatableImageIcon(byte[] imageData ) { super(imageData); RI_Initialize(); } RotatableImageIcon(byte[] imageData, String description) { super(imageData, description); RI_Initialize(); } RotatableImageIcon(Image image) { super(image); RI_Initialize(); } RotatableImageIcon(Image image, String description) { super(image, description); RI_Initialize(); } RotatableImageIcon(String filename) { super(filename); RI_Initialize(); } RotatableImageIcon(String filename, String description) { super(filename, description); RI_Initialize(); } RotatableImageIcon(URL location) { super(location); RI_Initialize(); } RotatableImageIcon(URL location, String description) { super(location, description); RI_Initialize(); } private void RI_Initialize() { Image iconI=getImage(); ImageObserver io=getImageObserver(); int iconW=iconI.getWidth(io); int iconH=iconI.getHeight(io); iconBuffer=new BufferedImage(iconW, iconH, BufferedImage.TYPE_INT_ARGB); ibG=iconBuffer.getGraphics(); paintIcon((Component)io, ibG, 0, 0); iw=getIconWidth(); ih=getIconHeight(); nw=(int)(Math.sqrt(iw*iw + ih*ih)+0.5) & ~1; nh=nw; maxx=(int)(nw/2+0.5); minx=-maxx; maxy=(int)(nh/2+0.5); miny=-maxy; iconBuffer2=new BufferedImage(nw, nh, BufferedImage.TYPE_INT_ARGB); rotatedIcon=new ImageIcon(iconBuffer2); iconRaster = iconBuffer.getRaster(); iconPixels = ( (DataBufferInt) iconRaster.getDataBuffer()).getData(); iconRaster2 = iconBuffer2.getRaster(); iconPixels2 = ( (DataBufferInt) iconRaster2.getDataBuffer()).getData(); isInitialized=true; } /* Karl Lager's algorithm with some extra oomph in the form of pure integer arithmetic (and only one multiplication) inside the loop. This also makes use of the direct raster access functionality of the BufferedImage class. See RI_Initialize(). A hint: don't ever use setRGB() for more than isolated pixels, unless you absolutely have to. */ public ImageIcon rotatedIcon(double angle) { if (!isInitialized) { RI_Initialize(); } double cosT=Math.cos(angle); double sinT=Math.sin(angle); double xpstart=(double)miny*sinT + (double)minx*cosT + 0.5 + iw/2; double ypstart=(double)miny*cosT - (double)minx*sinT + 0.5 + ih/2; int offsbits=16; int numscale=(1<<offsbits); int ixps=(int)(xpstart * numscale); int iyps=(int)(ypstart * numscale); int ist=(int)(sinT * numscale); int ict=(int)(cosT * numscale); int ixp, iyp, xp, yp; int oxp=0, oyp=0; int val=0; int line, col; int linemax=nh*nw; for (line=0; line < linemax; line += nw) { ixp=ixps; iyp=iyps; for (col=0; col<nw; col++) { xp=ixp >> offsbits; yp=iyp >> offsbits; if (xp>=0 && xp<iw && yp>=0 && yp<ih) { /* Avoid unnecessary accesses to the same pixel */ if (xp != oxp || yp != oyp) { val=iconPixels[xp + yp * iw]; oxp=xp; oyp=yp; } } else val=0xffffff; // Note: this is actually transparent! iconPixels2[line + col] = val; ixp += ict; iyp -= ist; } ixps += ist; iyps += ict; } return rotatedIcon; } }


Recent comments
1 year 19 weeks ago
1 year 46 weeks ago
1 year 49 weeks ago
2 years 2 weeks ago
2 years 2 weeks ago
2 years 18 weeks ago
2 years 28 weeks ago
2 years 28 weeks ago
2 years 28 weeks ago
2 years 29 weeks ago