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()setRotation(). 누군가 제발 도와주고 올바른 방향으로 밀어 줄 수 있습니까? :)


1
위의 코드는 여러 번 시도한 변형 이후입니다. mtx.setRotate (dir, x, y)가 모든 사전 / 사후 항목없이 자체적으로 트릭을 수행해야하는 것처럼 보입니다. 또한 새로 수정 된 new매트릭스 를 재설정 할 필요가 없습니다 . 이미 정체성입니다.
Mark Storer

답변:


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
Matrix를 취하는 Bitmap.createBitmap으로 할 수 있습니까? targetWidth와 targetHeight를 어떻게 계산하고 있습니까? 간단한 삼각법이라고 생각하지만 "더 쉬운"방법이 있습니까?

아래의 대답은, (미안 해요, 난 의견에 코드를 추가 할 수 없습니다) 확인하시기 바랍니다
Sudar Nimalan

이것을 적용하는 동안 품질이 나빠집니다. 어떤 해결책?
MSaudi

1
canvas.drawBitmap (source, matrix, new Paint ()); 변경 canvas.drawBitmap (source, matrix, new Paint (Paint.ANTI_ALIAS_FLAG));
Sudar Nimalan

3
이 프로세스는 메모리를 많이 사용하므로 단계 방법에서 사용해서는 안된다고 언급합니다.
MLProgrammer-CiM

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

이것은 이미지 포인트에 대한 매개 변수를 설정하면서 완벽하게 작동했습니다. 캔버스에 비트 맵을 그릴 때 매트릭스를 사용해야합니다.
a54studio 2013 년

6
이것이 효율적입니까? RotateBitmap ()이 N 번 실행되는 루프에 있었다면 비트 맵의 ​​해상도에 따라 엄청난 양의 메모리와 모든 새로운 Matrix 객체 할당을 낭비 할 수 있습니다.
Ryhan 2014-01-13

테스트되지 않았지만 문서에서는 "소스 비트 맵이 변경 불가능하고 요청 된 하위 집합이 소스 비트 맵 자체와 동일하면 소스 비트 맵이 반환되고 새 비트 맵이 생성되지 않습니다."라고 말합니다. Matrix 객체의 경우 좌표 클래스를 변형하는 것입니다. 반복을 위해 코드를 자유롭게 최적화하고 루프에서 동일한 Matrix 객체를 사용할 수 있습니다.
Arvis

참고로, 비트 맵은 변경 가능해야합니다
kip2

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 2010 년

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

내가 경험했듯이 setFillAfter (bool) 메서드가 Android API lvl 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 2010 년

canvas.drawBitmap (source, matrix, new Paint ()); 변경 canvas.drawBitmap (source, matrix, new Paint (Paint.ANTI_ALIAS_FLAG));
Sudar Nimalan 2012

사용중인 구성은 무엇입니까?
Sudar Nimalan

아래 코드를 답변으로 게시했습니다. 댓글에 쓸 수 없습니다. 정말 고마워요 선생님 :
MSaudi


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 정말 감사합니다. 정말 많이 도와 주셨어요.
MSaudi

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); 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.