Android:如何在中心点上旋转位图


84

我一直在寻找解决此问题的解决方案,但无济于事,甚至没有找到答案。文档也没有解释任何东西。

我只是试图使旋转方向朝另一个对象的方向。问题在于位图不是围绕固定点旋转,而是围绕位图(0,0)旋转。

这是我遇到麻烦的代码:

  Matrix mtx = new Matrix();
  mtx.reset();
  mtx.preTranslate(-centerX, -centerY);
  mtx.setRotate((float)direction, -centerX, -centerY);
  mtx.postTranslate(pivotX, pivotY);
  Bitmap rotatedBMP = Bitmap.createBitmap(bitmap, 0, 0, spriteWidth, spriteHeight, mtx, true);
  this.bitmap = rotatedBMP;

奇怪的是,无论如何更改pre/中的值postTranslate()以及中的float参数,都没有关系setRotation()。有人可以帮忙,把我推向正确的方向吗?:)


1
我认为上面的代码是经过几次尝试的变体。似乎mtx.setRotate(dir,x,y)应该自己完成技巧,而不需要所有前置/后置东西。另外,您无需重置新new编辑的矩阵。它已经是身份了。
Mark Storer 2010年

Answers:


101

希望以下代码序列对您有所帮助:

Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight, config);
Canvas canvas = new Canvas(targetBitmap);
Matrix matrix = new Matrix();
matrix.setRotate(mRotation,source.getWidth()/2,source.getHeight()/2);
canvas.drawBitmap(source, matrix, new Paint());

如果从以下方法检查以下方法 ~frameworks\base\graphics\java\android\graphics\Bitmap.java

public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
        Matrix m, boolean filter)

这将解释旋转和平移的作用。


1
您可以使用采用矩阵的Bitmap.createBitmap来做到这一点吗?您如何计算targetWidth和targetHeight?我以为是简单的触发,但是有“更轻松”的方式吗?

请检查以下答案,(对不起,我无法在注释中添加代码)
Sudar Nimalan 2010年

应用时质量变差。有什么办法吗?
MSaudi 2012年

1
更改canvas.drawBitmap(source,matrix,new Paint()); 与canvas.drawBitmap(源,矩阵,新的Paint(Paint.ANTI_ALIAS_FLAG));
Sudar Nimalan

3
只是评论说此过程非常耗费内存,因此不应在分步方法中使用。
MLProgrammer-CiM 2012年

79

编辑:优化代码。

public static Bitmap RotateBitmap(Bitmap source, float angle)
{
      Matrix matrix = new Matrix();
      matrix.postRotate(angle);
      return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}

要从资源获取位图:

Bitmap source = BitmapFactory.decodeResource(this.getResources(), R.drawable.your_img);

尝试使用此方法旋转带有任何w或h的位图:Matrix matrix = new Matrix(); matrix.postRotate(90); bitmapPicture = Bitmap.createBitmap(bitmapPicture,0,0,bitmapPicture.getWidth(),bitmapPicture.getHeight(),matrix,true);
Mark Molina 2013年

当我设置图像点的参数时,这对我来说效果很好。您只需要确保在将位图绘制到画布上时使用矩阵即可。
13年

6
您确定这有效吗?如果RotateBitmap()循环执行N次,则取决于位图的分辨率,您可能会浪费大量内存以及所有这些新的Matrix对象分配。
雷汉2014年

未经测试,但是文档说:“如果源位图是不可变的,并且所请求的子集与源位图本身相同,则将返回源位图,并且不会创建新位图。” 对于Matrix对象,它只是转换坐标类。您可以自由地优化代码以进行重复,并且可以在循环中使用相同的Matrix对象。
2014年

仅供参考,位图必须是可变的
kip2 2015年

25

现在我们要完成游戏的设计,我回到了这个问题,我只是想发布对我有用的东西。

这是旋转矩阵的方法:

this.matrix.reset();
this.matrix.setTranslate(this.floatXpos, this.floatYpos);
this.matrix.postRotate((float)this.direction, this.getCenterX(), this.getCenterY()); 

this.getCenterX()基本上是位图X位置+位图宽度/ 2)

以及绘制位图的方法(通过RenderManager类调用):

canvas.drawBitmap(this.bitmap, this.matrix, null);

因此直截了当是棘手的,但是我感到有点奇怪,我无法让它setRotate紧随其后postTranslate。也许有人知道为什么这行不通?现在所有的位图都可以正确旋转,但是在位图质量上并没有降低一些:/

无论如何,谢谢您的帮助!


前面的答案代码也可以。同样存在质量问题。
MSaudi 2012年

7

您也可以ImageView使用来旋转RotateAnimation

RotateAnimation rotateAnimation = new RotateAnimation(from, to,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                0.5f);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setDuration(ANIMATION_DURATION);
rotateAnimation.setFillAfter(true);

imageView.startAnimation(rotateAnimation);

4
您在回答错误的问题。他不想旋转视图,只希望旋转其中的一个位图。
Mark Storer 2010年

以我的经验,setFillAfter(bool)方法无法正常运行,因为它应在Android API lvl 11及以下版本上使用。因此,开发人员无法在视图对象上使用连续旋转事件,也无法在旋转后获得这些视图的旋转版本。所以@马克斯托勒,Macarse真正回答上来看逻辑上看,如果你设置动画的持续时间为0或一些接近0
格克汗阿克尔巴里斯

5

您可以使用如下所示的内容:


Matrix matrix = new Matrix();
matrix.setRotate(mRotation,source.getWidth()/2,source.getHeight()/2);
RectF rectF = new RectF(0, 0, source.getWidth(), source.getHeight());
matrix.mapRect(rectF);
Bitmap targetBitmap = Bitmap.createBitmap(rectF.width(), rectF.height(), config);
Canvas canvas = new Canvas(targetBitmap);
canvas.drawBitmap(source, matrix, new Paint());


所有解决方案都存在相同的问题:位图质量下降
MSaudi,2012年

更改canvas.drawBitmap(source,matrix,new Paint()); 与canvas.drawBitmap(源,矩阵,新的Paint(Paint.ANTI_ALIAS_FLAG));
Sudar Nimalan

您正在使用什么配置?
Sudar Nimalan

我在下面发布了代码作为答案。无法在评论中写出来。非常感谢先生:)
MSaudi 2012年


1

我使用了这种配置,但仍然存在像素化问题:

Bitmap bmpOriginal = BitmapFactory.decodeResource(this.getResources(), R.drawable.map_pin);
        Bitmap targetBitmap = Bitmap.createBitmap((bmpOriginal.getWidth()),
                (bmpOriginal.getHeight()), 
                Bitmap.Config.ARGB_8888);
        Paint p = new Paint();
        p.setAntiAlias(true);

        Matrix matrix = new Matrix();       
        matrix.setRotate((float) lock.getDirection(),(float) (bmpOriginal.getWidth()/2),
                (float)(bmpOriginal.getHeight()/2));

        RectF rectF = new RectF(0, 0, bmpOriginal.getWidth(), bmpOriginal.getHeight());
        matrix.mapRect(rectF);

        targetBitmap = Bitmap.createBitmap((int)rectF.width(), (int)rectF.height(), Bitmap.Config.ARGB_8888);


        Canvas tempCanvas = new Canvas(targetBitmap); 
        tempCanvas.drawBitmap(bmpOriginal, matrix, p);

1
你可以尝试setFilterBitmap,setDither选项
Sudar Nimalan

1
是的,这很好用。非常感谢Sudar,您确实对我有很大帮助。
2012年

1
:添加链接到你自己的随访与更新的代码stackoverflow.com/questions/13048953/...
克里斯·雷伊

0
matrix.reset();
matrix.setTranslate( anchor.x, anchor.y );
matrix.postRotate((float) rotation , 0,0);
matrix.postTranslate(positionOfAnchor.x, positionOfAnchor.x);
c.drawBitmap(bitmap, matrix, null); 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.