package com.lqr.wechat.util; import android.app.Activity; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.SystemClock; import android.view.Display; import android.view.WindowManager; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; /** * @创建者 CSDN_LQR * @描述 图像处理工具类 */ public class ImageUtils { private static final String thumbImgDirPath = UIUtils.getContext().getCacheDir().getAbsolutePath(); private static File thumbImgDir; /** * 根据一个网络连接(String)获取bitmap图像 * * @param imageUri * @return */ public static Bitmap getNetBitmap(String imageUri) { // 显示网络上的图片 Bitmap bitmap = null; try { URL myFileUrl = new URL(imageUri); HttpURLConnection conn = (HttpURLConnection) myFileUrl .openConnection(); conn.setDoInput(true); conn.connect(); InputStream is = conn.getInputStream(); bitmap = BitmapFactory.decodeStream(is); is.close(); } catch (OutOfMemoryError e) { e.printStackTrace(); bitmap = null; } catch (IOException e) { e.printStackTrace(); bitmap = null; } return bitmap; } // 图片sd地址 上传服务器时把图片调用下面方法压缩后 保存到临时文件夹 图片压缩后小于100KB,失真度不明显 public static Bitmap revitionImageSize(String path) throws IOException { BufferedInputStream in = new BufferedInputStream(new FileInputStream( new File(path))); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // Bitmap btBitmap=BitmapFactory.decodeFile(path); // System.out.println("原尺寸高度:"+btBitmap.getHeight()); // System.out.println("原尺寸宽度:"+btBitmap.getWidth()); BitmapFactory.decodeStream(in, null, options); in.close(); int i = 0; Bitmap bitmap = null; while (true) { if ((options.outWidth >> i <= 800) && (options.outHeight >> i <= 800)) { in = new BufferedInputStream( new FileInputStream(new File(path))); options.inSampleSize = (int) Math.pow(2.0D, i); options.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeStream(in, null, options); break; } i += 1; } // 当机型为三星时图片翻转 // bitmap = Photo.photoAdapter(path, bitmap); // System.out.println("-----压缩后尺寸高度:" + bitmap.getHeight()); // System.out.println("-----压缩后尺寸宽度度:" + bitmap.getWidth()); return bitmap; } public static Bitmap getLoacalBitmap(String url) { try { FileInputStream fis = new FileInputStream(url); return BitmapFactory.decodeStream(fis); // /把流转化为Bitmap图片 } catch (FileNotFoundException e) { e.printStackTrace(); return null; } } /** * @param x 图像的宽度 * @param y 图像的高度 * @param image 源图片 * @param outerRadiusRat 圆角的大小 * @return 圆角图片 */ public static Bitmap createFramedPhoto(int x, int y, Bitmap image, float outerRadiusRat) { // 根据源文件新建一个darwable对象 Drawable imageDrawable = new BitmapDrawable(image); // 新建一个新的输出图片 Bitmap output = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); // 新建一个矩形 RectF outerRect = new RectF(0, 0, x, y); // 产生一个红色的圆角矩形 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.RED); canvas.drawRoundRect(outerRect, outerRadiusRat, outerRadiusRat, paint); // 将源图片绘制到这个圆角矩形上 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); imageDrawable.setBounds(0, 0, x, y); canvas.saveLayer(outerRect, paint, Canvas.ALL_SAVE_FLAG); imageDrawable.draw(canvas); canvas.restore(); return output; } public static Bitmap zoomForFilePath(Activity context, String filePath) { Bitmap bitmap = BitmapFactory.decodeFile(filePath); BitmapFactory.Options opt = new BitmapFactory.Options(); //这个isjustdecodebounds很重要 opt.inJustDecodeBounds = true; //获取到这个图片的原始宽度和高度 int picWidth = bitmap.getWidth(); int picHeight = bitmap.getHeight(); //获取屏的宽度和高度 WindowManager windowManager = context.getWindowManager(); Display display = windowManager.getDefaultDisplay(); int screenWidth = display.getWidth(); int screenHeight = display.getHeight(); //isSampleSize是表示对图片的缩放程度,比如值为2图片的宽度和高度都变为以前的1/2 opt.inSampleSize = 1; //根据屏的大小和图片大小计算出缩放比例 if (picWidth > picHeight) { if (picWidth > screenWidth) opt.inSampleSize = picWidth / screenWidth; } else { if (picHeight > screenHeight) opt.inSampleSize = picHeight / screenHeight; } //这次再真正地生成一个有像素的,经过缩放了的bitmap opt.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeFile(filePath, opt); return bitmap; } /** * 高斯模糊 */ public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) { Bitmap bitmap; if (canReuseInBitmap) { bitmap = sentBitmap; } else { bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); } if (radius < 1) { return (null); } 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 File genThumbImgFile(String srcImgPath) { if (thumbImgDir == null) thumbImgDir = new File(thumbImgDirPath); if (!thumbImgDir.exists()) thumbImgDir.mkdirs(); String thumbImgName = SystemClock.currentThreadTimeMillis() + FileUtils.getFileNameFromPath(srcImgPath); File imageFileThumb = null; try { // 读取图片。 InputStream is = new FileInputStream(srcImgPath); Bitmap bmpSource = BitmapFactory.decodeStream(is); File imageFileSource = new File(srcImgPath); imageFileSource.createNewFile(); FileOutputStream fosSource = new FileOutputStream(imageFileSource); // 保存原图。 bmpSource.compress(Bitmap.CompressFormat.JPEG, 100, fosSource); // 创建缩略图变换矩阵。 Matrix m = new Matrix(); m.setRectToRect(new RectF(0, 0, bmpSource.getWidth(), bmpSource.getHeight()), new RectF(0, 0, 160, 160), Matrix.ScaleToFit.CENTER); // 生成缩略图。 Bitmap bmpThumb = Bitmap.createBitmap(bmpSource, 0, 0, bmpSource.getWidth(), bmpSource.getHeight(), m, true); imageFileThumb = new File(ImageUtils.thumbImgDirPath, thumbImgName); imageFileThumb.createNewFile(); FileOutputStream fosThumb = new FileOutputStream(imageFileThumb); // 保存缩略图。 bmpThumb.compress(Bitmap.CompressFormat.JPEG, 60, fosThumb); } catch (IOException e) { e.printStackTrace(); } return imageFileThumb; } /** * 获取压缩后的图片 * * @param res * @param resId * @param reqWidth 所需图片压缩尺寸最小宽度 * @param reqHeight 所需图片压缩尺寸最小高度 * @return */ public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { /** * 1.获取图片的像素宽高(不加载图片至内存中,所以不会占用资源) * 2.计算需要压缩的比例 * 3.按将图片用计算出的比例压缩,并加载至内存中使用 */ // 首先不加载图片,仅获取图片尺寸 final BitmapFactory.Options options = new BitmapFactory.Options(); // 当inJustDecodeBounds设为true时,不会加载图片仅获取图片尺寸信息 options.inJustDecodeBounds = true; // 此时仅会将图片信息会保存至options对象内,decode方法不会返回bitmap对象 BitmapFactory.decodeResource(res, resId, options); // 计算压缩比例,如inSampleSize=4时,图片会压缩成原图的1/4 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // 当inJustDecodeBounds设为false时,BitmapFactory.decode...就会返回图片对象了 options.inJustDecodeBounds = false; options.inScaled = false; // 利用计算的比例值获取压缩后的图片对象 return BitmapFactory.decodeResource(res, resId, options); } /** * 计算压缩比例值 * * @param options 解析图片的配置信息 * @param reqWidth 所需图片压缩尺寸最小宽度 * @param reqHeight 所需图片压缩尺寸最小高度 * @return */ public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // 保存图片原宽高值 final int height = options.outHeight; final int width = options.outWidth; // 初始化压缩比例为1 int inSampleSize = 1; // 当图片宽高值任何一个大于所需压缩图片宽高值时,进入循环计算系统 if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // 压缩比例值每次循环两倍增加, // 直到原图宽高值的一半除以压缩值后都~大于所需宽高值为止 while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { inSampleSize *= 2; } } return inSampleSize; } }