在最近的开发中,遇到一个需求,使用相机拍照,但是不能存储到本地,并上传到服务器,这边用到的服务器接受上传的是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.0mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);}public Camera getCamera(){if (mCamera == null)createCamera();return mCamera;}/*** 在surface创建后立即被调用。* 在开发自定义相机时,可以通过重载这个函数调用camera.open()、camera.setPreviewDisplay(),* 来实现获取相机资源、连接camera和surface等操作。* @param surfaceHolder*/@Overridepublic 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*/@Overridepublic 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() {@Overridepublic 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*/@Overridepublic 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>() {@Overridepublic 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>() {@Overridepublic 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%29mCamera.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:3result = size;Log.d(TAG, "curRatio: "+curRatio);break;}}}return result;}
}

CustomTakePhotoActivity

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

public class CustomTakePhotoActivity extends BaseActivity {private final String TAG="CustomTakePhotoActivity";//存储缓存KEYprivate final String CUSTOM_PHOTO="CUSTOM_PHOTO";//存储缓存,是否拍摄背景图片private final String IS_SET_BACKGROUND="IS_SET_BG";//回调CODEprivate final int CUSTOM_TAKE_RESULT=2023013101;//裁剪完成回调CODEprivate final int CUT_OVER_RESULT=200;//失败回调CODEprivate final int CUT_OVER_DEFAULT=500;//是否重拍回调private final int TAKE_FOR_RESULT_CODE=100;//是否重拍KEYprivate 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;@Overridepublic void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.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() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubCustomTakePhotoActivity.this.finish();}});//点击拍照mCustomTakephotoTake.setOnClickListener(new View.OnClickListener() {@Overridepublic 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() {@Overridepublic void onAutoFocus(boolean success, Camera camera) {// TODO Auto-generated method stubif (success) {mCamrea.takePicture(null, null,mPictureCallback);}}});}});}/*** 摄像头拍照回调*/private Camera.PictureCallback mPictureCallback =new Camera.PictureCallback() {@Overridepublic void onPictureTaken(byte[] data, Camera camera) {// TODO Auto-generated method stubLog.d(TAG, "jepg:"+data.length/1024+"KB");//转换为BitmapBitmap 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  裁剪失败*/@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {// TODO Auto-generated method stubsuper.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";//回调CODEprivate final int CUSTOM_TAKE_RESULT=2023013101;//缓存数据存储KEYpublic 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;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.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转换为BitmapBitmap bt=new BitmapToBase64().base64ToBitmap(bitmap);//判断前后摄像头,进行处理bt=new BitmapToBase64().converBimap(bt, open_camera);//展示图片mCustomShowimageImg.setImageBitmap(bt);//重拍mCustomShowimageBack.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubIntent intent=new Intent();intent.putExtra(TAKE_AGAIN,-1);setResult(TAKE_FOR_RESULT_CODE,intent);CustomShowImageActivity.this.finish();}});//确定,跳转裁剪,因为之前已经存储过了,如果不重拍,到裁剪页面直接获取之前存储的图片数据,不再通过intent传递数据mCustomShowimageSubmit.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubIntent intent=new Intent(CustomShowImageActivity.this,ClipPictureActivity.class);intent.putExtra("CAMERA_PHOTO", 0);startActivityForResult(intent, CUSTOM_TAKE_RESULT);}});}/*** CUT_PHOTO -1 裁剪失败* CUT_PHOTO 0 裁剪成功 不在此处判断是否裁剪成功,返回上一级*/@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {// TODO Auto-generated method stubsuper.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 {//回调CODEprivate 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 imageMatrix matrix = new Matrix();Matrix savedMatrix = new Matrix();// We can be in one of these 3 statesstatic 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 zoomingPointF start = new PointF();PointF mid = new PointF();float oldDist = 1f;//存储缓存KEYprivate final String CUSTOM_PHOTO="CUSTOM_PHOTO";//是否存储背景图片private boolean isSetBg=false;private SharedPreferences mPreferences;@Overridepublic 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 exceptione.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转换成bitmapimg =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 imagefinal 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// widthfinal 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);// }// 压缩判断// 图片允许最大空间 单位:KBdouble maxSize = 150.00;// 将bitmap放至数组中,意在bitmap的大小(与实际读取的原文件要大)ByteArrayOutputStream baos = new ByteArrayOutputStream();fianBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);byte[] bb = baos.toByteArray();// 将字节换成KBdouble 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;}}

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

  1. Android kotlin 将Base64字符串转换成Bitmap,并在jetpack compose的Image控件中显示

    Android kotlin 将Base64字符串转换成Bitmap 前言 代码 将Base64字符串转换成Bitmap 在jetpack compose的Image控件中显示Bitmap 完事 前言 ...

  2. android 自定义 黑点,Android自定义密码样式 黑点转换成特殊字符

    本文为大家分享了Android自定义密码样式的制作代码,黑点换成¥.%等特殊字符,供大家参考,具体内容如下 复制下面代码即可: 布局: xmlns:android="http://schem ...

  3. android密码是小黑点,Android自定义密码样式 黑点转换成特殊字符

    本文为大家分享了Android自定义密码样式的制作代码,黑点换成¥.%等特殊字符,供大家参考,具体内容如下 复制下面代码即可: 布局: xmlns:android="http://schem ...

  4. PPTPDF文件转换成图片上传OSS

    PPTPDFIMAGE 先把文件上传至本地,再去读取文件转变上传. <dependency><groupId>org.apache.pdfbox</groupId> ...

  5. Android 将drawable下的图片转换成bitmap、Drawable

    将drawable下的图片转换成bitmap 1. Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xx ...

  6. Android自定义相机,切换前后摄像头,照相机拍照

    Android自定义相机,简单实现切换前后摄像头,照相机拍照 Ctrl +C  Ctrl+V 可以直接 run 起来,注释比较详细;源码下载 <?xml version="1.0&qu ...

  7. android 自定义相机源码,Android 自定义相机及分析源码

    Android 自定义相机及分析源码 使用Android 系统相机的方法: 要想让应用有相机的action,咱们就必须在清单文件中做一些声明,好让系统知道,如下 action的作用就是声明action ...

  8. Android 自定义相机Demo 入门学习

    Android 自定义相机Demo 本文是参考网上一些自定义相机示例,再结合自己对相机的功能需求写的,基本上包含了很多基本功能,比如相机对焦.闪光灯,以及在手机预览界面上绘制自己想要绘制的图案. 话不 ...

  9. android 实现自动拍照,Android自定义相机实现定时拍照功能

    这篇博客为大家介绍Android自定义相机,并且实现倒计时拍照功能. 首先自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件: activity_main.xml andro ...

最新文章

  1. SAP WM初阶移动类型设置里的GR Date
  2. SSH免密登录(内含批量配置脚本)
  3. python操作excel-自动化办公:python 操作Excel
  4. leetcode算法题--相交链表
  5. 使用CEfSharp之旅(1) 加载网络页面
  6. 魅族android6.0,【魅族魅蓝5s评测】迷人Flyme 安卓6.0提升流畅度_手机评测-中关村在线...
  7. Win7局域网打印机共享设置(详细图文流程)
  8. 2路由策略_route-map(执行路由策略)
  9. 前端学习(1913)vue之电商管理系统电商系统之创建user分支并把代码推到码云
  10. 关于Vue 3.0 的改进 Proxy 代理实现数据驱动视图
  11. eslint不报错 vue_2-2【微信小程序全栈开发课程】index页面搭建--ESlint格式错误
  12. 关于ggplot2的一些用法
  13. 串口接收到的字符型数据如何转化成数字
  14. 实战开发经验:是什么阻碍了我们跨平台
  15. 解决sql2005远程连接报错,提示请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接
  16. 奇迹1.03H服务端开服架设文件Data文件详解
  17. 印刷质量缺陷的视觉检测原理概述
  18. 生信软件的下载与使用方法总结
  19. 【招聘】STM32、LINUX、FPGA工程师,硬件设计工程师,待遇7000~15000!
  20. 第四篇--关于device

热门文章

  1. 计算机编程类视频学习参考网站
  2. 谷歌公司推荐的计算机科学在线课程学习路线
  3. Physical Signal Overshadowing Attack on LTE学习笔记
  4. 暨南大学计算机专硕考英语一,2019暨南大学计算机考研初试科目、参考书目、招生人数...
  5. mysql 受影响行数_关于受影响行数的详细介绍
  6. font-weight:字体粗细
  7. MPU6050杨桃电子代码
  8. 一篇文章讲透线上应用监控
  9. 编写图片复制JAVA代码_何编写[java]代码为图片赋予“铅笔素描”效果
  10. 企业网站建设与UI设计的关系