Android: how to warp images?-ThrowExceptions

Exception or error:

I want to warp images like this:

Example image

Added 08-04-2013: I used this code but it’s not working properly:

    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.ic_launcher);

        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;
    }
How to solve:

There is a much easier way than coding you own. See TransitionDrawable

An extension of LayerDrawables that is intended to cross-fade between
the first and second layer. To start the transition, call
startTransition(int). To display just the first layer, call
resetTransition().
It can be defined in an XML file with the
<transition> element. Each Drawable in the transition is defined in a
nested <item>

You can find many examples on line, here is one:

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@drawable/first_image" />
  <item android:drawable="@drawable/second_image" />
</transition>

and the code

final ImageView image = (ImageView) findViewById(R.id.image);
final ToggleButton button = (ToggleButton) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(final View v) {
    TransitionDrawable drawable = (TransitionDrawable) image.getDrawable();
    if (button.isChecked()) {
      drawable.startTransition(500);
    } else {
      drawable.reverseTransition(500);
    }
  }
}); 

###

This could be achieved by OpenCV so give a try to this

Leave a Reply

Your email address will not be published. Required fields are marked *