package com.withiter.quhao.util.tool; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.SocketTimeoutException; import java.net.URL; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.ExifInterface; import android.os.Environment; import android.text.TextUtils; import android.util.Log; import com.withiter.quhao.util.QuhaoLog; import com.withiter.quhao.util.StringUtils; /** * * 从服务器上获取的图片,存储在本地 * * 采用单例模式 * * @author ASUS * */ public class ImageUtil { private static final String TAG = ImageUtil.class.getName(); private static File cacheDir; private static ImageUtil instance; // update this singleton implementation due to unsafe thread problem public static ImageUtil getInstance() { if (null == instance) { instance = new ImageUtil(); } return instance; } public static ImageUtil getInstance(Context context) { if (instance == null) { instance = new ImageUtil(); } return instance; } private ImageUtil() { // 判断SD卡是否存在 if (FileUtil.hasSdcard()) { // 在sd卡上建立图片存放空间 cacheDir = new File(Environment.getExternalStorageDirectory(), QuhaoConstant.IMAGES_SD_URL); if (!cacheDir.exists()) { cacheDir.mkdirs(); } } } /** * 读取图片属性:旋转的角度 * @param path 图片绝对路径 * @return degree旋转的角度 */ 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; } return degree; } /** * 质量压缩方法 * @param image * @return */ public static Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 int options = 100; while ( baos.toByteArray().length / 1024>50) { //循环判断如果压缩后图片是否大于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; } /** * 图片按比例大小压缩方法(根据路径获取图片并压缩): * @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; //现在主流手机比较多是800*480分辨率,所以高和宽我们设置为 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 <= 0) be = 1; newOpts.inSampleSize = be;//设置缩放比例 //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了 bitmap = BitmapFactory.decodeFile(srcPath, newOpts); return compressImage(bitmap);//压缩好比例大小后再进行质量压缩 } /** * 图片按比例大小压缩方法(根据Bitmap图片压缩): * @param image * @return */ public static Bitmap comp(Bitmap image) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, 100, baos); if( baos.toByteArray().length / 1024>1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出 baos.reset();//重置baos即清空baos image.compress(Bitmap.CompressFormat.JPEG, 50, baos);//这里压缩50%,把压缩后的数据存放到baos中 } ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray()); BitmapFactory.Options newOpts = new BitmapFactory.Options(); //开始读入图片,此时把options.inJustDecodeBounds 设回true了 newOpts.inJustDecodeBounds = true; Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts); newOpts.inJustDecodeBounds = false; int w = newOpts.outWidth; int h = newOpts.outHeight; //现在主流手机比较多是800*480分辨率,所以高和宽我们设置为 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 <= 0) be = 1; newOpts.inSampleSize = be;//设置缩放比例 //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了 isBm = new ByteArrayInputStream(baos.toByteArray()); bitmap = BitmapFactory.decodeStream(isBm, null, newOpts); return compressImage(bitmap);//压缩好比例大小后再进行质量压缩 } public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) { int initialSize = computeInitialSampleSize(options, minSideLength,maxNumOfPixels); int roundedSize; if (initialSize <= 8 ) { roundedSize = 1; while (roundedSize < initialSize) { roundedSize <<= 1; } } else { roundedSize = (initialSize + 7) / 8 * 8; } return roundedSize; } private static int computeInitialSampleSize(BitmapFactory.Options options,int minSideLength, int maxNumOfPixels) { double w = options.outWidth; double h = options.outHeight; int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels)); int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength)); if (upperBound < lowerBound) { // return the larger one when there is no overlapping zone. return lowerBound; } if ((maxNumOfPixels == -1) && (minSideLength == -1)) { return 1; } else if (minSideLength == -1) { return lowerBound; } else { return upperBound; } } public File getFile(String imageUrl) { String fileName = imageUrl.split("\\?fileName=")[1]; File file = new File(cacheDir, fileName); if (file.exists()) { return file; } return null; } public String getFilePath(String imageUrl) { QuhaoLog.d(TAG, "imageUrl : " + imageUrl); String path = cacheDir.getPath() + "/" + imageUrl.split("\\?fileName=")[1]; QuhaoLog.d(TAG, "file on sd:"+path); return path; } public File saveFile(String imageUrl, InputStream is) { QuhaoLog.i(TAG, "start to save image to SD card, the image url is : " + imageUrl); if (StringUtils.isNull(imageUrl)) { return null; } String fileName = imageUrl.split("\\?fileName=")[1]; // String newFileName = DesUtils.byteArr2HexStr(fileName.getBytes()); File file = null; try { file = new File(cacheDir, fileName); if (!file.exists()) { file.createNewFile(); OutputStream os = new FileOutputStream(file); final int buffer_size = 1024; byte[] bytes = new byte[buffer_size]; for (;;) { int count = is.read(bytes, 0, buffer_size); if (count == -1) break; os.write(bytes, 0, count); } os.close(); } } catch (Throwable e) { Log.e(fileName, e.getMessage()); e.printStackTrace(); } return file; } /** * 删除SD卡文件信息 */ public void cleanPictureCache() throws IOException { /** * 遍历所有的然后删除 */ if (FileUtil.hasSdcard() && cacheDir.exists()) { File files[] = cacheDir.listFiles(); if (files != null) { for (File f : files) { if (f.isDirectory()) { } else { f.delete(); } } } // fFile.delete(); } } /** * 获得bitmap对象 */ public Bitmap getBitmap(String url, boolean isScaleByWidth, int widthOrHeight) { return getBitmap(url, isScaleByWidth, widthOrHeight, true); } /** * 获得图片 * * @param url * @param isScaleByWidth * @param widthOrHeight * @param isNet * 没有网络不需要下载 * @return */ public Bitmap getBitmap(String url, boolean isScaleByWidth, int widthOrHeight, boolean isNet) { Bitmap bitmap = null; if (TextUtils.isEmpty(url)) { return null; // 缓存中不存在的场合 } if (bitmap == null) { URL imgUrl; HttpURLConnection conn = null; InputStream is = null; if (bitmap == null && isNet) { // sdcard中不存在的场合 // 从服务器获得bitmap对象 try { // if (DEBUG) Log.w(TAG, "从网络下载["+rand+"]"+start); imgUrl = new URL(url); conn = (HttpURLConnection) imgUrl.openConnection(); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); is = conn.getInputStream(); if(null!=is) { bitmap = BitmapFactory.decodeStream(is); } } catch (SocketTimeoutException e) { bitmap = null; } catch (Exception ex) { try { } catch (Exception e) { } if (bitmap != null) { bitmap = null; } } finally { if(null!=is) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if(null!=conn) { conn.disconnect(); } } } } return bitmap; } /** * decodes image and scales it to reduce memory consumption * * @param f * @return */ public static Bitmap decodeFile(String url, File f, boolean isScaleByWidth, int widthOrHeight) { Bitmap bitmap = null; try { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // 获取这个图片的宽和高 bitmap = BitmapFactory.decodeFile(f.getPath(), options); // 此时返回bm为空 options.inJustDecodeBounds = false; // 计算缩放比 float scale = 0; if (widthOrHeight != 0) { // if (DEBUG) Log.d(TAG, "make thumbnail"); if (isScaleByWidth) { scale = options.outWidth / (float) widthOrHeight; } else { scale = options.outHeight / (float) widthOrHeight; } } else { // if (DEBUG) Log.d(TAG, "use org"); } if (scale > 1.5 && scale < 2) scale = 2; if (scale <= 1) scale = 1; options.inSampleSize = (int) scale; // 重新读入图片,注意这次要把options.inJustDecodeBounds 设为 false哦 bitmap = BitmapFactory.decodeStream(new FileInputStream(f), null, options); } catch (OutOfMemoryError e) { System.gc(); // cleanCache(); if (bitmap != null) { bitmap = null; } } catch (Exception e) { System.gc(); // cleanCache(); if (bitmap != null) { bitmap = null; } } return bitmap; } public static Bitmap decodeFile(String path, int minSideLength, int maxNumOfPixels) { Bitmap bitmap = null; try { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; BitmapFactory.decodeFile(path,opts); opts.inSampleSize = computeSampleSize(opts, minSideLength, maxNumOfPixels); opts.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeFile(path, opts); }catch(Exception e) { e.printStackTrace(); return null; } return bitmap; } }