Android:中心点でビットマップを回転させる方法


84

私はこの問題の解決策を1日以上探していましたが、ここでの答えでさえ、何の助けにもなりません。ドキュメントも何も説明していません。

別のオブジェクトの方向に回転させようとしているだけです。問題は、ビットマップが固定点を中心に回転するのではなく、ビットマップ(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

回答:


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(source、matrix、new Paint(Paint.ANTI_ALIAS_FLAG));
Sudar Nimalan 2012年

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でビットマップを回転させるためにこれを試してください。Matrixmatrix= new Matrix(); matrix.postRotate(90); ビットマップ画像= Bitmap.createBitmap(bitmapPicture、0、0、bitmapPicture.getWidth()、bitmapPicture.getHeight()、matrix、true);
マークモリーナ

イメージポイントのパラメータを設定しているので、これは私にとって完璧に機能しました。ビットマップをキャンバスに描画するときは、必ずマトリックスを使用する必要があります。
a54studio 2013年

6
これが効率的であると確信していますか?RotateBitmap()がN回実行されるループ内にあった場合、ビットマップの解像度によっては、膨大な量のメモリとそれらすべての新しいMatrixオブジェクトの割り当てを浪費する可能性があります。
ライハン2014年

テストされていませんが、ドキュメントには次のように書かれています。「ソースビットマップが不変で、要求されたサブセットがソースビットマップ自体と同じである場合、ソースビットマップが返され、新しいビットマップは作成されません。」Matrixオブジェクトに関しては、座標クラスを変換するだけです。コードを繰り返し最適化して、同じMatrixオブジェクトをループで使用できます。
Arvis 2014年

参考

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

だから、pretteyまっすぐですが、私はそれがで私が仕事にそれを得ることができなかったことを奇妙ABIT見つける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
あなたは間違った質問に答えています。彼はビューを回転させたくはありません。ビュー内の1つのビットマップだけです。
Mark Storer 2010

私が経験したように、setFillAfter(bool)メソッドは、AndroidAPIレベル11以下で期待どおりに機能しません。したがって、開発者はビューオブジェクトで連続回転イベントを使用することも、回転後にこれらのビューの回転バージョンを取得することもできません。あなたが0に0か何かの近くでアニメーションの再生時間を設定した場合、@マークのStorerはそう、Macarseは、論理的な観点に本当に答え
グーカン・バリスアーカー

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(source、matrix、new Paint(Paint.ANTI_ALIAS_FLAG));
Sudar Nimalan 2012年

使用している構成は何ですか?
Sudar Nimalan 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 2012年

1
はい、これは完全に機能しました。スーダーさん、本当にありがとうございました。本当に助けてくれました。
MSaudi 2012年

1
更新されたコードであなた自身のフォローアップへのリンクを追加する:stackoverflow.com/questions/13048953/…–
Chris Rae

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); 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.