Android图片的剪裁处理

jopen 9年前

    /*        * Copyright (C) 2015 www.amengsoft.org        *         * Licensed under the Apache License, Version 2.0 (the "License");        * you may not use this file except in compliance with the License.        * You may obtain a copy of the License at        *        *     http://www.apache.org/licenses/LICENSE-2.0        *        * Unless required by applicable law or agreed to in writing, software        * distributed under the License is distributed on an "AS IS" BASIS,        * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.        * See the License for the specific language governing permissions and        * limitations under the License.        */        package com.baojia.view;                import java.io.File;        import java.io.FileOutputStream;        import java.util.concurrent.CountDownLatch;                import android.app.Activity;        import android.content.Context;        import android.graphics.Bitmap;        import android.graphics.Bitmap.CompressFormat;        import android.graphics.Canvas;        import android.graphics.Matrix;        import android.graphics.PointF;        import android.graphics.Rect;        import android.graphics.RectF;        import android.media.FaceDetector;        import android.os.Handler;                import com.ab.global.AbConstant;        import com.ab.util.AbFileUtil;        import com.ab.view.cropimage.HighlightView;                /**        * 裁剪处理.        * @author LuKe        */        public class CropImage{                        /** The file local. */            public File FILE_LOCAL = null;            // Whether we are wait the user to pick a face.            /** The m waiting to pick. */            public boolean mWaitingToPick;             // Whether the "save" button is already clicked.            /** The m saving. */            public boolean mSaving;                         /** The m crop. */            public HighlightView mCrop;                        /** The m context. */            private Context mContext;                        /** The m handler. */            private Handler mHandler;                        /** The m image view. */            private CropImageView mImageView;                        /** The m bitmap. */            private Bitmap mBitmap;            /**            * 裁切框宽和宽比            * **/            private float widthByHeight=1;                        private int cropImgWidth=300,cropImgHeight=200;                    /**            * Instantiates a new crop image.            *            * @param context the context            * @param imageView the image view            * @param handler the handler            */            public CropImage(Context context, CropImageView imageView,Handler handler,int cropImgWidth,int cropImgHeight){                mContext = context;                mImageView = imageView;                mImageView.setCropImage(this);                mHandler = handler;                this.cropImgWidth=cropImgWidth;                this.cropImgHeight=cropImgHeight;                widthByHeight=cropImgHeight/cropImgWidth;                //初始化图片保存路径                FILE_LOCAL = new File(AbFileUtil.getImageDownFullDir());                if(!FILE_LOCAL.exists()){                    FILE_LOCAL.mkdirs();                }            }                        /**            * 图片裁剪.            *            * @param bm the bm            */            public void crop(Bitmap bm){                mBitmap = bm;                startFaceDetection();            }                        /**            * Start rotate.            *            * @param d the d            */            public void startRotate(float d) {                if (((Activity)mContext).isFinishing()) {                    return;                }                final float degrees = d;                final CountDownLatch latch = new CountDownLatch(1);                Runnable mRunnable =  new Runnable() {                    public void run() {                        mHandler.post(new Runnable() {                            public void run() {                                try{                                    Matrix m = new Matrix();                                    m.setRotate(degrees);                                    Bitmap tb = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(),m,false);                                    mBitmap = tb;                                    mImageView.resetView(tb,cropImgWidth,cropImgHeight);                                    if (mImageView.mHighlightViews.size() > 0) {                                        mCrop = mImageView.mHighlightViews.get(0);                                        mCrop.setFocus(true);                                    }                                }catch (Exception e) {                                }                                latch.countDown();                            }                        });                        try {                            latch.await();                        } catch (Exception e) {                            throw new RuntimeException(e);                        }                        //mRunFaceDetection.run();                    }                };                new Thread(new BackgroundJob("", mRunnable, mHandler)).start();            }                        /**            * Start face detection.            */            private void startFaceDetection() {                if (((Activity)mContext).isFinishing()) {                    return;                }                Runnable mRunnable = new Runnable() {                    public void run() {                        final CountDownLatch latch = new CountDownLatch(1);                        final Bitmap b = mBitmap;                        mHandler.post(new Runnable() {                            public void run() {                                if (b != mBitmap && b != null) {                                    mImageView.setImageBitmapResetBase(b, true);                                    mBitmap.recycle();                                    mBitmap = b;                                }                                if (mImageView.getScale() == 1.0f) {                                    mImageView.center(true, true);                                }                                latch.countDown();                            }                        });                        try {                            latch.await();                        } catch (Exception e) {                            throw new RuntimeException(e);                        }                        mRunFaceDetection.run();                    }                };                new Thread(new BackgroundJob("", mRunnable, mHandler)).start();            }                    /**            * 裁剪并保存.            *            * @return the bitmap            */            public Bitmap cropAndSave(){                final Bitmap bmp = onSaveClicked(mBitmap);                mImageView.mHighlightViews.clear();                return bmp;            }                        /**            * 裁剪并保存.            *            * @param bm the bm            * @return the bitmap            */            public Bitmap cropAndSave(Bitmap bm){                final Bitmap bmp = onSaveClicked(bm);                mImageView.mHighlightViews.clear();                return bmp;            }                        /**            * 取消裁剪.            */            public void cropCancel(){                mImageView.mHighlightViews.clear();                mImageView.invalidate();            }                        /**            * On save clicked.            *            * @param bm the bm            * @return the bitmap            */            private Bitmap onSaveClicked(Bitmap bm) {                if (mSaving)                    return bm;                        if (mCrop == null) {                    return bm;                }                        mSaving = true;                        Rect r = mCrop.getCropRect();                //int width = 360;                   //int height = 360;                  Bitmap croppedImage = Bitmap.createBitmap(cropImgWidth, cropImgHeight, Bitmap.Config.RGB_565);                Canvas canvas = new Canvas(croppedImage);                Rect dstRect = new Rect(0, 0, cropImgWidth, cropImgHeight);                canvas.drawBitmap(bm, r, dstRect, null);                return croppedImage;            }                    /**            * Save to local.            *            * @param bitmap the bitmap            * @return the string            */            public String saveToLocal(Bitmap bitmap){                //需要裁剪后保存为新图片                String mFileName = System.currentTimeMillis() + ".jpg";                String path = FILE_LOCAL+File.separator+mFileName;                try{                    FileOutputStream fos = new FileOutputStream(path);                    bitmap.compress(CompressFormat.JPEG, 85, fos);                    fos.flush();                    fos.close();                } catch (Exception e){                    e.printStackTrace();                    return null;                }                return path;            }                        /** The m run face detection. */            Runnable mRunFaceDetection = new Runnable() {                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();                            Rect imageRect = new Rect(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, false, true);                            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();                            Rect imageRect = new Rect(0, 0, width, height);                            // CR: sentences!                    // make the default size about 4/5 of the width or height                    int cropWidth = Math.min(width, height) * 4 / 5;                    int cropHeight = cropWidth*cropImgHeight/cropImgWidth;                            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, false, true);                    mImageView.add(hv);                }                        // Scale the image down for faster face detection.                private Bitmap prepareBitmap() {                    if (mBitmap == null) {                        return null;                    }                            // 256 pixels wide is enough.                    // CR: F => f (or change all f to F).                    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) {                        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;                            makeDefault();                            mImageView.invalidate();                            if (mImageView.mHighlightViews.size() > 0) {                                mCrop = mImageView.mHighlightViews.get(0);                                mCrop.setFocus(true);                            }                                    if (mNumFaces > 1) {                            }                        }                    });                }            };                        /**            * The Class BackgroundJob.            */            public class BackgroundJob implements Runnable{                                /** The message. */                private String message;                                /** The m job. */                private Runnable mJob;                                /** The m handler. */                private Handler mHandler;                        /**                * Instantiates a new background job.                *                * @param m the m                * @param job the job                * @param handler the handler                */                public BackgroundJob(String m, Runnable job, Handler handler){                    message = m;                    mJob = job;                    mHandler = handler;                }                                /**                * 描述:TODO.                *                * @see java.lang.Runnable#run()                * @author: zhaoqp                * @date:2013-6-17 上午9:04:47                * @version v1.0                */                public void run(){                    final CountDownLatch latch = new CountDownLatch(1);                    mHandler.post(new Runnable() {                        public void run() {                            try{                                mHandler.sendMessage(mHandler.obtainMessage(AbConstant.SHOW_PROGRESS));                            }catch (Exception e) {                            }                            latch.countDown();                        }                    });                     try {                         latch.await();                     } catch (Exception e) {                         throw new RuntimeException(e);                     }                    try {                        mJob.run();                    }catch (Exception e) {                        e.printStackTrace();                    }finally{                        mHandler.sendMessage(mHandler.obtainMessage(AbConstant.REMOVE_PROGRESS));                    }                }            }        }