Android图片压缩上传和解决上传服务器之后图片旋转的问题

您所在的位置:网站首页 安卓手机图片压缩app Android图片压缩上传和解决上传服务器之后图片旋转的问题

Android图片压缩上传和解决上传服务器之后图片旋转的问题

2023-10-13 15:01| 来源: 网络整理| 查看: 265

Android图片上传是开发中最常见的应用场景,但是现在的手机摄像头像素都非常高,随便拍一张照片都在3~4M之间,分辨率也都在3000x4000左右,如此大的照片如果直接显示或者上传到服务器,体验都是非常差的,所以图片在上传之前,一般要做两次压缩,一次尺寸压缩,一次质量压缩。话不多说,直接上代码吧

一、图片的压缩一般写一个工具类进行处理,我们起一个方法名就叫compress吧

/** * 根据图片路径压缩图片并返回压缩后图片路径 * @param path * @return */ public static String compress(String path) { Bitmap bm = getimage(path);//得到压缩后的图片 if(bm == null){ return null; } String file = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp" + File.separator; File f = new File(file); if(!f.exists()){ f.mkdirs(); } String[] temps = path.split("/"); String temp = ""; if(!TextUtils.isEmpty(temps[temps.length-1])){ temp = temps[temps.length-1]; } String picName = temp+(DateUtil.getTimestamp())+".png"; try { FileOutputStream out = new FileOutputStream(file+picName); bm.compress(Bitmap.CompressFormat.PNG, 90, out); out.flush(); out.close(); } catch (Exception e) { e.printStackTrace(); } f = new File(file+picName); if(new File(path).length() < f.length()){ f.delete(); return ""; } return file+picName; }

二、这个方法就是得到一个压缩后的图片,然后把图片写到一个临时目录,返回一个压缩后的图片路径,得到这个路径之后,由网络框架进行上传。这个getimage方法就做两件事,一个是尺寸压缩,压缩完了以后进行质量压缩

/** * 第二:图片按比例大小压缩方法(根据路径获取图片并压缩): * @param srcPath * @return */ public static Bitmap getimage(String srcPath) { BitmapFactory.Options newOpts = new BitmapFactory.Options(); //开始读入图片,此时把options.inJustDecodeBounds 设回true了 newOpts.inJustDecodeBounds = true; Bitmap bitmap = BitmapFactory.decodeFile(srcPath,newOpts);//此时返回bm为空 newOpts.inJustDecodeBounds = false; int w = newOpts.outWidth; int h = newOpts.outHeight; float hh = 800f;//这里设置高度为800f float ww = 480f;//这里设置宽度为480f //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可 int be = 1;//be=1表示不缩放 if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放 be = (int) (newOpts.outWidth / ww); } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放 be = (int) (newOpts.outHeight / hh); } if (be 100 && options > 0) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩 baos.reset();//重置baos即清空baos image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中 options -= 10;//每次都减少10 } ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中 Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片 return bitmap; }

一顿猛操作下来,一张几M大小的图片,已经变成了100kb以下了,也可以稍微调大一点,200kb/300kb问题都不大,而且照片还清晰一些。上传服务器之后,服务器会为我们生成缩略图,所以上传原图清晰一点更好一些。如果是直接拍照上传的图片,可能还会遇到另外一个问题,就是本地查看正常的照片,传到服务器发现照片旋转了90°或者270°,这是因为有些手机摄像头的参数原因,拍出来的照片是自带旋转角度的。

还好数码照片会将它的拍摄参数存放在exif当中,你可以认为exif是照片的一些头部信息,比如拍照的时间,相机的品牌,型号和色彩编码等等,其中也包括了旋转角度。Android可以通过ExifInterface来读取图片的exif信息。所以我们要读取照片的旋转角度,然后通过matrix把它旋转过来

所以我们要在刚才的compress方法再加两个方法:

/** * 读取照片的旋转角度 * @param path * @return */ public static int readPictureDegree(String path) { int degree = 0; try { ExifInterface exifInterface = new ExifInterface(path); int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: degree = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: degree = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: degree = 270; break; } }catch (IOException e) { e.printStackTrace(); } return degree; } /** * 旋转照片 * @param bitmap * @param rotate * @return */ private static Bitmap rotateBitmap(Bitmap bitmap, int rotate) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); Matrix matrix = new Matrix(); matrix.postRotate(rotate); return Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true); }

 

所以完整的compress方法如下:

/** * 根据图片路径压缩图片并返回压缩后图片路径 * @param path * @return */ public static String compress(String path) { Bitmap bm = getimage(path);//压缩照片 if(bm == null){ return null; } int degree = readPictureDegree(path);//读取照片旋转角度 if (degree > 0) { bm = rotateBitmap(bm, degree); //旋转照片 } String file = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp" + File.separator; File f = new File(file); if(!f.exists()){ f.mkdirs(); } String picName = System.currentTimeMillis() + ".jpg"; String resultFilePath = file + picName; try { FileOutputStream out = new FileOutputStream(resultFilePath); bm.compress(Bitmap.CompressFormat.JPEG, 90, out); out.flush(); out.close(); } catch (Exception e) { e.printStackTrace(); } return resultFilePath; }

一个完整的图片上传流程应该是先进行尺寸压缩,然后在进行质量压缩,然后看照片是否有旋转角度,如果有,rotate一下,最后返回处理后的照片路径,由网络框架进行上传,请注意的是,由于压缩图片有点耗时,所以要放在子线程中操作

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3