2013-09-26 4 views
6

내 안드로이드 응용 프로그램에서 warp 효과를 Photo WarpPhoto Deformer 응용 프로그램에서 제공하는 효과를 적용하고 싶습니다. 그 때문에 나는 BitmapMesh을 사용했습니다. 문제는 뒤틀린 이미지를 저장하지 않는다는 것입니다. 이미지를 터치 할 때마다 이미지가 새로 고침되고 이전에 왜곡 된 이미지는 저장되지 않습니다. 사용자가 워프 작업을 수행 할 때마다 이미지를 저장하고 싶습니다. 여기에 내 코드를 게시하고 있습니다. 여기에 "BitmapMesh"활동을 사용하여 이미지에 워프 효과를 적용합니다.Android - 이미지 왜곡 효과

이 문제를 해결하는 데 도움을주십시오. 감사합니다. .

코드 :

BitmapMesh 활동 :

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

그래픽 작업 :

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

해결책을 찾았습니까? –

+0

아니요 나는 어떤 해결책도 찾지 못했습니다. 그러나이 효과를 원한다면 안드로이드와 함께 OpenCV를 사용해야 할 것입니다. 나는 그것에 대해별로 생각하지 않지만 그것에 관한 튜토리얼을 얻을 것이다. – zanky

+0

만약'OpenCv'가 아닌 다른 해결책을 찾으면,'OpenCV'를 안드로이드와 통합하고 싶지 않기 때문에 알려주세요. – zanky

답변

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

    }