2

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
}
7
  • Is the bitmap a square? And also, which direction do you plan on rotating it? Isn't there more information that we should have like the dimensions or the direction to flip it? Commented Oct 5, 2014 at 7:04
  • 1
    Can you define what you mean by 'rotate'? (Since it's a 1D array, the regular meaning of rotation-about-an-axis makes no sense to me.) Is it a context-dependent term (i.e. for bitmaps/image processing)? Commented Oct 5, 2014 at 7:04
  • Do you mean to rotate by any number of degrees, or only 90 degrees or 180 degrees? Commented Oct 5, 2014 at 7:15
  • it is a bitmap image stored in a 1 dimensional array and I wish to process the array and produce an array which contains the same image, rotated by theta degrees, clockwise. Commented Oct 5, 2014 at 8:10
  • Do you need it to support Android? If not it's easy; if yes, it might be easy, but I have no idea how to do it. Commented Oct 5, 2014 at 13:13

2 Answers 2

2

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!

Sign up to request clarification or add additional context in comments.

2 Comments

The only problem I have with this is the reason i'm avoiding bufferedimages and graphics in the first place, performance, just using bitmaps and pure integer path makes my program able to simulate thousands of particles with ease. i feel converting between bufferedimages and bitmaps will just be way too expensive
@ShaunWild I guarantee you that BufferedImage and Graphics will be faster than manual Java loops in most ways. Also, there is no conversion overhead in the above because it's not converting, it's just wrapping. That pixel array is both a BufferedImage and a plain array, so if you keep the wrapped image around, you can use either/or depending on which is easiest or fastest for the particular graphics operation.
0

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);
}

5 Comments

No this is not quite what I'm looking for.
Could you be more specific?
You want just part of the image rotated around x,y? Also I'm pretty sure you meant int[] pixels and not int[] pixels[] correct me if I'm wrong
You're not wrong, i'm very tired. :P i just want to rotate the entire image around the point (x, y)
Why not add x,y parameters to my rotate() method and include those in the calculations you require for dx,dy? for ex: rotate(x,y,theta)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.