Android自定义相机不存储照片,转换成Bitmap上传

在最近的开发中,遇到一个需求,使用相机拍照,但是不能存储到本地,并上传到服务器,这边用到的服务器接受上传的是base64的,需要将图片转换成base64上传。接下来我们开始整。

CameraPreview

CameraPreview这个是自定义相机
参考https:blog.csdn.net/qq_28193010/article/details/102719369
在此基础上增加了切换前后摄像头的功能

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback{
    private static final String TAG = "CameraPreview";

    private final int CAMERA_FONT = Camera.CameraInfo.CAMERA_FACING_FRONT;//前置摄像头标记

    private final int CAMERA_BACK = Camera.CameraInfo.CAMERA_FACING_BACK;//后置摄像头标记

    /**
     * open_camera 默认开启后置摄像头
     * true 后置摄像头
     * false 前置摄像头
     */
    private boolean open_camera = true;

    /**
     * SurfaceHolder是控制surface的一个抽象接口,它能够控制surface的尺寸和格式,修改surface的像素,监视surface的变化等等
     * 通过surfaceHolder可以将Camera和surface连接起来,当camera和surface连接后,camera获得的预览帧数据就可以通过surface显示在屏幕上了。
     */
    private SurfaceHolder mHolder;
    private Camera mCamera;

    private int picWidth = 1920;
    private int picHeight = 1080;

    public CameraPreview(Context context,boolean camera) {
        super(context);
        this.open_camera = camera;
        createCamera();
    }

    private void createCamera(){
        // 打开相机,获取camera实例
        mCamera =  Camera.open(open_camera ? CAMERA_BACK: CAMERA_FONT);
        //得到SurfaceHolder对象
        mHolder = getHolder();
        //添加回调,得到Surface的三个声明周期方法
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public Camera getCamera(){
        if (mCamera == null)
            createCamera();
        return mCamera;
    }

    /**
     * 在surface创建后立即被调用。
     * 在开发自定义相机时,可以通过重载这个函数调用camera.open()、camera.setPreviewDisplay(),
     * 来实现获取相机资源、连接camera和surface等操作。
     * @param surfaceHolder
     */
    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        if (mCamera == null)
            createCamera();
        try {
            //设置预览方向
//            mCamera.setDisplayOrientation(90);
            //把这个预览效果展示在SurfaceView上面
            mCamera.setPreviewDisplay(mHolder);
            //开启预览效果
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

    /**
     * 在surface发生format或size变化时调用。
     * 在开发自定义相机时,可以通过重载这个函数调用camera.startPreview来开启相机预览,
     * 使得camera预览帧数据可以传递给surface,从而实时显示相机预览图像。
     * @param holder
     * @param format
     * @param width
     * @param height
     */
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        if (holder.getSurface() == null) {
            return;
        }
        //	停止预览,关闭camra底层的帧数据传递以及surface上的绘制。
        mCamera.stopPreview();
        //重新设置预览效果
        try {
            mCamera.setPreviewDisplay(mHolder);
        } catch (IOException e) {
            e.printStackTrace();
        }
        setCameraParams(mCamera,picWidth,picHeight);
        // 开始预览,将camera底层硬件传来的预览帧数据显示在绑定的surface上。
        mCamera.startPreview();
        mCamera.autoFocus(new Camera.AutoFocusCallback() {
            @Override
            public void onAutoFocus(boolean success, Camera camera) {
                if (success) {
                    camera.cancelAutoFocus();
                }
            }
        });
    }

    public boolean getOpenCamera(){
        return this.open_camera;
    }

    /**
     *  csutCamera 切换摄像头
     */
    public void csutCamera(){
        mCamera.stopPreview();//停止预览
        mCamera.release();//释放摄像头
        /**
         * open_camera
         * true 后置摄像头
         * false 前置摄像头
         */
        try {
            mCamera = Camera.open(open_camera ? CAMERA_FONT : CAMERA_BACK);
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();//开启预览
            open_camera = open_camera ? false : true;
            Log.e(TAG, open_camera + "======");
        } catch (IOException e) {
            Log.e(TAG, "Error setting camera preview: " + e.getMessage());
        }
        setCameraParams(mCamera,picWidth,picHeight);

    }

    /**
     * 在surface销毁之前被调用。在开发自定义相机时,可以通过重载这个函数调用camera.stopPreview(),
     * camera.release()来实现停止相机预览及释放相机资源等操作。
     * @param surfaceHolder
     */
    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.setPreviewCallback(null);
            mCamera.release(); // 释放Camera实例
            mCamera = null;
        }
    }

    // 设置相机参数:在surfaceChanged方法中执行mCamera.startPreview()前调用setCameraParams(mCamera, mScreenWidth, mScreenHeight); 就可以了
    private void setCameraParams(Camera mCamera, int width, int height) {
        Log.i(TAG, "setCameraParams  width=" + width + "  height=" + height);
        Camera.Parameters parameters = mCamera.getParameters();

        // 获取摄像头支持的PictureSize列表
        List<Camera.Size> pictureSizeList = parameters.getSupportedPictureSizes();
        Collections.sort(pictureSizeList, new Comparator<Camera.Size>() {
            @Override
            public int compare(Camera.Size o1, Camera.Size o2) {
                return o2.width - o1.width;
            }
        });
        for (Camera.Size size : pictureSizeList) {
            Log.i(TAG, "pictureSizeList size.width=" + size.width + "  size.height=" + size.height);
        }

        /** 从列表中选取合适的分辨率 */
        Camera.Size picSize = getProperSize(pictureSizeList, ((float) height / width));
        if (null == picSize) {
            Log.i(TAG, "null == picSize");
            picSize = parameters.getPictureSize();
        }
        Log.i(TAG, "picSize.width=" + picSize.width + "  picSize.height=" + picSize.height);

        // 根据选出的PictureSize重新设置SurfaceView大小
        float w = picSize.width;
        float h = picSize.height;
        parameters.setPictureSize(picSize.width, picSize.height);
        Log.d(TAG, "保存图片尺寸:width*height: "+ w + "*" + h);
        //this.setLayoutParams(new FrameLayout.LayoutParams((int) (height * (h / w)), height));

        // 获取摄像头支持的PreviewSize列表
        List<Camera.Size> previewSizeList = parameters.getSupportedPreviewSizes();
        Collections.sort(previewSizeList, new Comparator<Camera.Size>() {
            @Override
            public int compare(Camera.Size o1, Camera.Size o2) {
                return o2.width - o1.width;
            }
        });
        for (Camera.Size size : previewSizeList) {
            Log.i(TAG, "previewSizeList size.width=" + size.width + "  size.height=" + size.height);
        }
        Camera.Size preSize = getProperSize(previewSizeList, ((float) height) / width);
        if (null != preSize) {
            Log.i(TAG, "preSize.width=" + preSize.width + "  preSize.height=" + preSize.height);
            parameters.setPreviewSize(preSize.width, preSize.height);
        }
        Log.d(TAG, "预览图片尺寸:width*height: "+ preSize.width + "*" + preSize.height);

        parameters.setJpegQuality(100); // 设置照片质量
//        if (parameters.getSupportedFocusModes().contains(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
//            parameters.setFocusMode(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); // 连续对焦模式
//        }
//        mCamera.cancelAutoFocus(); //自动对焦。
        // 设置PreviewDisplay的方向,效果就是将捕获的画面旋转多少度显示
        // TODO 这里直接设置90°不严谨,
        //  具体见https://developer.android.com/reference/android/hardware/Camera.html#setPreviewDisplay%28android.view.SurfaceHolder%29
        mCamera.setDisplayOrientation(90); // 不设置的话,将导致相机画面很奇怪
        mCamera.setParameters(parameters);
    }


    /**
     * 从列表中选取合适的分辨率
     * 默认w:h = 4:3
     * tip:这里的w对应屏幕的height, h对应屏幕的width
     */
    private Camera.Size getProperSize(List<Camera.Size> pictureSizeList, float screenRatio) {
        Log.i(TAG, "screenRatio=" + screenRatio);
        Camera.Size result = null;
        for (Camera.Size size : pictureSizeList) {
            if (size.width == 1920 && size.height == 1080){
                result = size;
                break;
            }

            float currentRatio = ((float) size.width) / size.height;
            if (currentRatio - screenRatio == 0  && size.width < 2500) {
                result = size;
                Log.d(TAG, "currentRatio - screenRatio == 0 : "+size.width);
                break;
            }
        }

        if (null == result) {
            for (Camera.Size size : pictureSizeList) {
                float curRatio = ((float) size.width) / size.height;
                if (curRatio == 4f / 3 && size.width < 2500) {// 默认w:h = 4:3
                    result = size;
                    Log.d(TAG, "curRatio: "+curRatio);
                    break;
                }
            }
        }
        return result;
    }
}

CustomTakePhotoActivity

CustomTakePhotoActivity是自定义相机预览页面,这里面将获取到的图片转换成了bitmap,再将bitmap转换成base64存储与缓存控件,其中有注释

public class CustomTakePhotoActivity extends BaseActivity {
	
	private final String TAG="CustomTakePhotoActivity";
	
	//存储缓存KEY
	private final String CUSTOM_PHOTO="CUSTOM_PHOTO";
	
	//存储缓存,是否拍摄背景图片
	private final String IS_SET_BACKGROUND="IS_SET_BG";
	
	//回调CODE
	private final int CUSTOM_TAKE_RESULT=2023013101;
	
	//裁剪完成回调CODE
	private final int CUT_OVER_RESULT=200;
	
	//失败回调CODE
	private final int CUT_OVER_DEFAULT=500;
	
	//是否重拍回调
	private final int TAKE_FOR_RESULT_CODE=100;
	
	//是否重拍KEY
	private final String TAKE_AGAIN="CUT_PHOTO";
	
	/**
	 * custom_takephoto_back 返回
	 */
	private LinearLayout mCustomTakephotoBack;
	/**
	 * custom_takephoto_surface 预览图像
	 */
	private FrameLayout mCustomTakephotoSurface;
	/**
	 * custom_takephoto_take 拍照
	 */
	private LinearLayout mCustomTakephotoTake;
	/**
	 * custom_takephoto_cut 切换前后摄像头
	 */
	private LinearLayout mCustomTakephoto_Cut;
	
	/**
	 * camera 声明相机对象
	 */
	private Camera mCamrea;
	
	/**
	 * mCameraPreView 声明自定义相机
	 */
	private CameraPreview mCameraPreView;
	
	/**
	 * openCamera 前后摄像头标记 默认开启后置摄像头
	 * true 后置摄像头
	 * false 前置摄像头
	 */
	private boolean openCamera=true;
	
	/**
	 * isSetBg 是否设置背景图片,默认不是
	 * true 设置背景图片
	 * false 不是设置背景图片
	 */
	private boolean isSetBg=false;
	
	/**
	 * mPreferences 缓存 存储图片数据
	 */
	private SharedPreferences mPreferences;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_custom_takephoto_layout);
		mPreferences=this.getSharedPreferences(CUSTOM_PHOTO, Activity.MODE_PRIVATE);
		initView();
	}
	
	
	public void initView() {
		mCustomTakephotoBack=findViewById(R.id.custom_takephoto_back);
		mCustomTakephotoSurface=findViewById(R.id.custom_takephoto_surface);
		mCustomTakephotoTake=findViewById(R.id.custom_takephoto_take);
		mCustomTakephoto_Cut=findViewById(R.id.custom_takephoto_cut);
		
		//初始化自定义相机
		mCameraPreView=new CameraPreview(this, openCamera);
		//获取相机对象
		mCamrea=mCameraPreView.getCamera();
		//添加预览页面
		mCustomTakephotoSurface.addView(mCameraPreView);
		
		//存储是否拍摄背景图片
		boolean isSetBg=getIntent().getBooleanExtra("IsSetBg", false);
		if(isSetBg) {
			Editor editor=mPreferences.edit();
			editor.putBoolean(IS_SET_BACKGROUND,isSetBg);
			editor.putInt("SET_BG_WIDTH",640);
			editor.putInt("SET_BG_HEIGHT",1130);
			editor.commit();
		}
		
		
		mCustomTakephotoBack.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				CustomTakePhotoActivity.this.finish();
			}
		});
		
		//点击拍照
		mCustomTakephotoTake.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				//获取相机对象
				mCamrea=mCameraPreView.getCamera();
				//得到相机参数
				Camera.Parameters parameters=mCamrea.getParameters();
				//设置对焦模式,自动对焦
				parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
				//设置图片格式
				parameters.setPictureFormat(ImageFormat.JPEG);
				//对焦成功后拍摄照片
				mCamrea.autoFocus(new Camera.AutoFocusCallback() {
					
					@Override
					public void onAutoFocus(boolean success, Camera camera) {
						// TODO Auto-generated method stub
						if (success) {
							mCamrea.takePicture(null, null,mPictureCallback);
						}
					}
				});
			}
		});
	}
	
	/**
	 * 摄像头拍照回调
	 */
	private Camera.PictureCallback mPictureCallback =new Camera.PictureCallback() {
		
		@Override
		public void onPictureTaken(byte[] data, Camera camera) {
			// TODO Auto-generated method stub
			Log.d(TAG, "jepg:"+data.length/1024+"KB");
			//转换为Bitmap
			Bitmap bt=BitmapFactory.decodeByteArray(data, 0, data.length);
			//转换为Base64,存储于缓存
			Editor editor=mPreferences.edit();
			editor.putString(CUSTOM_PHOTO,new BitmapToBase64().bitmapToBase64(bt));
			editor.commit();
			//存储缓存之后跳转预览页面
			Intent intent=new Intent(CustomTakePhotoActivity.this,CustomShowImageActivity.class);
			intent.putExtra(CUSTOM_PHOTO, openCamera);
			startActivityForResult(intent,TAKE_FOR_RESULT_CODE);
		}
	};
	
	/**
	 * TAKE_FOR_RESULT_CODE 回调判断是否重拍
	 * TAKE_AGAIN -1  重拍
	 * TAKE_AGAIN 0  裁剪完成
	 * TAKE_AGAIN 1  裁剪失败
	 */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// TODO Auto-generated method stub
		super.onActivityResult(requestCode, resultCode, data);
		if(requestCode==TAKE_FOR_RESULT_CODE) {
			if(resultCode==RESULT_OK) {
				int flag=data.getIntExtra(TAKE_AGAIN, -1);
				if(flag==-1) {
					//重拍
					//清除缓存数据
					Editor editor=mPreferences.edit();
					editor.clear();
					editor.commit();
					//获取相机对象
					mCamrea=mCameraPreView.getCamera();
					//开启预览
					mCamrea.startPreview();
				}else if(flag==0 || flag == 1) {
					//无需重拍,返回上一级判断是否裁剪成功
					Intent intent=new Intent();
					intent.putExtra("CUT_OVER",flag);
					setResult(CUSTOM_TAKE_RESULT, intent);
					finish();
				}
				
			}
		}
	}
	

}

CustomShowImageActivity

CustomShowImageActivity自定义的图片预览页面,确定或者重拍。这里特殊原因需要裁剪,因此我这里是确定之后跳转到裁剪页面的。

public class CustomShowImageActivity extends BaseActivity {
	
	private final String TAG="CustomShowImageActivity";
	
	//回调CODE
	private final int CUSTOM_TAKE_RESULT=2023013101;

	//缓存数据存储KEY
	public static final String CUSTOM_PHOTO="CUSTOM_PHOTO";
	
	//重拍回调
	private final int TAKE_FOR_RESULT_CODE=100;
	
	//重拍
	private final String TAKE_AGAIN="TAKE_AGAIN";
	
	/**
	 * custom_showimage_back 重拍
	 */
	private LinearLayout mCustomShowimageBack;
	
	/**
	 * custom_showimage_submit 确定
	 */
	private LinearLayout mCustomShowimageSubmit;
	
	/**
	 * custom_showimage_img 图片展示
	 */
	private ImageView mCustomShowimageImg;
	
	/**
	 * mPreferences 获取缓存中图片数据
	 */
	private SharedPreferences mPreferences;
	
	/**
	 * open_camera 判断前后摄像头 默认后置摄像头
	 */
	private boolean open_camera=true;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_custom_showimage_layout);
		mPreferences=this.getSharedPreferences(CUSTOM_PHOTO, Activity.MODE_PRIVATE);
		open_camera=getIntent().getBooleanExtra(CUSTOM_PHOTO,true);
		initView();
	}
	
	public void initView() {
		mCustomShowimageBack=findViewById(R.id.custom_showimage_back);
		mCustomShowimageSubmit=findViewById(R.id.custom_showimage_submit);
		mCustomShowimageImg=findViewById(R.id.custom_showimage_img);
		
		//获取图片数据
		String bitmap=mPreferences.getString(CUSTOM_PHOTO,"");
		//将Base64转换为Bitmap
		Bitmap bt=new BitmapToBase64().base64ToBitmap(bitmap);
		//判断前后摄像头,进行处理
		bt=new BitmapToBase64().converBimap(bt, open_camera);
		//展示图片
		mCustomShowimageImg.setImageBitmap(bt);
		
		//重拍
		mCustomShowimageBack.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Intent intent=new Intent();
				intent.putExtra(TAKE_AGAIN,-1);
				setResult(TAKE_FOR_RESULT_CODE,intent);
				CustomShowImageActivity.this.finish();
			}
		});
		
		//确定,跳转裁剪,因为之前已经存储过了,如果不重拍,到裁剪页面直接获取之前存储的图片数据,不再通过intent传递数据
		mCustomShowimageSubmit.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Intent intent=new Intent(CustomShowImageActivity.this,ClipPictureActivity.class);
				intent.putExtra("CAMERA_PHOTO", 0);
				startActivityForResult(intent, CUSTOM_TAKE_RESULT);
			}
		});
	}
	
	/**
	 * CUT_PHOTO -1 裁剪失败
	 * CUT_PHOTO 0 裁剪成功 不在此处判断是否裁剪成功,返回上一级
	 */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// TODO Auto-generated method stub
		super.onActivityResult(requestCode, resultCode, data);
		if(requestCode==CUSTOM_TAKE_RESULT) {
			if(resultCode==RESULT_OK) {
				int flag =data.getIntExtra("CUT_PHOTO",-1);
				Intent intent=new Intent();
				intent.putExtra("CUT_PHOTO",flag);
				setResult(RESULT_OK, intent);
				finish();
			}
		}
	}
}

ClipPictureActivity

ClipPictureActivity,自定义裁剪,细节看注释

public class ClipPictureActivity extends Activity implements OnTouchListener,
		OnClickListener {
	
	//回调CODE
	private final int CUSTOM_TAKE_RESULT=2023013101;
	
	ImageView srcPic;
	Button sure;
	ClipView clipview;
	private CommonUtil commonutil=new CommonUtil(this);
	int reqwidth = 0;
	int reqheight = 0;

	// These matrices will be used to move and zoom image
	Matrix matrix = new Matrix();
	Matrix savedMatrix = new Matrix();

	// We can be in one of these 3 states
	static final int NONE = 0;
	static final int DRAG = 1;
	static final int ZOOM = 2;
	private static final String TAG = "11";
	int mode = NONE;

	// Remember some things for zooming
	PointF start = new PointF();
	PointF mid = new PointF();
	float oldDist = 1f;
	
	//存储缓存KEY
	private final String CUSTOM_PHOTO="CUSTOM_PHOTO";
	
	//是否存储背景图片
	private boolean isSetBg=false;
	
	private SharedPreferences mPreferences;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		mPreferences=this.getSharedPreferences(CUSTOM_PHOTO, Activity.MODE_PRIVATE);
		
		isSetBg=mPreferences.getBoolean("IS_SET_BG", false);
		
		if(isSetBg) {
			reqwidth = mPreferences.getInt("SET_BG_WIDTH", 0);
			reqheight = mPreferences.getInt("SET_BG_HEIGHT", 0);
		}
		
		String photoPath = null;
		try {
			photoPath = getIntent().getStringExtra("photoPath");
			
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		
		if (isSetBg && (0 != reqwidth && 0 != reqheight)) {
			setContentView(R.layout.bgphotocrop);
		} else {
			setContentView(R.layout.photocrop);
		}
		
		

		Bitmap img=null;
		// 设置要剪裁的图片
		//判断是相机拍摄还是图库选择 0 相机 1 图库
		int flag=getIntent().getIntExtra("CAMERA_PHOTO",1);
		if(flag==0) {
			//获取图片数据
			String base=mPreferences.getString(CUSTOM_PHOTO, "");
			//将Base64转换成bitmap
			img =new BitmapToBase64().base64ToBitmap(base);
		}else {
			BitmapFactory.Options options = new BitmapFactory.Options();
			options.inJustDecodeBounds = true;
			BitmapFactory.decodeFile(photoPath, options);
			options.inSampleSize = calculateInSampleSize(options, 600, 600);
			options.inJustDecodeBounds = false;
			img = BitmapFactory.decodeFile(photoPath, options);
		}
		

		
		if (img.getWidth() > img.getHeight()) {
		    img = rotateBitmapByDegree(img, 90);
		}

		srcPic = (ImageView) this.findViewById(R.id.src_pic);
		srcPic.setImageBitmap(img);
		if(img==null){
			Intent idata = new Intent();
			idata.putExtra("returnData", "文件格式不支持");
			setResult(20141104, idata);
			this.finish();		
		}else{
			/* 这里就是绘制矩形区域 */
			WindowManager wm = this.getWindowManager();
			int width = wm.getDefaultDisplay().getWidth();
			int height = wm.getDefaultDisplay().getHeight();
			int w = img.getWidth();
			int h = img.getWidth();
			matrix.postTranslate((width - w) / 2, (height - h) / 2);
			srcPic.setImageMatrix(matrix);
			srcPic.setOnTouchListener(this);
	
			sure = (Button) this.findViewById(R.id.sure);
			sure.setOnClickListener(this);
		}
	}

	public int calculateInSampleSize(BitmapFactory.Options options,
			int reqWidth, int reqHeight) {
		// Raw height and width of image
		final int height = options.outHeight;
		final int width = options.outWidth;
		int inSampleSize = 1;

		if (height > reqHeight || width > reqWidth) {

			// Calculate ratios of height and width to requested height and
			// width
			final int heightRatio = Math.round((float) height
					/ (float) reqHeight);
			final int widthRatio = Math.round((float) width / (float) reqWidth);

			// Choose the smallest ratio as inSampleSize value, this will
			// guarantee
			// a final image with both dimensions larger than or equal to the
			// requested height and width.
			inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
		}

		return inSampleSize;
	}

	/* 这里实现了多点触摸放大缩小,和单点移动图片的功能,参考了论坛的代码 */
	public boolean onTouch(View v, MotionEvent event) {
		ImageView view = (ImageView) v;
		// Handle touch events here...
		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_UP:
		case MotionEvent.ACTION_POINTER_UP:
			mode = NONE;
			Log.d(TAG, "mode=NONE");
			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;
		}

		view.setImageMatrix(matrix);
		return true; // indicate event was handled
	}

	/** Determine the space between the first two fingers */
	private float spacing(MotionEvent event) {
		float x = event.getX(0) - event.getX(1);
		float y = event.getY(0) - event.getY(1);
		return (float)Math.sqrt(x * x + y * y);
	}

	/** Calculate the mid point of the first two fingers */
	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);
	}

	boolean isDoingtheJob = false;

	/* 点击进入预览 */
	public void onClick(View v) {
		if (isDoingtheJob) {
			return;
		}
		isDoingtheJob = true;
		sure.setClickable(false);
		try {

			Bitmap fianBitmap = getBitmap();
			// ByteArrayOutputStream baos = new ByteArrayOutputStream();
			// fianBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);

			// if(0!=reqwidth&&0!=reqheight){
			// fianBitmap=bigBt(fianBitmap);
			// }

			// 压缩判断
			// 图片允许最大空间 单位:KB
			double maxSize = 150.00;
			// 将bitmap放至数组中,意在bitmap的大小(与实际读取的原文件要大)
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			fianBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
			byte[] bb = baos.toByteArray();
			// 将字节换成KB
			double mid = bb.length / 1024;
			// 判断bitmap占用空间是否大于允许最大空间 如果大于则压缩 小于则不压缩
			if (mid > maxSize) {
				// 获取bitmap大小 是允许最大大小的多少倍
				double i = mid / maxSize;
				// 开始压缩 此处用到平方根 将宽带和高度压缩掉对应的平方根倍
				// (1.保持刻度和高度和原bitmap比率一致,压缩后也达到了最大大小占用空间的大小)
				fianBitmap = HttpTool.zoomImage(fianBitmap,
						fianBitmap.getWidth() / Math.sqrt(i),
						fianBitmap.getHeight() / Math.sqrt(i));
			}

			Intent idata = new Intent();
			if (Global.isDebug) {
				System.out.println("reqwidth=" + reqwidth + ",reqheight="
					+ reqheight + "-------------------->");
			}
			if () {
				idata.putExtra("bitmap", BitmapUtils.Bitmap2Bytes(fianBitmap));
				fianBitmap.recycle();
			} else {
				String base64 = bitmapToBase64(fianBitmap);
				//idata.putExtra("bitmap", base64);
				commonutil.doRememberAvatarBase64(base64);
				fianBitmap.recycle();
				idata.putExtra("CUT_PHOTO",0);
				Editor editor=mPreferences.edit();
				editor.clear();
				editor.commit();
			}
			setResult(RESULT_OK, idata);
			this.finish();
		} catch (Exception e) {
			isDoingtheJob = false;
			sure.setClickable(true);
		}

		// startActivity(intent);
	}

	private Bitmap bigBt(Bitmap bitmap) {
		if (Global.isDebug) {
			System.out.println("((float)reqwidth)/cvrealwidth "
					+ ((float) reqwidth) / cvrealwidth
					+ "((float)reqwidth)/cvrealwidth" + ((float) reqheight)
					/ cvrealheight);
		}
		Matrix matrix = new Matrix();
		matrix.postScale(((float) reqwidth) / cvrealwidth, ((float) reqheight)
				/ cvrealheight); // 长和宽放大缩小的比例
		Bitmap resizeBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
				bitmap.getHeight(), matrix, true);
		bitmap.recycle();
		return resizeBmp;
	}

	private int cvrealwidth;
	private int cvrealheight;

	/* 获取矩形区域内的截图 */
	private Bitmap getBitmap() {
		getBarHeight();
		Bitmap screenShoot = takeScreenShot();

		if (0 != reqwidth && 0 != reqheight) {
			clipview = (BGClipView) this.findViewById(R.id.clipview);
		} else {
			clipview = (HeaderClipView) this.findViewById(R.id.clipview);
		}
		int width = clipview.getWidth();
		int height = clipview.getHeight();
		cvrealwidth = height / 3;
		cvrealheight = height / 3;
		Bitmap finalBitmap;

		if (0 != reqwidth && 0 != reqheight) {
			finalBitmap = Bitmap.createBitmap(screenShoot,
					(width - height / 3) / 2, height * 1 / 6 + titleBarHeight
							+ statusBarHeight, height / 3, height * 2 / 3);
		} else {
			finalBitmap = Bitmap.createBitmap(screenShoot,
					(width - height / 3) / 2, height / 3 + titleBarHeight
							+ statusBarHeight, height / 3, height / 3);
		}
		screenShoot.recycle();
		return finalBitmap;
	}

	int statusBarHeight = 0;
	int titleBarHeight = 0;

	private void getBarHeight() {
		// 获取状态栏高度
		Rect frame = new Rect();
		this.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
		statusBarHeight = frame.top;

		int contenttop = this.getWindow()
				.findViewById(Window.ID_ANDROID_CONTENT).getTop();
		// statusBarHeight是上面所求的状态栏的高度
		titleBarHeight = contenttop - statusBarHeight;
		if (Global.isDebug) {
			Log.v(TAG, "statusBarHeight = " + statusBarHeight
					+ ", titleBarHeight = " + titleBarHeight);
		}
	}

	// 获取Activity的截屏
	private Bitmap takeScreenShot() {
		View view = this.getWindow().getDecorView();
		view.setDrawingCacheEnabled(true);
		view.buildDrawingCache();
		return view.getDrawingCache();
	}

	/**
	 * bitmap转为base64
	 * 
	 * @param bitmap
	 * @return
	 */
	public String bitmapToBase64(Bitmap bitmap) {

		String result = null;
		ByteArrayOutputStream baos = null;
		try {
			if (bitmap != null) {
				baos = new ByteArrayOutputStream();
				bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);

				baos.flush();
				baos.close();

				byte[] bitmapBytes = baos.toByteArray();
				result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT);
			}
		} catch (IOException e) {
			// 解析出错
			e.printStackTrace();
		} finally {
			try {
				if (baos != null) {
					baos.flush();
					baos.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	
	public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
	    Bitmap returnBm = null;

	    // 根据旋转角度,生成旋转矩阵
	    Matrix matrix = new Matrix();
	    matrix.postRotate(degree);
	    try {
	        // 将原始图片按照旋转矩阵进行旋转,并得到新的图片
	        returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
	    } catch (OutOfMemoryError e) {
	    }
	    if (returnBm == null) {
	        returnBm = bm;
	    }
	    if (bm != returnBm) {
	        bm.recycle();
	    }
	    return returnBm;
	}

}

工具类

使用到的工具类,base64与bitmap之间的互相转换,以及bitmap图片旋转等操作

public class BitmapToBase64 {
	private final String TAG="BitmapToBase64";
	
	private ByteArrayOutputStream btOut;
	
	/**
	 * Bitmap转换成Base64
	 * @param bt
	 * @return string
	 */
	public String bitmapToBase64(Bitmap bt) {
		String result=null;
		try {
			if(bt!=null) {
				btOut=new ByteArrayOutputStream();
				bt.compress(Bitmap.CompressFormat.PNG, 100, btOut);
				btOut.flush();
				btOut.close();
				byte[] btArray=btOut.toByteArray();
				result=Base64.encodeToString(btArray,Base64.DEFAULT);
			}
		}catch(IOException e) {
			Log.d(TAG, e.getMessage());
		}finally {
			try {
				btOut.flush();
				btOut.close();
			} catch (IOException e2) {
				// TODO: handle exception
			}
		}
		return result;
	}
	
	/**
	 * Base64 转换成Bitmap
	 * @param base
	 * @return bitmap
	 */
	public Bitmap base64ToBitmap(String base) {
		byte[] bytes=Base64.decode(base,Base64.DEFAULT);
		Bitmap bt=BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
		return bt;
	}
	
	/**
	 * Bitmap图像翻转
	 * @param bt
	 * @param camera
	 * true 后置摄像头 顺时针旋转90°
	 * false 前置摄像头 逆时针旋转90°+镜像水平翻转
	 * @return
	 */
	public Bitmap converBimap(Bitmap bt,boolean camera) {
		int w=bt.getWidth();
		int h=bt.getHeight();
		//创建一个与原图大小一致的空白图
		Bitmap bt1=Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
		Canvas canvas=new Canvas(bt1);
		Matrix m=new Matrix();
		if(camera) {
			//后置摄像头,顺时针旋转90°
			m.postRotate(90);
		}else {
			//前置摄像头 逆时针旋转90°+镜像水平翻转
			m.postRotate(-90);
			m.postScale(-1, 1);
		}
		
		Bitmap bt2=Bitmap.createBitmap(bt,0,0,w,h,m,true);
		canvas.drawBitmap(bt2, new Rect(0, 0, bt2.getWidth(),bt2.getHeight()),new Rect(0,0,w,h),null);
		return bt2;
		
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值