开发中图片加载是个问题,我们图片加载通常使用Glide来进行加载,因为Glide可以实现图片的三级缓存,比较简单
的工具类在图片的加载上省去很多开发中不必要的工作。
功能如下:
1:无加载中的图片。
2:获取图片的旋转角度。
3:将图片按照某个角度进行旋转。
4:通过uri获取图片并进行压缩。
5:获取HTML中的图片src地址。
6:保存图片到本地。
7:创建图片file对象。
工具类封装如下:
/**
* Created by AndyYuan317 on 2020/7/27.
* 图片加载工具类
*/
public class ImageUtil {
/**
* 无加载中图片
*
* @param context
* @param imageView
* @param url
*/
public static void loadNotPlace(Context context, ImageView imageView, String url) {
if (TextUtils.isEmpty(url)) {
imageView.setImageResource(R.drawable.ic_placeholder);
return;
}
if (url.length() > 3 && "gif".equals(url.substring(url.length() - 3, url.length()))) {
Glide.with(context)
.load(url)
.asGif()
.error(R.drawable.ic_placeholder)
.dontAnimate()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
} else {
Glide.with(context)
.load(url)
.error(R.drawable.ic_placeholder)
.dontAnimate()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
}
}
@SuppressLint("NewApi")
public static void load(Context context, ImageView imageView, String url) {
if (TextUtils.isEmpty(url)) {
imageView.setImageResource(R.drawable.ic_placeholder);
return;
}
if (url.length() > 3 && "gif".equals(url.substring(url.length() - 3, url.length()))) {
Glide.with(context)
.load(url)
.asGif()
.placeholder(R.drawable.ic_placeholder)
.error(R.drawable.ic_placeholder)
.dontAnimate()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
} else if(!((Activity)context).isFinishing() && !((Activity)context).isDestroyed()){
Glide.with(context)
.load(url)
.placeholder(R.drawable.ic_placeholder)
.error(R.drawable.ic_placeholder)
.dontAnimate()
.skipMemoryCache(true)
.into(imageView);
}
}
public static void loadBitmap(Context context, final ImageView imageView, String url, RequestListener<String, Bitmap> listener){
if (TextUtils.isEmpty(url)) {
imageView.setImageResource(R.drawable.ic_placeholder);
return;
}
Glide.with(context)
.load(url)
.asBitmap()
.listener(listener)
.placeholder(R.drawable.ic_placeholder)
.error(R.drawable.ic_placeholder)
//.override(640, 360)
.dontAnimate().preload();
//.into(imageView);
}
public static void loadFixSize(Context context, ImageView imageView, String url) {
if (TextUtils.isEmpty(url)) {
imageView.setImageResource(R.drawable.ic_placeholder);
return;
}
if (url.length() > 3 && "gif".equals(url.substring(url.length() - 3, url.length()))) {
Glide.with(context)
.load(url)
.asGif()
.placeholder(R.drawable.ic_placeholder)
.error(R.drawable.ic_placeholder)
.dontAnimate()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
} else {
Glide.with(context)
.load(url)
.placeholder(R.drawable.ic_placeholder)
.error(R.drawable.ic_placeholder)
.override(640, 360)
.dontAnimate()
.into(imageView);
}
}
public static void load(Fragment fragment, ImageView imageView, String url) {
if (TextUtils.isEmpty(url)) {
imageView.setImageResource(R.drawable.ic_placeholder);
return;
}
if (url.length() > 3 && "gif".equals(url.substring(url.length() - 3, url.length()))) {
Glide.with(fragment)
.load(url)
.asGif()
.placeholder(R.drawable.ic_placeholder)
.error(R.drawable.ic_placeholder)
.dontAnimate()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
} else {
Glide.with(fragment)
.load(url)
.placeholder(R.drawable.ic_placeholder)
.error(R.drawable.ic_placeholder)
.dontAnimate()
.into(imageView);
}
}
public static void loadLocalFile(Context context, ImageView imageView, String url) {
if (TextUtils.isEmpty(url)) {
imageView.setImageResource(R.drawable.ic_placeholder);
return;
}
Glide.with(context)
.load(new File(url))
.placeholder(R.drawable.ic_placeholder)
.error(R.drawable.ic_placeholder)
.dontAnimate()
.into(imageView);
}
/**
* 加载头像
*
* @param context
* @param imageView
* @param url
*/
public static void loadAvator(Context context, ImageView imageView, String url) {
// if (TextUtils.isEmpty(url)) {
// imageView.setImageResource(R.drawable.ic_avator);
// return;
// }
Glide.with(context)
.load(url)
.placeholder(R.drawable.ic_avator)
.error(R.drawable.ic_avator)
.dontAnimate()
.into(imageView);
}
/**
* 读取图片的旋转的角度
*
* @param path 图片绝对路径
* @return 图片的旋转角度
*/
public static int getBitmapDegree(String path) {
int degree = 0;
try {
// 从指定路径下读取图片,并获取其EXIF信息
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 bm 需要旋转的图片
* @param degree 旋转角度
* @return 旋转后的图片
*/
public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
Bitmap returnBm = null;
// 根据旋转角度,生成旋转矩阵
Matrix matrix = new Matrix();
matrix.postRotate(degree);
try {
// 将原始图片按照旋转矩阵进行旋转,并得到新的图片
returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
} catch (OutOfMemoryError e) {
}
if (returnBm == null) {
returnBm = bm;
}
if (bm != returnBm) {
bm.recycle();
}
return returnBm;
}
/**
* 通过uri获取图片并进行压缩
*
* @param uri
*/
public static Bitmap getBitmapFormUri(Activity ac, Uri uri, float width, float height, int maxSize) throws FileNotFoundException, IOException {
InputStream input = ac.getContentResolver().openInputStream(uri);
BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
onlyBoundsOptions.inJustDecodeBounds = true;
onlyBoundsOptions.inDither = true;//optional
onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
input.close();
int originalWidth = onlyBoundsOptions.outWidth;
int originalHeight = onlyBoundsOptions.outHeight;
if ((originalWidth == -1) || (originalHeight == -1))
return null;
//图片分辨率以480x800为标准
float hh = height == 0 ? 800f : height;//这里设置高度为800f
float ww = width == 0 ? 480f : width;//这里设置宽度为480f
//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int be = 1;//be=1表示不缩放
if (originalWidth > originalHeight && originalWidth > ww) {//如果宽度大的话根据宽度固定大小缩放
be = (int) (originalWidth / ww);
} else if (originalWidth < originalHeight && originalHeight > hh) {//如果高度高的话根据宽度固定大小缩放
be = (int) (originalHeight / hh);
}
if (be <= 0)
be = 1;
//比例压缩
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inSampleSize = be;//设置缩放比例
bitmapOptions.inDither = true;//optional
bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
input = ac.getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
input.close();
return compressImage(bitmap, maxSize);//再进行质量压缩
}
/**
* 质量压缩方法
*
* @param image
* @return
*/
public static Bitmap compressImage(Bitmap image, int maxSize) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 100;
while (baos.toByteArray().length / 1024 > maxSize) { //循环判断如果压缩后图片是否大于200kb,大于继续压缩
baos.reset();//重置baos即清空baos
//第一个参数 :图片格式 ,第二个参数: 图片质量,100为最高,0为最差 ,第三个参数:保存压缩后的数据的流
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;
}
/**
* 获取html中的src地址
*
* @param htmlStr
* @return
*/
public static List<String> getImgStr(String htmlStr) {
List<String> pics = new ArrayList<>();
String img = "";
Pattern p_image;
Matcher m_image;
String regEx_img = "]*?>" ;
p_image = Pattern.compile(regEx_img, Pattern.CASE_INSENSITIVE);
m_image = p_image.matcher(htmlStr);
while (m_image.find()) {
// 得到数据
img = m_image.group();
// 匹配中的src数据
Matcher m = Pattern.compile("src\\s*=\\s*\"?(.*?)(\"|>|\\s+)").matcher(img);
while (m.find()) {
pics.add(m.group(1));
}
}
return pics;
}
public static Observable<String> observableSaveImageToExternal(final Context context, final Bitmap cropBitmap) {
return Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext(saveImageToExternal(context, cropBitmap, createImageFile()));
subscriber.onCompleted();
}
});
}
public static Observable<File> observableImagePath(final File file){
return Observable.create(new Observable.OnSubscribe<File>() {
@Override
public void call(Subscriber<? super File> subscriber) {
subscriber.onNext(file);
subscriber.onCompleted();
}
});
}
/**
* 保存图片到本地
*
* @param bm
* @return
*/
public static String saveImageToExternal(Context context, Bitmap bm, File imageFile) {
try {
FileOutputStream out = new FileOutputStream(imageFile);
bm.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
//TODO 还不能马上刷新
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(imageFile);
mediaScanIntent.setData(contentUri);
context.sendBroadcast(mediaScanIntent);
} else {
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + imageFile.getAbsoluteFile())));
}
if (imageFile.exists()) {
return imageFile.getAbsolutePath();
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 创建图片File对象
*
* @return
*/
public static File createImageFile() {
File imageFile = null;
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
try {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES + "/PudongNews");
path.mkdirs();
imageFile = File.createTempFile(timeStamp, ".jpg", path);
} else {
imageFile = File.createTempFile(timeStamp, ".jpg", App.getInstance().getExternalFilesDir(null));
}
} catch (IOException e) {
e.printStackTrace();
}
return imageFile;
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float) height / (float) reqHeight);
} else {
inSampleSize = Math.round((float) width / (float) reqWidth);
}
return inSampleSize + 1;
}
return inSampleSize;
}
public static Bitmap decodeImage(String path, int showWidth, int showHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
options.inJustDecodeBounds = false;
if (showWidth != 0 && showHeight != 0)
options.inSampleSize = calculateInSampleSize(options, showWidth,
showHeight);
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
return BitmapFactory.decodeFile(path, options);
}
public static ByteArrayOutputStream getSmallBitmap(String filePath) {
Bitmap bm = decodeImage(filePath, 600, 800);
long fileLength = new File(filePath).length();
int scale = 60;
if (fileLength > 2097152)
scale = 20;
if (fileLength <= 2097152 && fileLength > 1572864)
scale = 40;
if (fileLength <= 1572864 && fileLength > 1048576)
scale = 60;
if (fileLength <= 1048576 && fileLength > 524288)
scale = 70;
if (fileLength <= 524288 && fileLength > 262144)
scale = 80;
if (fileLength <= 262144)
scale = 60;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (filePath.endsWith(".jpg") || filePath.endsWith(".JPG"))
bm.compress(Bitmap.CompressFormat.JPEG, scale, baos);
if (filePath.endsWith(".jpeg") || filePath.endsWith(".JPEG"))
bm.compress(Bitmap.CompressFormat.JPEG, scale, baos);
if (filePath.endsWith(".png") || filePath.endsWith(".PNG"))
bm.compress(Bitmap.CompressFormat.JPEG, scale, baos);
return baos;
}
public static ByteArrayOutputStream getBitmapStream(String filePath){
Bitmap bmp = decodeImage(filePath, 0, 0);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos);
return baos;
}
}