Reputation: 1243
i have a class, Bitmap,which simply contains a pixel array of rgba values, I've searched all over the internet for an answer to no avail.
How could i create a function called, say;
private int[] pixels;
private int width;
private int height;
/**
*Rotates this image around (x, y) by theta degrees
*/
public void rotate(int theta, int x, int y){
// Code to rotate 1D array here
}
Upvotes: 2
Views: 871
Reputation: 50010
First, it's not possible to do the rotation in place -- you need to draw the rotated image into a different buffer. To simulate an in-place rotation, it is still necessary to take a copy of the array.
Also, unless the rotation is by 180°, the result of rotating a rectangular image is going to occupy a larger rectangle than the original, so its corners will be clipped off when drawn back into the original buffer.
Anyway, here is one way to do this, by wrapping the pixel array in a BufferedImage and invoking the help of AWT (import java.awt.* and java.awt.image.*):
/** Creates an RGBA BufferedImage backed by the specified pixel array. */
static BufferedImage asBufferedImage(int[] pixels, int width, int height) {
ColorModel cm = ColorModel.getRGBdefault();
int[] bandMasks = new int[] { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
DataBuffer dataBuffer = new DataBufferInt(pixels, pixels.length);
WritableRaster raster = Raster.createPackedRaster(
dataBuffer,
width,
height,
width,
bandMasks,
null);
return new BufferedImage(cm, raster, false, null);
}
/** Rotates this image clockwise by an angle in degrees about the point (x, y). */
public void rotate(double theta, double x, double y) {
BufferedImage srcImage = asBufferedImage(pixels.clone(), width, height);
BufferedImage dstImage = asBufferedImage(pixels, width, height);
Arrays.fill(pixels, 0x00000000);
Graphics2D g = dstImage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setComposite(AlphaComposite.Src);
g.transform(AffineTransform.getRotateInstance(theta * (Math.PI / 180), x, y));
g.drawImage(srcImage, null, 0, 0);
g.dispose();
}
The method asBufferedImage()
returns a new BufferedImage backed by the same pixel array, so changes made either through the pixel array or the BufferedImage are modifying the same thing. We do this so we can use the array with Java's graphics pipeline. We take a copy of the source image by pixels.clone()
, to read from. The Arrays.fill
call clears the destination buffer to transparent black, so we don't have parts of the original image visible around the sides. The setRenderingHints
call is optional; it turns on bilinear antialiasing so it looks nicer, although it does cost in speed. The setComposite(AlphaComposite.Src)
call is a minor optimization to prevent blending. The default compositing mode, SrcOver, would blend the new pixels with those already in the image, whereas Src simply replaces the existing pixels. Since we know the image buffer is cleared to transparent black, blending or not blending have the same effect. An AffineTransform is a matrix that encapsulates a 2D coordinate transformation, in this case a rotation about a point, which we use to transform what is drawn by the Graphics object. And then we draw it!
Upvotes: 2
Reputation: 2569
You could extend Point and then use the translate(dx,dy) method to do what you wish, for ex:
public class MyPixel extends Point{
//Your implementation of 'pixel' here
}
public class Bitmap{
private Vector<MyPixel> pixels;
//Implement constructors
public void rotate(int theta){
for(MyPixel p : pixels){
int dx; //Calculate those using theta - they are the change of the x and y coordinates of
int dy; //The point p you will translate.
p.translate(dx,dy);
}
}
public static void main(String[] args){
Bitmap bmp = new Bitmap();
bmp.rotate(30);
}
Upvotes: 0