2013-09-26 15 views
6

In meiner Android-Anwendung möchte ich Bild warp Wirkung in Photo Warp und Photo Deformer Anwendung angewendet anwenden. Dafür habe ich BitmapMesh verwendet. Das Problem ist, dass das verzerrte Bild nicht gespeichert wird. Jedes Mal, wenn ich ein Bild berühre, wird das Bild aktualisiert und das zuvor verzerrte Bild wird nicht gespeichert. Ich möchte das Bild speichern, wenn der Benutzer eine Warp-Operation ausführt. Hier poste ich meinen Code. Hier verwende ich "BitmapMesh" Aktivität, um Warp-Effekt auf Bild durchzuführen.Android - Bild Warp-Effekt

Bitte helfen Sie mir, dieses Problem zu lösen. Danke.

Code:

BitmapMesh Aktivität:

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.Matrix; 
import android.os.Bundle; 
import android.util.FloatMath; 
import android.view.MotionEvent; 
import android.view.View; 

public class BitmapMesh extends GraphicsActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(new SampleView(this)); 
    } 

    private static class SampleView extends View { 
     private static final int WIDTH = 20; 
     private static final int HEIGHT = 20; 
     private static final int COUNT = (WIDTH + 1) * (HEIGHT + 1); 

     private final Bitmap mBitmap; 
     private final float[] mVerts = new float[COUNT * 2]; 
     private final float[] mOrig = new float[COUNT * 2]; 

     private final Matrix mMatrix = new Matrix(); 
     private final Matrix mInverse = new Matrix(); 

     private static void setXY(float[] array, int index, float x, float y) { 
      array[index * 2 + 0] = x; 
      array[index * 2 + 1] = y; 
     } 

     public SampleView(Context context) { 
      super(context); 
      setFocusable(true); 

      mBitmap = BitmapFactory.decodeResource(getResources(), 
        R.drawable.image1); 

      float w = mBitmap.getWidth(); 
      float h = mBitmap.getHeight(); 
      // construct our mesh 
      int index = 0; 
      for (int y = 0; y <= HEIGHT; y++) { 
       float fy = h * y/HEIGHT; 
       for (int x = 0; x <= WIDTH; x++) { 
        float fx = w * x/WIDTH; 
        setXY(mVerts, index, fx, fy); 
        setXY(mOrig, index, fx, fy); 
        index += 1; 
       } 
      } 

      mMatrix.setTranslate(10, 10); 
      mMatrix.invert(mInverse); 
     } 

     @Override 
     protected void onDraw(Canvas canvas) { 
      canvas.drawColor(0xFFCCCCCC); 

      canvas.concat(mMatrix); 
      canvas.drawBitmapMesh(mBitmap, WIDTH, HEIGHT, mVerts, 0, null, 0, 
        null); 
     } 

     private void warp(float cx, float cy) { 
      final float K = 10000; 
      float[] src = mOrig; 
      float[] dst = mVerts; 
      for (int i = 0; i < COUNT * 2; i += 2) { 
       float x = src[i + 0]; 
       float y = src[i + 1]; 
       float dx = cx - x; 
       float dy = cy - y; 
       float dd = dx * dx + dy * dy; 
       float d = FloatMath.sqrt(dd); 
       float pull = K/(dd + 0.000001f); 

       pull /= (d + 0.000001f); 
       // android.util.Log.d("skia", "index " + i + " dist=" + d + 
       // " pull=" + pull); 

       if (pull >= 1) { 
        dst[i + 0] = cx; 
        dst[i + 1] = cy; 
       } else { 
        dst[i + 0] = x + dx * pull; 
        dst[i + 1] = y + dy * pull; 
       } 
      } 

     } 

     private int mLastWarpX = -9999; // don't match a touch coordinate 
     private int mLastWarpY; 

     @Override 
     public boolean onTouchEvent(MotionEvent event) { 
      float[] pt = { event.getX(), event.getY() }; 
      mInverse.mapPoints(pt); 

      int x = (int) pt[0]; 
      int y = (int) pt[1]; 
      if (mLastWarpX != x || mLastWarpY != y) { 
       mLastWarpX = x; 
       mLastWarpY = y; 
       warp(pt[0], pt[1]); 
       invalidate(); 
      } 
      return true; 
     } 
    } 
} 

Graphics Aktivität:

import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.view.ViewGroup; 

class GraphicsActivity extends Activity { 
    // set to true to test Picture 
    private static final boolean TEST_PICTURE = false; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
    } 

    @Override 
    public void setContentView(View view) { 
     if (TEST_PICTURE) { 
      ViewGroup vg = new PictureLayout(this); 
      vg.addView(view); 
      view = vg; 
     } 

     super.setContentView(view); 
    } 
} 

PictureLayout.java

import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Picture; 
import android.graphics.Rect; 
import android.graphics.drawable.Drawable; 
import android.util.AttributeSet; 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.ViewParent; 

class PictureLayout extends ViewGroup { 
    private final Picture mPicture = new Picture(); 

    public PictureLayout(Context context) { 
     super(context); 
    } 

    public PictureLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    @Override 
    public void addView(View child) { 
     if (getChildCount() > 1) { 
      throw new IllegalStateException(
        "PictureLayout can host only one direct child"); 
     } 

     super.addView(child); 
    } 

    @Override 
    public void addView(View child, int index) { 
     if (getChildCount() > 1) { 
      throw new IllegalStateException(
        "PictureLayout can host only one direct child"); 
     } 

     super.addView(child, index); 
    } 

    @Override 
    public void addView(View child, LayoutParams params) { 
     if (getChildCount() > 1) { 
      throw new IllegalStateException(
        "PictureLayout can host only one direct child"); 
     } 

     super.addView(child, params); 
    } 

    @Override 
    public void addView(View child, int index, LayoutParams params) { 
     if (getChildCount() > 1) { 
      throw new IllegalStateException(
        "PictureLayout can host only one direct child"); 
     } 

     super.addView(child, index, params); 
    } 

    @Override 
    protected LayoutParams generateDefaultLayoutParams() { 
     return new LayoutParams(LayoutParams.MATCH_PARENT, 
       LayoutParams.MATCH_PARENT); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     final int count = getChildCount(); 

     int maxHeight = 0; 
     int maxWidth = 0; 

     for (int i = 0; i < count; i++) { 
      final View child = getChildAt(i); 
      if (child.getVisibility() != GONE) { 
       measureChild(child, widthMeasureSpec, heightMeasureSpec); 
      } 
     } 

     maxWidth += getPaddingLeft() + getPaddingRight(); 
     maxHeight += getPaddingTop() + getPaddingBottom(); 

     Drawable drawable = getBackground(); 
     if (drawable != null) { 
      maxHeight = Math.max(maxHeight, drawable.getMinimumHeight()); 
      maxWidth = Math.max(maxWidth, drawable.getMinimumWidth()); 
     } 

     setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec), 
       resolveSize(maxHeight, heightMeasureSpec)); 
    } 

    private void drawPict(Canvas canvas, int x, int y, int w, int h, float sx, 
      float sy) { 
     canvas.save(); 
     canvas.translate(x, y); 
     canvas.clipRect(0, 0, w, h); 
     canvas.scale(0.5f, 0.5f); 
     canvas.scale(sx, sy, w, h); 
     canvas.drawPicture(mPicture); 
     canvas.restore(); 
    } 

    @Override 
    protected void dispatchDraw(Canvas canvas) { 
     super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight())); 
     mPicture.endRecording(); 

     int x = getWidth()/2; 
     int y = getHeight()/2; 

     if (false) { 
      canvas.drawPicture(mPicture); 
     } else { 
      drawPict(canvas, 0, 0, x, y, 1, 1); 
      drawPict(canvas, x, 0, x, y, -1, 1); 
      drawPict(canvas, 0, y, x, y, 1, -1); 
      drawPict(canvas, x, y, x, y, -1, -1); 
     } 
    } 

    @Override 
    public ViewParent invalidateChildInParent(int[] location, Rect dirty) { 
     location[0] = getLeft(); 
     location[1] = getTop(); 
     dirty.set(0, 0, getWidth(), getHeight()); 
     return getParent(); 
    } 

    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) { 
     final int count = super.getChildCount(); 

     for (int i = 0; i < count; i++) { 
      final View child = getChildAt(i); 
      if (child.getVisibility() != GONE) { 
       final int childLeft = getPaddingLeft(); 
       final int childTop = getPaddingTop(); 
       child.layout(childLeft, childTop, 
         childLeft + child.getMeasuredWidth(), 
         childTop + child.getMeasuredHeight()); 

      } 
     } 
    } 
} 
+0

Haben Sie die Lösung gefunden? –

+0

nein ich habe keine Lösung gefunden. Aber wenn Sie diesen Effekt wollen, dann müssen Sie möglicherweise 'OpenCV' mit Android verwenden. Ich habe nicht viel Ahnung davon, aber du wirst Tutorials dazu bekommen. – zanky

+0

Wenn Sie eine andere Lösung als 'OpenCv' finden, dann lassen Sie es mich bitte wissen, da ich' OpenCV' nicht mit Android integrieren möchte. – zanky

Antwort

8
//Little changes in this piece of code 
    float[] dst; //Global 

public SampleView(Context context) { 
     super(context); 
     setFocusable(true); 

     mBitmap = BitmapFactory.decodeResource(getResources(), 
       R.drawable.image1); 

     float w = mBitmap.getWidth(); 
     float h = mBitmap.getHeight(); 
     // construct our mesh 
     int index = 0; 
     for (int y = 0; y <= HEIGHT; y++) { 
      float fy = h * y/HEIGHT; 
      for (int x = 0; x <= WIDTH; x++) { 
       float fx = w * x/WIDTH; 
       setXY(mVerts, index, fx, fy); 
       setXY(mOrig, index, fx, fy); 
       index += 1; 

       dst=mVerts;//Assign dst here just once 

      } 
     } 

     mMatrix.setTranslate(10, 10); 
     mMatrix.invert(mInverse); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     canvas.drawColor(0xFFCCCCCC); 

     canvas.concat(mMatrix); 
     canvas.drawBitmapMesh(mBitmap, WIDTH, HEIGHT, mVerts, 0, null, 0, 
       null); 
    } 

    private void warp(float cx, float cy) { 
     final float K = 10000; 
     float[] src = dst; //now you are applying wrap effect on the last effected pixels 

     for (int i = 0; i < COUNT * 2; i += 2) { 
      float x = src[i + 0]; 
      float y = src[i + 1]; 
      float dx = cx - x; 
      float dy = cy - y; 
      float dd = dx * dx + dy * dy; 
      float d = FloatMath.sqrt(dd); 
      float pull = K/(dd + 0.000001f); 

      pull /= (d + 0.000001f); 
      // android.util.Log.d("skia", "index " + i + " dist=" + d + 
      // " pull=" + pull); 

      if (pull >= 1) { 
       dst[i + 0] = cx; 
       dst[i + 1] = cy; 
      } else { 
       dst[i + 0] = x + dx * pull; 
       dst[i + 1] = y + dy * pull; 
      } 
     } 

    }