如何以编程方式旋转存储为1D数组的位图图像?

时间:2014-10-05 06:57:35

标签: java bitmap

我有一个类Bitmap,它只包含一个rgba值的像素数组,我已经在互联网上搜索过无效的答案。

我怎样才能创建一个叫做的函数,比如说;

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
}

2 个答案:

答案 0 :(得分:2)

首先,无法进行旋转 - 您需要将旋转后的图像绘制到不同的缓冲区中。要模拟就地旋转,仍然需要获取数组的副本。

此外,除非旋转180°,否则旋转矩形图像的结果将占据比原始图像更大的矩形,因此当绘制回原始缓冲区时,其角将被剪掉。

无论如何,这是一种方法,通过将像素数组包装在BufferedImage中并调用AWT的帮助(import java.awt。*和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();
}

方法asBufferedImage()返回由相同像素数组支持的新BufferedImage,因此通过像素数组或BufferedImage进行的更改正在修改相同的内容。我们这样做,所以我们可以使用Java的图形管道数组。我们通过pixels.clone()获取源图像的​​副本,以便阅读。 Arrays.fill调用会将目标缓冲区清除为透明黑色,因此我们不会在两侧看到原始图像的部分内容。 setRenderingHints电话是可选的;它打开了双线性抗锯齿,所以它看起来更好,虽然它确实在速度上花费。 setComposite(AlphaComposite.Src)调用是一项次要优化,可防止混合。默认合成模式SrcOver会将新像素与图像中已有的像素混合,而Src只需替换现有像素。由于我们知道图像缓冲区被清除为透明黑色,因此混合或不混合具有相同的效果。 AffineTransform是一个封装2D坐标变换的矩阵,在这种情况下是一个关于点的旋转,我们用它来变换Graphics对象绘制的内容。然后我们画它!

答案 1 :(得分:0)

你可以扩展Point,然后使用translate(dx,dy)方法做你想做的事情,例如:

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