2016-05-30 12 views
8

Stiamo costruendo un'applicazione Android che comporta l'editing delle immagini. Alcune delle funzioni includono la rotazione di un'immagine e la cancellazione di parte dell'immagine.La cancellazione di un'immagine ruotata in Android non mostra la cancellazione del percorso corretto

Stiamo utilizzando la seguente libreria: https://github.com/nimengbo/StickerView

abbiamo creato con successo una funzione per ruotare e cancellare l'immagine. Tuttavia, quando abbiamo provato a eseguire le seguenti azioni:

  1. Rotazione di un'immagine in una certa misura.
  2. Quindi, cancellando l'immagine.

Abbiamo trovato il seguente errore:

  1. Quando abbiamo cercato di cancellare l'immagine ruotata, il percorso cancellato non rifletteva il percorso che il nostro dito tracciato sullo schermo.

enter image description here

dall'immagine qui sopra, la linea gialla è il movimento reale del dito (verso il basso verticale attraverso l'adesivo). Ma, il percorso cancellato risultante è stato trovato per essere diagonale.

Questo problema esiste solo quando l'immagine viene ruotata. Non esiste quando l'immagine non viene ruotata.

Dopo ulteriore debugging, abbiamo alcune assunzioni dai problemi di cui sopra:

  1. causa dell'immagine ruotata, x ed y posizione assoluzione viene cambiata. Pertanto, il percorso non riflette il percorso corretto per le rotte tattili.

Come possiamo garantire che il percorso stia ancora facendo riferimento al percorso corretto su ciò che il dito sta toccando anche dopo essere stato ruotato?

Ecco il codice che abbiamo nella nostra classe StickerView.java che estende la classe ImageView.

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

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

risposta

4

È Ne ed per applicare le matrici di rotazione sulle tue coordinate. Qui theta è l'angolo di rotazione dell'immagine. You Need to Apply Matrix rotation

Fonte immagine wikipedia

Nel codice che sarà qualcosa di simile

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

Dove devo applicare la matrice di rotazione? È nella posizione di onTouchEvent? O alla funzione getAbsolutePosition? –

+0

Supponiamo che theta è l'angolo con cui è stato ruotato imageView. Quindi abbiamo bisogno di ruotare la posizione di cancellazione (o la posizione di tocco in corso) per (-theta) i.e negativo di theta. Per fare ciò applicare la trasformazione sul luogo in cui l'utente tocca lo schermo usando (-theta) e quindi cancellare le coordinate ottenute come risultato da imageView. –

+0

È possibile calcolare l'intero percorso di cancellazione, in primo luogo, senza applicare alcuna trasformazione. Quindi, una volta calcolato l'intero percorso, è possibile applicare la trasformazione su tutto il percorso e ottenere un percorso risultante. Quindi cancella questo percorso trasformato dall'immagine –

2

Stai ruotando l'intera vista nel metodo OnDraw. Non solo ciò influenza le prestazioni (stai ripetendo la stessa trasformazione ogni volta), influisce sul risultato come hai notato dal momento che ruota tutto nella vista, compresi i percorsi.

Se per qualche motivo è necessario farlo in questo modo (non consigliato), quindi è necessario ruotare i percorsi nella direzione opposta della stessa quantità. Vi suggerisco caldamente di non farlo. Cerca invece di trovare un modo per ruotare lo sfondo all'interno di onDraw. Ad esempio, ogni volta che lo sfondo viene ruotato, puoi creare un nuovo sfondo (al di fuori del metodo onDraw) e utilizzare quello sfondo nel metodo onDraw.

Problemi correlati