2016-05-30 7 views
8

画像編集を含むAndroidアプリケーションを構築しています。いくつかの特徴は、画像を回転させ、画像の一部を消去することである。Androidで回転した画像を消去しても正しいパスが消去されない

我々は次のライブラリを使用している:https://github.com/nimengbo/StickerView

は、我々が正常に回転した画像を消去する機能を作成しました。ただし、次の操作を実行しようとしたとき:

  1. ある程度画像を回転しています。
  2. 次に、イメージを消去します。

我々は、次のバグが見つかりました:

  1. を我々が回転した画像を消去しようとしたときに、消去パスは、私たちの指が画面上でトレースパスを反映するものではありませんでした。上記画像から

enter image description here

、黄色の線は、(まっすぐ垂直ステッカーを横切る)指の実際の動きです。しかし、消去された経路は対角であることが判明した。

この問題は、画像を回転した場合にのみ発生します。イメージが回転していないときは存在しません。

はさらに、デバッグした後、我々は、上記の問題のいくつかの仮定があります

  1. により回転された画像には、xとyの赦免の位置が変更されます。したがって、経路はタッチ経路によって正しい経路を反映しない。

どのようにして、回転した後でも指が触れている正しいパスを経路が参照していることを確認できますか?

クラスを拡張したStickerView.javaクラスのコードは次のとおりです。

onTouchEvent

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    int action = MotionEventCompat.getActionMasked(event); 

    float[] pointXY = new float[2]; 

    pointXY = getAbsolutePosition(event.getX(0),event.getY(0)); 
    float xPoint = pointXY[0]; 
    float yPoint = pointXY[1]; 


    switch (action) { 
     case MotionEvent.ACTION_DOWN: 

      // first touch 
      // if it is inside the image 
      if (isInBitmap(event)) { 
       // set isInSide to true 
       isInSide = true; 

       // if it is a scratch 
       if(doScratch){ 
        // start creating the scratch path 
        mScratchPath = new Path(); 
        mScratchPath.moveTo(xPoint, yPoint); 
        mScratchPath.lineTo(xPoint, yPoint); 
        paths.add(new Pair<Path, Paint>(mScratchPath, mScratchCurrentPaint)); 
       } 
      } 
      break; 
     case MotionEvent.ACTION_MOVE: 

      // if two fingers touch and is not a scratch, 
      // then it means we can rotate/resize/pan 
      if (isPointerDown && !doScratch) { 
       // reset matrix 
       matrix.reset(); 
       // get the center point 
       scaledImageCenterX = (mImageWidth * mScaleFactor)/2 ; 
       scaledImageCenterY = (mImageHeight * mScaleFactor)/2; 

       // ROTATE THE IMAGE !!! 
       matrix.postRotate(lastRotateDegree, scaledImageCenterX, scaledImageCenterY); 

       // done to call onDraw 
       invalidate(); 
      } 
      break; 
    } 

    if (operationListener != null) { 
     operationListener.onEdit(this); 
    } 

    // if it is a scratch 
    if(doScratch){ 
     // then for every point, create a scratch path 
     mScratchPath.lineTo(xPoint, yPoint); 
     invalidate(); 
    }else{ 
     mScaleDetector.onTouchEvent(event); 
     mRotateDetector.onTouchEvent(event); 
     mMoveDetector.onTouchEvent(event); 
     mShoveDetector.onTouchEvent(event); 
    } 
    return handled; 
} 

onDraw

@Override 
protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 

    // if the image exists 
    if (mBitmap != null) { 
     // save canvas 
     canvas.save(); 

     // if it is a scratch 
     if(doScratch){ 
      // scratch the image 
      mFillCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); 

      // Draw our surface, nice an pristine 
      final Drawable surface = mScratchSurface; 
      if(surface != null) { 
       surface.draw(mFillCanvas); 
      } 
      //Scratch the surface 
      if(paths != null) { 
       for (Pair<Path, Paint> p : paths) { 
        mFillCanvas.drawPath(p.first,p.second); 
       } 
      } 
      mBitmap = mFillCache; 
     } 

     canvas.drawBitmap(mBitmap, matrix, bitmapPaint); 
     canvas.restore(); 
    } 
} 

getAbsolutePosition機能

public float[] getAbsolutePosition(float Ax, float Ay) { 
    float[] mMatrixValues = new float[9]; 
    matrix.getValues(mMatrixValues); 

    float x = mImageWidth - ((mMatrixValues[Matrix.MTRANS_X] - Ax)/mMatrixValues[Matrix.MSCALE_X]) - (mImageWidth - getTranslationX()); 

    float y = mImageHeight - ((mMatrixValues[Matrix.MTRANS_Y] - Ay)/mMatrixValues[Matrix.MSCALE_X]) - (mImageHeight - getTranslationY()); 

    return new float[] { x, y}; 
} 

答えて

4

あなたのne座標に回転マットを適用します。ここでthetaは、画像が回転する角度です。コードで You Need to Apply Matrix rotation

イメージソースウィキペディア

それはあなたがonDrawメソッドでビュー全体を回転している。この

int getAbsoluteX(int x, int y, double theta) 
{ 
    int x_new = (int)(x*Math.cos(theta) - y*Math.sin(theta)); 
    return x_new; 
} 

int getAbsoluteY(int x, int y, double theta) 
{ 
    int y_new = (int)(x*Math.sin(theta) + y*Math.cos(theta)); 
    return y_new; 
} 
+0

どこで回転行列を適用すればよいですか? onTouchEventの位置にありますか?またはgetAbsolutePosition関数で? –

+0

thetaは、imageViewが回転された角度であるとします。次に、消去位置(またはオンタッチ位置)を(-theta)すなわちθの負数だけ回転させる必要があります。これを行うには、(-theta)を使用してユーザーが画面に触れる場所で変換を適用し、結果として得られた座標をimageViewから消去します。 –

+0

最初に、変換を適用せずに消去パス全体を計算することができます。その後、パス全体が計算されたら、パス全体に変換を適用して結果のパスを得ることができます。次に、この変換されたパスをイメージから消去します –

2

のようなものになります。これはパフォーマンスに影響するだけでなく(毎回同じ変換を繰り返す)、パスを含めてビュー内のすべてを回転させるため、気付いたように結果に影響を与えます。

何らかの理由でこの方法(推奨されていない)を行う必要がある場合は、反対方向に同じ量だけパスを回転させる必要があります。私はあなたがそうしないことを強く勧めます。代わりにonDrawの中で背景を回転させる方法を見つけてください。たとえば、背景を回転させると、(onDrawメソッドの外に)新しい背景を作成し、その背景をonDrawメソッドで使用することができます。

関連する問題