Putting some indicator around the image in image move/resize/rotate operations
Asked Answered
F

8

28

I would like to Scale, Move, Resize Image. I would like to surround the image with Indicators which guide user what operation these indicators perform i.e. Moving, Rotating, Scaling.

enter image description here

I've tried

  • Scaling - but it only crops down. No chance to increase length and height of image.
  • Rotate - achieved but via inserting manual degrees. That's not a good option in here.
  • Moving - as I'm achieving drag on Api < 11. So little bit of difficult. Still no hope in here.

Is there any library which can do me simple image edit [Move, Scale, Rotate]?

Forspent answered 10/2, 2013 at 16:46 Comment(1)
@Pragnani Nah not yet. Increasing the size of image is bugging me as we can't add more size than actual image size insite matrix.postScale()Forspent
F
4

Using Library : StickerView

Its a 3rd Party Library which gives exactly what i was looking for.

WorkAround :

Still these answer is half of what I've asked for in OP. Means It ain't surronded by some specific Indicator. I'm still searching how to wrap ImageView with indicators and use them for Translate & Resize.

Initilization of Variables inside Activity important for Translate & Resize ImageView

public static final int DRAG = 1;
public static final int NONE = 0;
private static final String TAG = "Touch";
public static final int ZOOM = 2;
public static PointF mid = new PointF();
public static int mode = 0;
float d = 0.0F;
Matrix savedMatrix = new Matrix();
Matrix matrix = new Matrix();
PointF start = new PointF();

Setting ImageView to scaleType - Matrix

iv = new ImageView(this);
iv.setPadding(10, 10, 25, 25);
iv.setScaleType(ImageView.ScaleType.MATRIX);

iv.setOnTouchListener(t);

Adding onTouch Listener to ImageView which uses

  • 1 Finger for Translate - Drag
  • 2 Finger for Zoom - Resize {Pinch To Zoom}

    View.OnTouchListener t = new View.OnTouchListener()
    {
    public boolean onTouch(View paramView, MotionEvent event)
    {
      ImageView view = (ImageView)paramView;
      switch (event.getAction() & MotionEvent.ACTION_MASK)
      {
      case MotionEvent.ACTION_DOWN:
    
          savedMatrix.set(matrix);
          start.set(event.getX(), event.getY());
          Log.d(TAG, "mode=DRAG" );
          mode = DRAG;
          break;
      case MotionEvent.ACTION_POINTER_DOWN:
    
          oldDist = spacing(event);
          Log.d(TAG, "oldDist=" + oldDist);
          if (oldDist > 10f) {
    
              savedMatrix.set(matrix);
              midPoint(mid, event);
              mode = ZOOM;
              Log.d(TAG, "mode=ZOOM" );
          }
          break;
    
      case MotionEvent.ACTION_MOVE:
    
          if (mode == DRAG) {
    
              matrix.set(savedMatrix);
              matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);
          }
          else if (mode == ZOOM) {
    
              float newDist = spacing(event);
              Log.d(TAG, "newDist=" + newDist);
              if (newDist > 10f) {
    
                  matrix.set(savedMatrix);
                  float scale = newDist / oldDist;
                  matrix.postScale(scale, scale, mid.x, mid.y);
              }
          }
          break;
    
      case MotionEvent.ACTION_UP:
      case MotionEvent.ACTION_POINTER_UP:
    
          mode = NONE;
          Log.d(TAG, "mode=NONE" );
          break;
      }  
      view.setImageMatrix(matrix);
      return true;
    
    }
    
     private void midPoint(PointF point, MotionEvent event) {
    
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }
    
          private float spacing(MotionEvent event) {
          float x = event.getX(0) - event.getX(1);
          float y = event.getY(0) - event.getY(1);
          return FloatMath.sqrt(x * x + y * y);
          }
         };
    
Forspent answered 19/2, 2013 at 14:41 Comment(0)
R
6

You can use Matrix transaformation to achieve rotating, scaling, and moving....I hope this will help you....

for rotating

Matrix matrix = new Matrix();
    matrix.postRotate(90);

for scaling

 matrix.postScale(scaleWidth, scaleHeight);

create new bitmap without changing the original one...like this

Bitmap bmp2 = Bitmap.createBitmap(bmp1, 0, 0, pow2, pow2, matrix, true);
Ressieressler answered 10/2, 2013 at 16:57 Comment(3)
Yeah Surely I can use Matrix Transformation. I've tried on rotation by adding matrix. But what i need is input to matrix from the indicator. Any help of fetching input from indicator to Matrix would be most welcomes.Forspent
@VikalpPatel you will get x and y co ordinates of the image when you set onTouchListener to it...based on the movement you can scale, rotate and moveRessieressler
yeah but in matrix.postScale() we can't add size more than image actual size. That'z the problem which bugs me out.Forspent
B
4

Just check out this image cropping reference :

http://www.londatiga.net/featured-articles/how-to-select-and-crop-image-on-android/

For image rotation, just refer to this example; this sample code represents the rotation of image dynamically:

http://android-er.blogspot.in/2010/07/rotate-bitmap-image-using-matrix.html

This link is also useful for image crop, rotate and scale:

https://github.com/Yalantis/uCrop

Burch answered 19/2, 2013 at 9:18 Comment(1)
The first link uses a crop intent that is specific to AOSP camera app, which is not present in all devices, so using that method will crash. Use some library like github.com/lvillani/android-cropimage, which covers it all.Anility
F
4

Using Library : StickerView

Its a 3rd Party Library which gives exactly what i was looking for.

WorkAround :

Still these answer is half of what I've asked for in OP. Means It ain't surronded by some specific Indicator. I'm still searching how to wrap ImageView with indicators and use them for Translate & Resize.

Initilization of Variables inside Activity important for Translate & Resize ImageView

public static final int DRAG = 1;
public static final int NONE = 0;
private static final String TAG = "Touch";
public static final int ZOOM = 2;
public static PointF mid = new PointF();
public static int mode = 0;
float d = 0.0F;
Matrix savedMatrix = new Matrix();
Matrix matrix = new Matrix();
PointF start = new PointF();

Setting ImageView to scaleType - Matrix

iv = new ImageView(this);
iv.setPadding(10, 10, 25, 25);
iv.setScaleType(ImageView.ScaleType.MATRIX);

iv.setOnTouchListener(t);

Adding onTouch Listener to ImageView which uses

  • 1 Finger for Translate - Drag
  • 2 Finger for Zoom - Resize {Pinch To Zoom}

    View.OnTouchListener t = new View.OnTouchListener()
    {
    public boolean onTouch(View paramView, MotionEvent event)
    {
      ImageView view = (ImageView)paramView;
      switch (event.getAction() & MotionEvent.ACTION_MASK)
      {
      case MotionEvent.ACTION_DOWN:
    
          savedMatrix.set(matrix);
          start.set(event.getX(), event.getY());
          Log.d(TAG, "mode=DRAG" );
          mode = DRAG;
          break;
      case MotionEvent.ACTION_POINTER_DOWN:
    
          oldDist = spacing(event);
          Log.d(TAG, "oldDist=" + oldDist);
          if (oldDist > 10f) {
    
              savedMatrix.set(matrix);
              midPoint(mid, event);
              mode = ZOOM;
              Log.d(TAG, "mode=ZOOM" );
          }
          break;
    
      case MotionEvent.ACTION_MOVE:
    
          if (mode == DRAG) {
    
              matrix.set(savedMatrix);
              matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);
          }
          else if (mode == ZOOM) {
    
              float newDist = spacing(event);
              Log.d(TAG, "newDist=" + newDist);
              if (newDist > 10f) {
    
                  matrix.set(savedMatrix);
                  float scale = newDist / oldDist;
                  matrix.postScale(scale, scale, mid.x, mid.y);
              }
          }
          break;
    
      case MotionEvent.ACTION_UP:
      case MotionEvent.ACTION_POINTER_UP:
    
          mode = NONE;
          Log.d(TAG, "mode=NONE" );
          break;
      }  
      view.setImageMatrix(matrix);
      return true;
    
    }
    
     private void midPoint(PointF point, MotionEvent event) {
    
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }
    
          private float spacing(MotionEvent event) {
          float x = event.getX(0) - event.getX(1);
          float y = event.getY(0) - event.getY(1);
          return FloatMath.sqrt(x * x + y * y);
          }
         };
    
Forspent answered 19/2, 2013 at 14:41 Comment(0)
T
3

I recently tried the same thing but ended up using a library since it covered a lot more edge cases. This is a great, and pretty widely used library:

http://code.google.com/p/android-multitouch-controller/

Terraqueous answered 19/2, 2013 at 1:0 Comment(0)
N
2

I think I can help you with the rotation part. I recently made an android wheel menu library. It tracks user's hand motion and rotates the imageview accordingly. You can check out the source to see how I did it here:

https://github.com/anupcowkur/Android-Wheel-Menu

Nyssa answered 18/2, 2013 at 8:14 Comment(5)
Thanks brother for your rotation library. I'll check it out ASAP!!Forspent
This library is nice.. But when i create an image view in java file and use this library to rotate the image, i am unable to see the rotation. Can you help me in this one?Apteral
@Apteral If everything is set up according to the instructions provided, then it should work perfectly without any problems.Nyssa
I created an object and associated it with my imageview. But I am unable to rotate it. Can i know where are the instructionsApteral
This is what i tried but i am unable to rotate the image LinearLayout layout = (LinearLayout)findViewById(R.id.mainLayout); ImageView wheel_image = new ImageView(this); wheel_image.setImageResource(R.drawable.wheel); final WheelMenu wm = new WheelMenu(MainActivity.this, 12, R.drawable.wheel, wheel_image, true); layout.addView(wheel_image);Apteral
G
2

I know this is not an answer but it's worth mentioning.

Take a look at this project. I intend to put it on GitHub but it is not done yet (at all).

There is a button to rotate the image. I am still working on the "save". Many of the classes are taken from the Android source thanks to Lorenzo Villani's project

Add to your project's manifest:

    <activity
        android:name="mobi.sherif.camera.CropImage"
        android:hardwareAccelerated="false"
        android:screenOrientation="portrait" >

Call the activity using:

Intent intent = new Intent(mContext, CropImage.class);
intent.setData(uri);
startActivityForResult(intent, S.request.cropimage);

enter image description here

Gentilis answered 20/2, 2013 at 7:57 Comment(4)
thanks for the recommendations. I'll take a look at your github repository.Forspent
@VikalpPatel I posted the ZiP file. It is rotating but am working on Saving the file. I am still working on it slowly.Gentilis
Were you able to achieve 'rotate' and 'crop' on same Activity then?Anility
@Anility I honestly can't remember. Try the project out. Sorry ):Gentilis
O
1

Bitmap rotation

Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight, config);
Canvas canvas = new Canvas(targetBitmap);
Matrix matrix = new Matrix();
matrix.setRotate(mRotation,source.getWidth()/2,source.getHeight()/2);
canvas.drawBitmap(source, matrix, new Paint());

Image Scaling Scaling

AssetManager assetManager = context.getAssets();
InputStream imageIn;
String imgPath = "test.png";
Bitmap image;
try {
    imageIn = assetManager.open(imgPath, AssetManager.ACCESS_BUFFER);
    image = BitmapFactory.decodeStream(imageIn);
} catch (IOException e) {

}
//TODO: calculate width and height to fill or fit screen
image = Bitmap.createScaledBitmap(image, width, height, true);

Image moving Image in Canvas with touch events

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;

public class ImgView extends View {

private static final int INVALID_POINTER_ID = -1;

    private Drawable mImage;
    private float mPosX;
    private float mPosY;

    private float mLastTouchX;
    private float mLastTouchY;
    private int mActivePointerId = INVALID_POINTER_ID;

    private ScaleGestureDetector mScaleDetector;
    private float mScaleFactor = 1.f;

    public ImgView(Context context) {
        this(context, null, 0);
    mImage = getResources().getDrawable(R.drawable.imagename);

        mImage.setBounds(0, 0, mImage.getIntrinsicWidth(), mImage.getIntrinsicHeight());
    }

    public ImgView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ImgView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        // Let the ScaleGestureDetector inspect all events.
        mScaleDetector.onTouchEvent(ev);

        final int action = ev.getAction();
        switch (action & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN: {
            final float x = ev.getX();
            final float y = ev.getY();

            mLastTouchX = x;
            mLastTouchY = y;
            mActivePointerId = ev.getPointerId(0);
            break;
        }

        case MotionEvent.ACTION_MOVE: {
            final int pointerIndex = ev.findPointerIndex(mActivePointerId);
            final float x = ev.getX(pointerIndex);
            final float y = ev.getY(pointerIndex);

            // Only move if the ScaleGestureDetector isn't processing a gesture.
            if (!mScaleDetector.isInProgress()) {
                final float dx = x - mLastTouchX;
                final float dy = y - mLastTouchY;

                mPosX += dx;
                mPosY += dy;

                invalidate();
            }

            mLastTouchX = x;
            mLastTouchY = y;

            break;
        }

        case MotionEvent.ACTION_UP: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_CANCEL: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_POINTER_UP: {
            final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) 
                    >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
            final int pointerId = ev.getPointerId(pointerIndex);
            if (pointerId == mActivePointerId) {
                // This was our active pointer going up. Choose a new
                // active pointer and adjust accordingly.
                final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                mLastTouchX = ev.getX(newPointerIndex);
                mLastTouchY = ev.getY(newPointerIndex);
                mActivePointerId = ev.getPointerId(newPointerIndex);
            }
            break;
        }
        }

        return true;
    }

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

        canvas.save();
        Log.d("DEBUG", "X: "+mPosX+" Y: "+mPosY);
        canvas.translate(mPosX, mPosY);
        canvas.scale(mScaleFactor, mScaleFactor);
        mImage.draw(canvas);
        canvas.restore();
    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            mScaleFactor *= detector.getScaleFactor();

            // Don't let the object get too small or too large.
            mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f));

            invalidate();
            return true;
        }
    }

}
Osbourn answered 19/2, 2013 at 8:30 Comment(0)
D
1

You can https://github.com/siddhpuraamitr/MultitouchWithDynamicAddandRemove try this code in your project

Despot answered 8/7, 2015 at 11:0 Comment(1)
This is a great repository! If only it had a better documentation.Winslow

© 2022 - 2024 — McMap. All rights reserved.