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;
}
}