package com.xscm.moduleutil.utils;
import static android.view.View.GONE;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.blankj.utilcode.util.ConvertUtils;
import com.blankj.utilcode.util.Utils;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.request.FutureTarget;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;
import com.bumptech.glide.signature.ObjectKey;
import com.opensource.svgaplayer.SVGADrawable;
import com.opensource.svgaplayer.SVGAImageView;
import com.opensource.svgaplayer.SVGAParser;
import com.opensource.svgaplayer.SVGAVideoEntity;
import com.xscm.moduleutil.R;
import com.xscm.moduleutil.utils.logger.Logger;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
/**
*
图片加载工具类
*
* @name ImageUtils
*/
public class ImageUtils {
public static final int ANIM = -1;
/**
* 默认加载
*/
public static void loadImageView(String path, ImageView mImageView) {
Glide.with(mImageView).load(path).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
}
/**
* 默认加载
*/
public static void loadIcon(String path, ImageView mImageView) {
mImageView.setVisibility(TextUtils.isEmpty(path) ? GONE : View.VISIBLE);
Glide.with(mImageView).load(path).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
}
/**
* 加载爵位动图
*/
public static void loadVipWebp(String path, ImageView mImageView) {
loadSample(path, mImageView, ConvertUtils.dp2px(200), ConvertUtils.dp2px(200));
}
/**
* 采样
*
* @param path
* @param mImageView
* @param width
* @param height
*/
public static void loadSample(String path, ImageView mImageView, int width, int height) {
RequestOptions options = new RequestOptions().override(width, height).diskCacheStrategy(DiskCacheStrategy.ALL);
Glide.with(mImageView).load(path).apply(options).into(mImageView);
}
/**
* 默认加载
*/
public static void loadDecorationAvatar(String path, SVGAImageView mImageView) {
if (path.endsWith(".svga")) {
try {
SVGAParser.Companion.shareParser().decodeFromURL(new URL(path), new SVGAParser.ParseCompletion() {
@Override
public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) {
if (mImageView != null) {
SVGADrawable svgaDrawable = new SVGADrawable(svgaVideoEntity);
mImageView.setImageDrawable(svgaDrawable);
mImageView.startAnimation();
}
}
@Override
public void onError() {
Logger.e("loadDecorationAvatar error");
}
});
} catch (MalformedURLException e) {
e.printStackTrace();
}
} else {
if (mImageView.isAnimating()) {
mImageView.stopAnimation();
}
Glide.with(mImageView).load(path).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
}
}
private static Map svgaCache = new HashMap<>();
// TODO: 2025/8/22 播放svga
public static void loadDecorationAvatar2(int resourceId, SVGAImageView mImageView) {
// 从资源文件夹加载SVGA文件
if (resourceId != 0) {
// 检查缓存
SVGAVideoEntity cachedEntity = svgaCache.get(resourceId);
if (cachedEntity != null) {
// 使用缓存的实体
SVGADrawable svgaDrawable = new SVGADrawable(cachedEntity);
mImageView.setImageDrawable(svgaDrawable);
mImageView.startAnimation();
return;
}
try {
// 没有缓存,正常加载
SVGAParser parser = SVGAParser.Companion.shareParser();
InputStream inputStream = mImageView.getContext().getResources().openRawResource(resourceId);
parser.decodeFromAssets("heart_line_31.svga", new SVGAParser.ParseCompletion() {
@Override
public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) {
if (mImageView != null) {
// 缓存实体
svgaCache.put(resourceId, svgaVideoEntity);
SVGADrawable svgaDrawable = new SVGADrawable(svgaVideoEntity);
mImageView.setImageDrawable(svgaDrawable);
mImageView.startAnimation();
}
}
@Override
public void onError() {
Logger.e("loadDecorationAvatar2 error, resourceId: " + resourceId);
}
});
} catch (Exception e) {
Logger.e("loadDecorationAvatar2 exception, resourceId: " + resourceId, e);
}
} else {
Logger.e("Resource ID is 0 or invalid");
}
}
public static void loadHeadCC(String path, ImageView mImageView) {
Glide.with(mImageView).load(path).error(R.mipmap.default_avatar).placeholder(R.mipmap.default_avatar).centerCrop().diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
}
public static void loadCompressImg(String path, ImageView mImageView, int width, int height) {
Glide.with(mImageView)
.load(path)
.centerCrop()
.override(width, height).diskCacheStrategy(DiskCacheStrategy.ALL)
.into(mImageView);
}
public static void loadCenterCrop(String path, ImageView mImageView) {
Glide.with(mImageView).load(path).centerCrop().diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
}
public static void loadRes(int path, ImageView mImageView) {
Glide.with(mImageView).load(path).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
}
/**
* 加载图片(优先使用本地缓存,无缓存则下载)
*
* @param context 上下文
* @param url 图片 URL
* @param imageView 目标 ImageView
*/
public static void loadImageWithCache(Context context, String url, ImageView imageView) {
if (TextUtils.isEmpty(url)) return;
// 去掉动态参数,提取稳定 URL
String stableUrl = url.split("\\?")[0];
String signature = Md5Utils.getMD5String(stableUrl); // 使用 MD5 生成唯一签名
// Glide 加载配置
Glide.with(context)
.load(stableUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL) // 缓存所有版本
.signature(new ObjectKey(signature)) // 使用签名确保缓存一致
.placeholder(R.mipmap.room_bj) // 加载中占位图
.error(R.mipmap.room_bj) // 加载失败占位图
.centerCrop()
.into(imageView);
}
public static boolean isImageCached(Context context, String url) {
FutureTarget future = Glide.with(context)
.downloadOnly()
.load(url)
.submit();
try {
File cacheFile = future.get();
return cacheFile != null && cacheFile.exists();
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public static void loadImageBlurBg(String url, ImageView imageView) {
RequestOptions options = new RequestOptions().centerCrop().placeholder(R.mipmap.room_bg).error(R.mipmap.room_bg).diskCacheStrategy(DiskCacheStrategy.ALL);
Glide.with(imageView).asBitmap().apply(options).load(url).into(new SimpleTarget(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition super Bitmap> transition) {
try {
Drawable foregroundDrawable = FastBlurUtil.getForegroundDrawable(resource);
imageView.setImageDrawable(foregroundDrawable);
} catch (Exception e) {
imageView.setImageResource(R.mipmap.room_bg);
}
}
});
}
public static void loadCoverBlurBg(Context context, String url, LinearLayout linearLayout) {
RequestOptions options = new RequestOptions().centerCrop().placeholder(R.mipmap.default_avatar).error(R.mipmap.default_avatar).diskCacheStrategy(DiskCacheStrategy.ALL);
Glide.with(context).asBitmap().apply(options).load(url).into(new SimpleTarget(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition super Bitmap> transition) {
try {
setUpCoverBg(linearLayout, resource);
} catch (Exception e) {
linearLayout.setBackgroundResource(R.mipmap.index_bg_hot);
}
}
});
}
private static void setUpCoverBg(LinearLayout linearLayout, Bitmap resource) {
// Palette.from(resource).generate(new Palette.PaletteAsyncListener() {
// @Override
// public void onGenerated(Palette palette) {
// //记得判空
// if (palette == null) return;
// //palette取色不一定取得到某些特定的颜色,这里通过取多种颜色来避免取不到颜色的情况
// if (palette.getDarkVibrantColor(Color.TRANSPARENT) != Color.TRANSPARENT) {
// createLinearGradientBitmap(linearLayout, resource, palette.getDarkVibrantColor(Color.TRANSPARENT), palette.getVibrantColor(Color.TRANSPARENT));
// } else if (palette.getDarkMutedColor(Color.TRANSPARENT) != Color.TRANSPARENT) {
// createLinearGradientBitmap(linearLayout, resource, palette.getDarkMutedColor(Color.TRANSPARENT), palette.getMutedColor(Color.TRANSPARENT));
// } else {
// createLinearGradientBitmap(linearLayout, resource, palette.getLightMutedColor(Color.TRANSPARENT), palette.getLightVibrantColor(Color.TRANSPARENT));
// }
// }
// });
}
//创建线性渐变背景色
private static void createLinearGradientBitmap(LinearLayout ivBg, Bitmap bgBitmap, int darkColor, int color) {
int bgColors[] = new int[2];
bgColors[0] = darkColor;
bgColors[1] = color;
if (bgBitmap == null) {
bgBitmap = Bitmap.createBitmap(ivBg.getWidth(), ivBg.getHeight(), Bitmap.Config.ARGB_4444);
}
Canvas mCanvas = new Canvas();
Paint mPaint = new Paint();
mCanvas.setBitmap(bgBitmap);
mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
LinearGradient gradient = new LinearGradient(0, 0, 0, bgBitmap.getHeight(), bgColors[0], bgColors[1], Shader.TileMode.CLAMP);
mPaint.setShader(gradient);
RectF rectF = new RectF(0, 0, bgBitmap.getWidth(), bgBitmap.getHeight());
mCanvas.drawRoundRect(rectF, 16, 16, mPaint);
// mCanvas.drawRect(rectF, mPaint);
ivBg.setBackground(new BitmapDrawable(bgBitmap));
}
public static void loadRoomBg(String url, ImageView imageView) {
RequestOptions options = new RequestOptions().centerCrop().placeholder(R.mipmap.room_bg).error(R.mipmap.room_bg).diskCacheStrategy(DiskCacheStrategy.ALL);
Glide.with(imageView).load(url).apply(options).into(imageView);
}
/**
* 设置加载中以及加载失败图片
*/
public static void loadImageWithLoading(String path, ImageView mImageView, int lodingImage, int errorRes) {
Glide.with(mImageView).load(path).placeholder(lodingImage).
error(errorRes).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
}
/**
* 加载为bitmap
*
* @param path 图片地址
* @param listener 回调
*/
public static void loadBitmap(String path, final onLoadBitmap listener) {
Glide.with(Utils.getApp()).asBitmap().load(path).into(new SimpleTarget() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition super Bitmap> transition) {
listener.onReady(resource);
}
});
}
public static void loadGift(ImageView view, int res) {
if (res == ANIM) {
try {
AnimationDrawable background = (AnimationDrawable) view.getBackground();
if (background != null) {
background.start();
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
Glide.with(view.getContext()).asGif().load(res).into(view);
}
}
public static void loadIconByHeight(String path, ImageView mImageView) {
mImageView.setVisibility(TextUtils.isEmpty(path) ? GONE : View.VISIBLE);
Glide.with(mImageView).load(path).diskCacheStrategy(DiskCacheStrategy.ALL).into(new SimpleTarget() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition super Drawable> transition) {
mImageView.setImageDrawable(resource);
ViewGroup.LayoutParams layoutParams = mImageView.getLayoutParams();
layoutParams.width = (int) (layoutParams.height * 1f / resource.getIntrinsicHeight() * resource.getIntrinsicWidth());
mImageView.setLayoutParams(layoutParams);
}
});
}
public static void loadIconByHeight1(String path, ImageView mImageView,int height) {
mImageView.setVisibility(TextUtils.isEmpty(path) ? GONE : View.VISIBLE);
Glide.with(mImageView).load(path).diskCacheStrategy(DiskCacheStrategy.ALL).into(new SimpleTarget() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition super Drawable> transition) {
mImageView.setImageDrawable(resource);
ViewGroup.LayoutParams layoutParams = mImageView.getLayoutParams();
layoutParams.width = (int) (layoutParams.height * 1f / resource.getIntrinsicHeight() * resource.getIntrinsicWidth());
layoutParams.height = height;
mImageView.setLayoutParams(layoutParams);
}
});
}
/**
* 加载网络图片并高斯模糊,失败时加载默认图片并同样模糊
*/
public static void loadBlurredImageWithDefault(String url, ImageView imageView, int defaultResId, int radius) {
if (imageView == null) return;
Glide.with(imageView.getContext())
.asBitmap()
.load(url)
.error(defaultResId) // 加载失败时显示默认图片
.into(new SimpleTarget() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition super Bitmap> transition) {
// 对网络图或默认图都进行模糊处理
Bitmap blurred = com.blankj.utilcode.util.ImageUtils.stackBlur(resource, radius);
imageView.setImageBitmap(blurred);
}
@Override
public void onLoadFailed(@Nullable Drawable errorDrawable) {
// 如果 errorDrawable 不为空,也可以直接用它生成 Bitmap
if (errorDrawable instanceof BitmapDrawable) {
Bitmap bitmap = ((BitmapDrawable) errorDrawable).getBitmap();
Bitmap blurred = com.blankj.utilcode.util.ImageUtils.stackBlur(bitmap, radius);
imageView.setImageBitmap(blurred);
} else {
// 如果不是 BitmapDrawable,尝试从资源中加载 Bitmap
Bitmap defaultBitmap = BitmapFactory.decodeResource(imageView.getResources(), defaultResId);
if (defaultBitmap != null) {
Bitmap blurred = com.blankj.utilcode.util.ImageUtils.stackBlur(defaultBitmap, radius);
imageView.setImageBitmap(blurred);
}
}
}
});
}
/**
* 加载bitmap回调
*/
public interface onLoadBitmap {
void onReady(Bitmap resource);
}
public static void loadOneTimeGif(Context context, Object model, final ImageView imageView) {
Glide.with(context).asGif().load(model).listener(new RequestListener() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(GifDrawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) {
try {
Field gifStateField = GifDrawable.class.getDeclaredField("state");
gifStateField.setAccessible(true);
Class gifStateClass = Class.forName("com.bumptech.glide.load.resource.gif.GifDrawable$GifState");
Field gifFrameLoaderField = gifStateClass.getDeclaredField("frameLoader");
gifFrameLoaderField.setAccessible(true);
Class gifFrameLoaderClass = Class.forName("com.bumptech.glide.load.resource.gif.GifFrameLoader");
Field gifDecoderField = gifFrameLoaderClass.getDeclaredField("gifDecoder");
gifDecoderField.setAccessible(true);
Class gifDecoderClass = Class.forName("com.bumptech.glide.gifdecoder.GifDecoder");
Object gifDecoder = gifDecoderField.get(gifFrameLoaderField.get(gifStateField.get(resource)));
Method getDelayMethod = gifDecoderClass.getDeclaredMethod("getDelay", int.class);
getDelayMethod.setAccessible(true);
//设置只播放一次
resource.setLoopCount(1);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return false;
}
}).into(imageView);
}
// public static String getImagePath() {
// String path = Constants.IMAGE_PATH;
// File file = new File(path);
// if (file.mkdirs()) {
// return path;
// } else {
// return path;
// }
// }
public static String getUrl(String url) {
// url = EncodeUtils.htmlDecode(url).toString();
// if (!TextUtils.isEmpty(url) && !url.contains("http"))
// url = BuildConfig.BASE_URL + url;
return url;
}
public static void preload(String url) {
// Glide.with(BaseApplication.getInstance()).download(url).preload();
}
public static void preloadImgConstants() {
// try {
// ImgConstants constants = new ImgConstants();
// Field[] fields = ImgConstants.class.getDeclaredFields();
// for (Field field : fields) {
// preload(field.get(constants).toString());
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
}
/**
* 将 assets 中的文件复制到指定路径
*
* @param assetName assets 中的文件名,例如:"my_file.txt"
* @param savePath 要保存的目录路径,例如:"/data/data/your.package/files/"
* @param saveName 保存后的文件名
*/
public static void copyAssetToFile(String assetName, String savePath, String saveName) {
InputStream myInput = null;
FileOutputStream myOutput = null;
try {
// 打开 assets 中的文件输入流
myInput = Utils.getApp().getAssets().open(assetName);
// 创建目标目录(如果不存在)
File dir = new File(savePath);
if (!dir.exists()) {
dir.mkdirs();
}
// 创建目标文件
File outFile = new File(savePath + saveName);
if (outFile.exists()) {
outFile.delete(); // 如果已存在,先删除
}
// 创建输出流
myOutput = new FileOutputStream(outFile);
// 缓冲区读写
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
// 刷新输出流
myOutput.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭流
try {
if (myInput != null) {
myInput.close();
}
if (myOutput != null) {
myOutput.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void clearDiskCache(Context context){
Glide.get(context).clearDiskCache();
}
}