Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to crop image in android

I am creating application in android. In this application there is one part of cropping image. When I googled it, I got some ideas based on cropping of image but I have some problem over there as I have a man image. Here I need to crop exactly the face of the man but my code only works for rectangle and overwrite image in a sdcard. I am confused with that code.. can anyone please help me...

Edited:

 super.onCreate(icicle);
mContentResolver = getContentResolver();

requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.cropimage);

mImageView = (CropImageView) findViewById(R.id.image);

showStorageToast(this);

Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
    if (extras.getString("circleCrop") != null) {
    mCircleCrop = true;
    mAspectX = 1;
    mAspectY = 1;
    }

    mImagePath = extras.getString("image-path");

    mSaveUri = getImageUri(mImagePath);
    mBitmap = getBitmap(mImagePath);

    mAspectX = extras.getInt("aspectX");
    mAspectY = extras.getInt("aspectY");
    mOutputX = extras.getInt("outputX");
    mOutputY = extras.getInt("outputY");
    mScale = extras.getBoolean("scale", true);
    mScaleUp = extras.getBoolean("scaleUpIfNeeded", true);
}



if (mBitmap == null) {
    Log.d(TAG, "finish!!!");
    finish();
    return;
}

// Make UI fullscreen.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

findViewById(R.id.discard).setOnClickListener(
    new View.OnClickListener() {
        public void onClick(View v) {
        setResult(RESULT_CANCELED);
        finish();
        }
    });

findViewById(R.id.save).setOnClickListener(
    new View.OnClickListener() {
        public void onClick(View v) {
        onSaveClicked();
        }
    });
startFaceDetection();
}

private Uri getImageUri(String path) {
return Uri.fromFile(new File(path));
}

private Bitmap getBitmap(String path) {
Uri uri = getImageUri(path);
InputStream in = null;
try {
    in = mContentResolver.openInputStream(uri);
    return BitmapFactory.decodeStream(in);
} catch (FileNotFoundException e) {
    Log.e(TAG, "file " + path + " not found");
}
return null;
}


private void startFaceDetection() {
if (isFinishing()) {
    Toast.makeText(this, "Inside Face Detection",Toast.LENGTH_LONG).show();
    return;
}
Toast.makeText(this, "Outside Face Detection",Toast.LENGTH_LONG).show();
mImageView.setImageBitmapResetBase(mBitmap, true);


Util.startBackgroundJob(this, null,
    "Please wait\u2026",
    new Runnable() {
    public void run() {

    final CountDownLatch latch = new CountDownLatch(1);
    final Bitmap b = (mImage != null)
    ? mImage.fullSizeBitmap(IImage.UNCONSTRAINED,
        1024 * 1024)
        : mBitmap;
    mHandler.post(new Runnable() {
        public void run() {
        if (b != mBitmap && b != null) {
            mImageView.setImageBitmapResetBase(b, true);
          //  mBitmap.recycle();
            mBitmap = b;
        }
        if (mImageView.getScale() == 1F) {
            mImageView.center(true, true);
        }
        latch.countDown();
        }
    });
    try {
        latch.await();
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    mRunFaceDetection.run();
    }
}, mHandler);
}



private void onSaveClicked() {
// TODO this code needs to change to use the decode/crop/encode single
// step api so that we don't require that the whole (possibly large)
// bitmap doesn't have to be read into memory
if (mSaving) return;

if (mCrop == null) {
    return;
}

mSaving = true;

Rect r = mCrop.getCropRect();

int width = (int) r.width();
int height = (int) r.height();

// If we are circle cropping, we want alpha channel, which is the
// third param here.
Bitmap croppedImage = Bitmap.createBitmap(width, height,
    mCircleCrop
    ? Bitmap.Config.ARGB_8888
        : Bitmap.Config.RGB_565);
{
    Canvas canvas = new Canvas(croppedImage);
    RectF dstRect = new RectF(0, 0, width, height);
   // canvas.drawBitmap(mBitmap, r, dstRect, null);
   // canvas.drawOval(dstRect, null);

   canvas.drawBitmap(mBitmap, r, dstRect, null);
}

if (mCircleCrop) {
    // OK, so what's all this about?
    // Bitmaps are inherently rectangular but we want to return
    // something that's basically a circle.  So we fill in the
    // area around the circle with alpha.  Note the all important
    // PortDuff.Mode.CLEAR.
    Canvas c = new Canvas(croppedImage);
    Path p = new Path();
    p.addCircle(width / 2F, height / 2F, width / 2F,
        Path.Direction.CW);
    c.clipPath(p, Region.Op.DIFFERENCE);
    c.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
}

/* If the output is required to a specific size then scale or fill */
if (mOutputX != 0 && mOutputY != 0) {
    if (mScale) {
    /* Scale the image to the required dimensions */
    Bitmap old = croppedImage;
    croppedImage = Util.transform(new Matrix(),
        croppedImage, mOutputX, mOutputY, mScaleUp);
    if (old != croppedImage) {
        old.recycle();
    }
    } else {

    /* Don't scale the image crop it to the size requested.
     * Create an new image with the cropped image in the center and
     * the extra space filled.
     */

    // Don't scale the image but instead fill it so it's the
    // required dimension
    Bitmap b = Bitmap.createBitmap(mOutputX, mOutputY,
        Bitmap.Config.RGB_565);
    Canvas canvas = new Canvas(b);

    Rect srcRect = mCrop.getCropRect();
    RectF dstRect = new RectF(0, 0, mOutputX, mOutputY);

    int dx = (int) ((srcRect.width() - dstRect.width()) / 2);
    int dy = (int) ((srcRect.height() - dstRect.height()) / 2);

    /* If the srcRect is too big, use the center part of it. */
    srcRect.inset(Math.max(0, dx), Math.max(0, dy));

    /* If the dstRect is too big, use the center part of it. */
    dstRect.inset(Math.max(0, -dx), Math.max(0, -dy));

    /* Draw the cropped bitmap in the center */
    //canvas.drawBitmap(mBitmap, srcRect, dstRect, null);
    canvas.drawOval(dstRect, null);

    /* Set the cropped bitmap as the new bitmap */
    croppedImage.recycle();
    //croppedImage = b;
    }
}

// Return the cropped image directly or save it to the specified URI.
Bundle myExtras = getIntent().getExtras();
//if (myExtras != null && (myExtras.getParcelable("data") != null
//    || myExtras.getBoolean("return-data"))) {
    Bundle extras = new Bundle(); 
    extras.putParcelable("data", croppedImage);
   Intent intent=new Intent(CropImage.this,nextImage.class); 
   intent.putExtras(extras);
   startActivity(intent);
    //setResult(RESULT_OK,
      //  (new Intent()).setAction("inline-daintentta").putExtras(extras));
   // finish();
//} 
/*else {
    final Bitmap b = croppedImage;
    Util.startBackgroundJob(this, null,"Saving image",
        new Runnable() {
    public void run() {
        saveOutput(b);
    }
    }, mHandler);
}*/
}

private void saveOutput(Bitmap croppedImage) {
if (mSaveUri != null) {
    OutputStream outputStream = null;
    try {
    outputStream = mContentResolver.openOutputStream(mSaveUri);
    if (outputStream != null) {
        croppedImage.compress(mOutputFormat, 75, outputStream);
    }
    } catch (IOException ex) {
    // TODO: report error to caller
    Log.e(TAG, "Cannot open file: " + mSaveUri, ex);
    } finally {
    Util.closeSilently(outputStream);
    }
    Bundle extras = new Bundle();
    setResult(RESULT_OK, new Intent(mSaveUri.toString())
    .putExtras(extras));
} else {
    Log.e(TAG, "neni definovana adresa pro ulozeni");
    /*Bundle extras = new Bundle();
    extras.putString("rect", mCrop.getCropRect().toString());

    File oldPath = new File(mImage.getDataPath());
    File directory = new File(oldPath.getParent());

    int x = 0;
    String fileName = oldPath.getName();
    fileName = fileName.substring(0, fileName.lastIndexOf("."));

    // Try file-1.jpg, file-2.jpg, ... until we find a filename which
    // does not exist yet.
    while (true) {
    x += 1;
    String candidate = directory.toString()
    + "/" + fileName + "-" + x + ".jpg";
    boolean exists = (new File(candidate)).exists();
    if (!exists) {
        break;
    }
    }

    try {
    Uri newUri = ImageManager.addImage(
        mContentResolver,
        mImage.getTitle(),
        mImage.getDateTaken(),
        null,    // TODO this null is going to cause us to lose
        // the location (gps).
        0,       // TODO this is going to cause the orientation
        // to reset.
        directory.toString(),
        fileName + "-" + x + ".jpg");

     Cancelable<Void> cancelable =
                    ImageManager.storeImage(
                    newUri,
                    mContentResolver,
                    0, // TODO fix this orientation
                    croppedImage,
                    null);

            cancelable.get();
    setResult(RESULT_OK, new Intent()
    .setAction(newUri.toString())
    .putExtras(extras));
    } catch (Exception ex) {
    // basically ignore this or put up
    // some ui saying we failed
    Log.e(TAG, "store image fail, continue anyway", ex);
    }
    */
}
//croppedImage.recycle();
finish();
}

@Override
protected void onPause() {
super.onPause();
BitmapManager.instance().cancelThreadDecoding(mDecodingThreads);
    //mBitmap.recycle();
}

@Override
protected void onDestroy() {
super.onDestroy();
}


Runnable mRunFaceDetection = new Runnable() {
@SuppressWarnings("hiding")
float mScale = 1F;
Matrix mImageMatrix;
FaceDetector.Face[] mFaces = new FaceDetector.Face[3];
int mNumFaces;

// For each face, we create a HightlightView for it.
private void handleFace(FaceDetector.Face f) {
    PointF midPoint = new PointF();

    int r = ((int) (f.eyesDistance() * mScale)) * 2;
    f.getMidPoint(midPoint);
    midPoint.x *= mScale;
    midPoint.y *= mScale;

    int midX = (int) midPoint.x;
    int midY = (int) midPoint.y;

    HighlightView hv = new HighlightView(mImageView);

    int width = mBitmap.getWidth();
    int height = mBitmap.getHeight();

    RectF imageRect = new RectF(0, 0, width, height);

    RectF faceRect = new RectF(midX, midY, midX, midY);
    faceRect.inset(-r, -r);
    if (faceRect.left < 0) {
    faceRect.inset(-faceRect.left, -faceRect.left);
    }

    if (faceRect.top < 0) {
    faceRect.inset(-faceRect.top, -faceRect.top);
    }

    if (faceRect.right > imageRect.right) {
    faceRect.inset(faceRect.right - imageRect.right,
        faceRect.right - imageRect.right);
    }

    if (faceRect.bottom > imageRect.bottom) {
    faceRect.inset(faceRect.bottom - imageRect.bottom,
        faceRect.bottom - imageRect.bottom);
    }

    hv.setup(mImageMatrix, imageRect, faceRect, mCircleCrop,
        mAspectX != 0 && mAspectY != 0);

    mImageView.add(hv);
}

// Create a default HightlightView if we found no face in the picture.
private void makeDefault() {
    HighlightView hv = new HighlightView(mImageView);

    int width = mBitmap.getWidth();
    int height = mBitmap.getHeight();

    RectF imageRect = new RectF(0, 0, width, height);

    // make the default size about 4/5 of the width or height
    int cropWidth = Math.min(width, height) * 4 / 5;
    int cropHeight = cropWidth;

    if (mAspectX != 0 && mAspectY != 0) {
    if (mAspectX > mAspectY) {
        cropHeight = cropWidth * mAspectY / mAspectX;
    } else {
        cropWidth = cropHeight * mAspectX / mAspectY;
    }
    }

    int x = (width - cropWidth) / 2;
    int y = (height - cropHeight) / 2;

    RectF cropRect = new RectF(x, y, x + cropWidth, y + cropHeight);
    hv.setup(mImageMatrix, imageRect, cropRect, mCircleCrop,
        mAspectX != 0 && mAspectY != 0);
    mImageView.add(hv);
}

// Scale the image down for faster face detection.
private Bitmap prepareBitmap() {
    if (mBitmap == null) {
    return null;
    }

    // 256 pixels wide is enough.
    if (mBitmap.getWidth() > 256) {
    mScale = 256.0F / mBitmap.getWidth();
    }
    Matrix matrix = new Matrix();
    matrix.setScale(mScale, mScale);
    Bitmap faceBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap
        .getWidth(), mBitmap.getHeight(), matrix, true);
    return faceBitmap;
}

public void run() {
    mImageMatrix = mImageView.getImageMatrix();
    Bitmap faceBitmap = prepareBitmap();

    mScale = 1.0F / mScale;
    if (faceBitmap != null && mDoFaceDetection) {
    FaceDetector detector = new FaceDetector(faceBitmap.getWidth(),
        faceBitmap.getHeight(), mFaces.length);
    mNumFaces = detector.findFaces(faceBitmap, mFaces);
    }

    if (faceBitmap != null && faceBitmap != mBitmap) {
//    faceBitmap.recycle();
    }

    mHandler.post(new Runnable() {
    public void run() {
        mWaitingToPick = mNumFaces > 1;
        if (mNumFaces > 0) {
        for (int i = 0; i < mNumFaces; i++) {
            handleFace(mFaces[i]);
        }
        } else {
        makeDefault();
        }
        mImageView.invalidate();
        if (mImageView.mHighlightViews.size() == 1) {
        mCrop = mImageView.mHighlightViews.get(0);
        mCrop.setFocus(true);
        }

        if (mNumFaces > 1) {
        Toast t = Toast.makeText(CropImage.this,
            "Multi face crop help",
            Toast.LENGTH_SHORT);
        t.show();
        }
    }
    });
}
};

public static final int NO_STORAGE_ERROR = -1;
public static final int CANNOT_STAT_ERROR = -2;

public static void showStorageToast(Activity activity) {
showStorageToast(activity, calculatePicturesRemaining());
}

public static void showStorageToast(Activity activity, int remaining) {
String noStorageText = null;

if (remaining == NO_STORAGE_ERROR) {
    String state = Environment.getExternalStorageState();
    if (state == Environment.MEDIA_CHECKING) {
    noStorageText = "Preparing card";
    } else {
    noStorageText = "No storage card";
    }
} else if (remaining < 1) {
    noStorageText = "Not enough space";
}

if (noStorageText != null) {
    Toast.makeText(activity, noStorageText, 5000).show();
}
}

public static int calculatePicturesRemaining() {
try {
    /*if (!ImageManager.hasStorage()) {
            return NO_STORAGE_ERROR;
        } else {*/
    String storageDirectory =
    Environment.getExternalStorageDirectory().toString();
    StatFs stat = new StatFs(storageDirectory);
    float remaining = ((float) stat.getAvailableBlocks()
        * (float) stat.getBlockSize()) / 400000F;
    return (int) remaining;
    //}
} catch (Exception ex) {
    // if we can't stat the filesystem then we don't know how many
    // pictures are remaining.  it might be zero but just leave it
    // blank since we really don't know.
    return CANNOT_STAT_ERROR;
}
}



 }


class CropImageView extends ImageViewTouchBase {
ArrayList<HighlightView> mHighlightViews = new ArrayList<HighlightView>();
HighlightView mMotionHighlightView = null;
float mLastX, mLastY;
int mMotionEdge;

private Context mContext;

@Override
protected void onLayout(boolean changed, int left, int top,
    int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mBitmapDisplayed.getBitmap() != null) {
    for (HighlightView hv : mHighlightViews) {
    hv.mMatrix.set(getImageMatrix());
    hv.invalidate();
    if (hv.mIsFocused) {
        centerBasedOnHighlightView(hv);
    }
    }
}
}

public CropImageView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
}

@Override
protected void zoomTo(float scale, float centerX, float centerY) {
super.zoomTo(scale, centerX, centerY);
for (HighlightView hv : mHighlightViews) {
    hv.mMatrix.set(getImageMatrix());
    hv.invalidate();
}
}

@Override
protected void zoomIn() {
super.zoomIn();
for (HighlightView hv : mHighlightViews) {
    hv.mMatrix.set(getImageMatrix());
    hv.invalidate();
}
}

@Override
protected void zoomOut() {
super.zoomOut();
for (HighlightView hv : mHighlightViews) {
    hv.mMatrix.set(getImageMatrix());
    hv.invalidate();
}
}

@Override
protected void postTranslate(float deltaX, float deltaY) {
super.postTranslate(deltaX, deltaY);
for (int i = 0; i < mHighlightViews.size(); i++) {
    HighlightView hv = mHighlightViews.get(i);
    hv.mMatrix.postTranslate(deltaX, deltaY);
    hv.invalidate();
}
}

// According to the event's position, change the focus to the first
// hitting cropping rectangle.
private void recomputeFocus(MotionEvent event) {
for (int i = 0; i < mHighlightViews.size(); i++) {
    HighlightView hv = mHighlightViews.get(i);
    hv.setFocus(false);
    hv.invalidate();
}

for (int i = 0; i < mHighlightViews.size(); i++) {
    HighlightView hv = mHighlightViews.get(i);
    int edge = hv.getHit(event.getX(), event.getY());
    if (edge != HighlightView.GROW_NONE) {
    if (!hv.hasFocus()) {
        hv.setFocus(true);
        hv.invalidate();
    }
    break;
    }
}
invalidate();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
CropImage cropImage = (CropImage) mContext;
if (cropImage.mSaving) {
    return false;
}

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
    if (cropImage.mWaitingToPick) {
    recomputeFocus(event);
    } else {
    for (int i = 0; i < mHighlightViews.size(); i++) {
        HighlightView hv = mHighlightViews.get(i);
        int edge = hv.getHit(event.getX(), event.getY());
        if (edge != HighlightView.GROW_NONE) {
        mMotionEdge = edge;
        mMotionHighlightView = hv;
        mLastX = event.getX();
        mLastY = event.getY();
        mMotionHighlightView.setMode(
            (edge == HighlightView.MOVE)
            ? HighlightView.ModifyMode.Move
                : HighlightView.ModifyMode.Grow);
        break;
        }
    }
    }
    break;
case MotionEvent.ACTION_UP:
    if (cropImage.mWaitingToPick) {
    for (int i = 0; i < mHighlightViews.size(); i++) {
        HighlightView hv = mHighlightViews.get(i);
        if (hv.hasFocus()) {
        cropImage.mCrop = hv;
        for (int j = 0; j < mHighlightViews.size(); j++) {
            if (j == i) {
            continue;
            }
            mHighlightViews.get(j).setHidden(true);
        }
        centerBasedOnHighlightView(hv);
        ((CropImage) mContext).mWaitingToPick = false;
        return true;
        }
    }
    } else if (mMotionHighlightView != null) {
    centerBasedOnHighlightView(mMotionHighlightView);
    mMotionHighlightView.setMode(
        HighlightView.ModifyMode.None);
    }
    mMotionHighlightView = null;
    break;
case MotionEvent.ACTION_MOVE:
    if (cropImage.mWaitingToPick) {
    recomputeFocus(event);
    } else if (mMotionHighlightView != null) {
    mMotionHighlightView.handleMotion(mMotionEdge,
        event.getX() - mLastX,
        event.getY() - mLastY);
    mLastX = event.getX();
    mLastY = event.getY();

    if (true) {
        // This section of code is optional. It has some user
        // benefit in that moving the crop rectangle against
        // the edge of the screen causes scrolling but it means
        // that the crop rectangle is no longer fixed under
        // the user's finger.
        ensureVisible(mMotionHighlightView);
    }
    }
    break;
}

switch (event.getAction()) {
case MotionEvent.ACTION_UP:
    center(true, true);
    break;
case MotionEvent.ACTION_MOVE:
    // if we're not zoomed then there's no point in even allowing
    // the user to move the image around.  This call to center puts
    // it back to the normalized location (with false meaning don't
    // animate).
    if (getScale() == 1F) {
    center(true, true);
    }
    break;
}

return true;
}

// Pan the displayed image to make sure the cropping rectangle is visible.
private void ensureVisible(HighlightView hv) {
RectF r = hv.mDrawRect;

int panDeltaX1 = (int) Math.max(0, mLeft - r.left);
int panDeltaX2 = (int) Math.min(0, mRight - r.right);

int panDeltaY1 = (int) Math.max(0, mTop - r.top);
int panDeltaY2 = (int) Math.min(0, mBottom - r.bottom);

int panDeltaX = panDeltaX1 != 0 ? panDeltaX1 : panDeltaX2;
int panDeltaY = panDeltaY1 != 0 ? panDeltaY1 : panDeltaY2;

if (panDeltaX != 0 || panDeltaY != 0) {
    panBy(panDeltaX, panDeltaY);
}
}

// If the cropping rectangle's size changed significantly, change the
// view's center and scale according to the cropping rectangle.
private void centerBasedOnHighlightView(HighlightView hv) {
RectF drawRect = hv.mDrawRect;

float width = drawRect.width();
float height = drawRect.height();

float thisWidth = getWidth();
float thisHeight = getHeight();

float z1 = thisWidth / width * .6F;
float z2 = thisHeight / height * .6F;

float zoom = Math.min(z1, z2);
zoom = zoom * this.getScale();
zoom = Math.max(1F, zoom);
if ((Math.abs(zoom - getScale()) / zoom) > .1) {
    float [] coordinates = new float[] {hv.mCropRect.centerX(),
        hv.mCropRect.centerY()};
    getImageMatrix().mapPoints(coordinates);
    zoomTo(zoom, coordinates[0], coordinates[1], 300F);
}

ensureVisible(hv);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < mHighlightViews.size(); i++) {
    mHighlightViews.get(i).draw(canvas);
}
}

public void add(HighlightView hv) {
mHighlightViews.add(hv);
invalidate();
}

Thanks in advance

like image 534
deepa Avatar asked Jun 24 '11 06:06

deepa


1 Answers

i hope this code will help u..

Uri ImageCaptureUri = Uri.fromFile(new File("filepath"); 
Intent intent = new Intent("com.android.camera.action.CROP"); 
intent.setType("image/*"); 
intent.setData(ImageCaptureUri); 
intent.putExtra("outputX", 200); 
intent.putExtra("outputY", 200); 
intent.putExtra("aspectX", 1); 
intent.putExtra("aspectY", 1); 
intent.putExtra("scale", true); 
intent.putExtra("return-data", true); 
intent.setComponent( new ComponentName(com.android.gallery , com.android.camera.CropImage)); 
startActivityForResult(intent, 1);
like image 148
Crishnan Kandada Avatar answered Oct 13 '22 20:10

Crishnan Kandada