package cn.jiguang.imui.commons; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Point; import android.media.ThumbnailUtils; import android.util.Log; import java.io.File; import java.text.NumberFormat; import java.util.List; public class BitmapLoader { public static Bitmap getBitmapFromFile(String path, float density) { BitmapFactory.Options opts = null; int width = (int) (50 * density); int height = (int) (50 * density); if (path != null) { if (width > 0 && height > 0) { opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, opts); final int minSideLength = Math.min(width, height); opts.inSampleSize = computeSampleSize(opts, minSideLength, width * height); opts.inJustDecodeBounds = false; } return BitmapFactory.decodeFile(path, opts); } else return null; } public static Bitmap getBitmapFromFile(String path, int width, int height) { BitmapFactory.Options opts = null; if (path != null) { if (width > 0 && height > 0) { opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, opts); final int minSideLength = Math.min(width, height); opts.inSampleSize = computeSampleSize(opts, minSideLength, width * height); opts.inJustDecodeBounds = false; } return BitmapFactory.decodeFile(path, opts); } else return null; } public static Bitmap compressBySize(String pathName, int targetWidth, int targetHeight) { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true;// 不去真的解析图片,只是获取图片的头部信息,包含宽高等; BitmapFactory.decodeFile(pathName, opts); // 得到图片的宽度、高度; int imgWidth = opts.outWidth; int imgHeight = opts.outHeight; // 分别计算图片宽度、高度与目标宽度、高度的比例;取大于等于该比例的最小整数; int widthRatio = (int) Math.ceil(imgWidth / (float) targetWidth); int heightRatio = (int) Math.ceil(imgHeight / (float) targetHeight); int ratio = 1; if (widthRatio < heightRatio) { ratio = widthRatio; } else { ratio = heightRatio; } if (ratio <= 0) { ratio = 1; } opts.inSampleSize = ratio; // 设置好缩放比例后,加载图片进内容; opts.inJustDecodeBounds = false; Bitmap bitmap = BitmapFactory.decodeFile(pathName, opts); bitmap = ThumbnailUtils.extractThumbnail(bitmap, targetWidth, targetHeight, ThumbnailUtils.OPTIONS_RECYCLE_INPUT); return bitmap; } public static Bitmap getCompressBitmap(String path, int maxWidth, int maxHeight, float density) { Point point = new Point(); BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true;// 不去真的解析图片,只是获取图片的头部信息,包含宽高等; BitmapFactory.decodeFile(path, opts); // 得到图片的宽度、高度; int imgWidth = opts.outWidth; int imgHeight = opts.outHeight; Log.i("BitmapLoader", "Image width: " + imgWidth + " Image Height: " + imgHeight); if (imgWidth <= 50 * density) { point.x = (int) (50 * density); } else if (imgWidth > maxWidth) { point.x = maxWidth; } else { point.x = imgWidth; } if (imgHeight <= 50 * density) { point.y = (int) (50 * density); } else if (imgHeight > maxHeight) { point.y = maxHeight; } else { point.y = imgHeight; } Log.i("BitmapLoader", "x: " + point.x + " y: " + point.y); if (path != null) { final int minSideLength = Math.min(point.x, point.y); opts.inSampleSize = computeSampleSize(opts, minSideLength, point.x * point.y); opts.inJustDecodeBounds = false; return BitmapFactory.decodeFile(path, opts); } else return null; } public static boolean verifyPictureSize(String path) { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, opts); if (opts.outHeight <= 1280 && opts.outWidth <= 720) return true; else return false; } 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 static String getPictureSize(List<String> pathList) { long totalSize = 0; for (String path : pathList) { File file = new File(path); if (file.exists() && file.isFile()) totalSize += file.length(); } NumberFormat ddf1 = NumberFormat.getNumberInstance(); //保留小数点后两位 ddf1.setMaximumFractionDigits(2); double size = totalSize / 1048576.0; return ddf1.format(size) + "M"; } public static Bitmap doBlur(Bitmap sentBitmap, boolean canReuseInBitmap) { // Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com> Bitmap bitmap; int radius = 5; if (canReuseInBitmap) { bitmap = sentBitmap; } else { bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); } int w = bitmap.getWidth(); int h = bitmap.getHeight(); int[] pix = new int[w * h]; bitmap.getPixels(pix, 0, w, 0, 0, w, h); int wm = w - 1; int hm = h - 1; int wh = w * h; int div = radius + radius + 1; int r[] = new int[wh]; int g[] = new int[wh]; int b[] = new int[wh]; int rsum, gsum, bsum, x, y, i, p, yp, yi, yw; int vmin[] = new int[Math.max(w, h)]; int divsum = (div + 1) >> 1; divsum *= divsum; int dv[] = new int[256 * divsum]; for (i = 0; i < 256 * divsum; i++) { dv[i] = (i / divsum); } yw = yi = 0; int[][] stack = new int[div][3]; int stackpointer; int stackstart; int[] sir; int rbs; int r1 = radius + 1; int routsum, goutsum, boutsum; int rinsum, ginsum, binsum; for (y = 0; y < h; y++) { rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; for (i = -radius; i <= radius; i++) { p = pix[yi + Math.min(wm, Math.max(i, 0))]; sir = stack[i + radius]; sir[0] = (p & 0xff0000) >> 16; sir[1] = (p & 0x00ff00) >> 8; sir[2] = (p & 0x0000ff); rbs = r1 - Math.abs(i); rsum += sir[0] * rbs; gsum += sir[1] * rbs; bsum += sir[2] * rbs; if (i > 0) { rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; } else { routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; } } stackpointer = radius; for (x = 0; x < w; x++) { r[yi] = dv[rsum]; g[yi] = dv[gsum]; b[yi] = dv[bsum]; rsum -= routsum; gsum -= goutsum; bsum -= boutsum; stackstart = stackpointer - radius + div; sir = stack[stackstart % div]; routsum -= sir[0]; goutsum -= sir[1]; boutsum -= sir[2]; if (y == 0) { vmin[x] = Math.min(x + radius + 1, wm); } p = pix[yw + vmin[x]]; sir[0] = (p & 0xff0000) >> 16; sir[1] = (p & 0x00ff00) >> 8; sir[2] = (p & 0x0000ff); rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; rsum += rinsum; gsum += ginsum; bsum += binsum; stackpointer = (stackpointer + 1) % div; sir = stack[(stackpointer) % div]; routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; rinsum -= sir[0]; ginsum -= sir[1]; binsum -= sir[2]; yi++; } yw += w; } for (x = 0; x < w; x++) { rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; yp = -radius * w; for (i = -radius; i <= radius; i++) { yi = Math.max(0, yp) + x; sir = stack[i + radius]; sir[0] = r[yi]; sir[1] = g[yi]; sir[2] = b[yi]; rbs = r1 - Math.abs(i); rsum += r[yi] * rbs; gsum += g[yi] * rbs; bsum += b[yi] * rbs; if (i > 0) { rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; } else { routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; } if (i < hm) { yp += w; } } yi = x; stackpointer = radius; for (y = 0; y < h; y++) { // Preserve alpha channel: ( 0xff000000 & pix[yi] ) pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]; rsum -= routsum; gsum -= goutsum; bsum -= boutsum; stackstart = stackpointer - radius + div; sir = stack[stackstart % div]; routsum -= sir[0]; goutsum -= sir[1]; boutsum -= sir[2]; if (x == 0) { vmin[y] = Math.min(y + r1, hm) * w; } p = x + vmin[y]; sir[0] = r[p]; sir[1] = g[p]; sir[2] = b[p]; rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; rsum += rinsum; gsum += ginsum; bsum += binsum; stackpointer = (stackpointer + 1) % div; sir = stack[stackpointer]; routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; rinsum -= sir[0]; ginsum -= sir[1]; binsum -= sir[2]; yi += w; } } bitmap.setPixels(pix, 0, w, 0, 0, w, h); return (bitmap); } public static Bitmap imageCropWithRect(Bitmap bitmap) { if (bitmap == null) { return null; } int w = bitmap.getWidth(); // 得到图片的宽,高 int h = bitmap.getHeight(); int nw, nh, retX, retY; if (w > h) { nw = h / 2; nh = h; retX = (w - nw) / 2; retY = 0; } else { nw = w / 2; nh = (h - w) / 2; retX = w / 4; retY = (int) (h - 0.95 * w); } // 下面这句是关键 Bitmap bmp = Bitmap.createBitmap(bitmap, retX, retY, nw, nh, null, false); if (bitmap != null && !bitmap.equals(bmp) && !bitmap.isRecycled()) { bitmap.recycle(); bitmap = null; } return bmp; } }