Android Glide加载小gif和图片比较模糊

news/2024/11/30 7:33:17/

其实Glide加载还是可以将小图片加载的非常清晰的,

可以通过Glide转换为Bitmap

利用Drawable将setFilterBitmap为true

但是这玩意解决不了GIF。在没有找到库的情况下:我直接自定义view
通过

pl.droidsonroids.gif:android-gif-drawable

获取时间间隔并将gif解析成bitmap获取像素 再通过Choreographer进行页面刷新

/*** GIF支持类 兼容 图片* @author xiaotie https://www.cnblogs.com/xiao-tie/* @time  2023/7/11 15:14* @param widthNum 像素宽* @param heightNum 像素高* @param seekGif 时间戳间隔* @param pos 当前显示位置* @param data 像素数据组*/
data class GifSupport(val widthNum:Int, val heightNum:Int, val seekGif:Long, var pos:Int = 0, val data: MutableList<IntArray>){fun next(){pos++if(pos >= data.size){pos = 0}}
}/*** 以像素点加载gif支持图片默认以宽度为标准(以高度为标准暂时不需要 未开发)* @author xiaotie https://www.cnblogs.com/xiao-tie/* @time  2023/7/11 14:48*/
class GIFView : View, Choreographer.FrameCallback{constructor(context: Context?):super(context)constructor(context: Context?, attrs: AttributeSet?):super(context, attrs)constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int):super(context, attrs, defStyleAttr)private var gifSupport: GifSupport? = nullprivate var size = 0private var margin = 0fprivate val paint = Paint()private val choreographer: Choreographer = Choreographer.getInstance()private var isRendering = false///是否加网格var isGrid = trueset(value) {field = valueinvalidate()}var widthDigit = 16set(value) {field = valuerequestLayout()}var heightDigit = 16set(value) {field = valuerequestLayout()}var path = Path()override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {val measuredWidth = MeasureSpec.getSize(widthMeasureSpec)size = measuredWidth / (gifSupport?.widthNum?:widthDigit)margin = (MeasureSpec.getSize(widthMeasureSpec).toFloat() - size * (gifSupport?.widthNum?:widthDigit)) / 2val measuredHeight = size * (gifSupport?.heightNum?:heightDigit) + margin*2setMeasuredDimension(measuredWidth, measuredHeight.toInt())}override fun onAttachedToWindow() {super.onAttachedToWindow()startRendering()}override fun onDetachedFromWindow() {super.onDetachedFromWindow()stopRendering()}@SuppressLint("DrawAllocation")override fun onDraw(canvas: Canvas?) {super.onDraw(canvas)gifSupport?.apply {paint.reset()for (y in 0 until heightNum){for (x in 0 until widthNum){paint.color = data[pos][x + widthNum*y]val left = margin + x * sizeval top = margin + y * sizecanvas?.drawRect(Rect(left.toInt(), top.toInt(),(left+size).toInt(), (top+size).toInt()),paint)}}if(isGrid){path.reset()for (y in 0 until heightNum){path.moveTo(margin,margin + y * size)path.lineTo(width-margin, margin + y * size)}for (x in 0 until widthNum){path.moveTo(margin + x * size, margin)path.lineTo(margin + x * size, height-margin)}paint.color = Color.parseColor("#66000000")paint.strokeWidth = 1fpaint.style = Paint.Style.STROKEcanvas?.drawPath(path,paint)}}}override fun doFrame(frameTimeNanos: Long) {gifSupport?.next()gifSupport?.let {invalidate() // 强制重绘视图}?: kotlin.run {stopRendering()}if (isRendering) {choreographer.postFrameCallbackDelayed(this, gifSupport?.seekGif?:100) // 每 200 毫秒刷新一次}}private fun startRendering() {if (!isRendering) {isRendering = truechoreographer.postFrameCallback(this)}}private fun stopRendering() {invalidate()if (isRendering) {isRendering = falsechoreographer.removeFrameCallback(this)}}private suspend fun getHttpToStream(url:String) = withContext(Dispatchers.IO) {val client = OkHttpClient()val request: Request = Request.Builder().url(url).build()try {val response = client.newCall(request).execute()response.body!!.byteStream()}catch (e:Exception){e.printStackTrace()null}}private suspend fun getFileToStream(filePath:String) = withContext(Dispatchers.IO) {val file = File(filePath)try {val inputStream = FileInputStream(file) as InputStreaminputStream}catch (e:Exception){e.printStackTrace()null}}/*** 颜色填充* @author xiaotie https://www.cnblogs.com/xiao-tie/* @time  2023/7/12 15:06*/fun setColorData(@ColorInt colorInt: Int) {val colors:IntArray = Array(widthDigit * heightDigit) { colorInt }.toIntArray()gifSupport = GifSupport(widthDigit,heightDigit,10,0, mutableListOf(colors))invalidate()}/*** 资源链接 支持本地链接和图片链接* @author xiaotie https://www.cnblogs.com/xiao-tie/* @time  2023/7/12 15:06*/fun setUrlOrFile(link :String?) {link?:returngifSupport = nullGlobalScope.launch {if(link.contains("http")){getHttpToStream(link)}else{getFileToStream(link)}?.also {if(link.contains(".gif")){val bis = BufferedInputStream(it)val resource =  GifDrawable( bis )val width = resource.intrinsicWidthval height = resource.intrinsicHeightval bitmapsData = mutableListOf<IntArray>()// 将 GIF 每帧的像素数据写入 ByteBufferfor (i in 0 until resource.numberOfFrames) {val frame = resource.seekToFrameAndGet(i)val framePixels = IntArray(width * height)frame.getPixels(framePixels, 0, width, 0, 0, width, height)bitmapsData.add(framePixels)}gifSupport = GifSupport(width,height,resource.duration.toLong()/resource.numberOfFrames, 0,bitmapsData)post {widthDigit = widthheightDigit = height}startRendering()resource.recycle()}else if(link.contains(".png")){val frame = BitmapFactory.decodeStream(it)setBitmap(frame)it.close()}}}}/*** 设置图片* @author xiaotie https://www.cnblogs.com/xiao-tie/* @time  2023/7/13 10:05*/fun setBitmap(frame:Bitmap){val width = frame.widthval height = frame.heightval framePixels = IntArray(width * height)frame.getPixels(framePixels, 0, width, 0, 0, width, height)gifSupport = GifSupport(width,height,10,0, mutableListOf(framePixels))post {widthDigit = widthheightDigit = height}invalidate()}/*** 设置gif数据* @author xiaotie https://www.cnblogs.com/xiao-tie/* @time  2023/7/13 10:06* @param byte Byte数组*/fun setRawGifBytes(byte: ByteArray){val resource =  GifDrawable( byte )val width = resource.intrinsicWidthval height = resource.intrinsicHeightval bitmapsData = mutableListOf<IntArray>()// 将 GIF 每帧的像素数据写入 ByteBufferfor (i in 0 until resource.numberOfFrames) {val frame = resource.seekToFrameAndGet(i)val framePixels = IntArray(width * height)frame.getPixels(framePixels, 0, width, 0, 0, width, height)bitmapsData.add(framePixels)}gifSupport = GifSupport(width,height,resource.duration.toLong()/resource.numberOfFrames, 0,bitmapsData)widthDigit = widthheightDigit = heightstartRendering()resource.recycle()}/*** 设置图片数据* @author xiaotie https://www.cnblogs.com/xiao-tie/* @time  2023/7/13 10:06* @param byte Byte数组*/fun setRawPictureBytes(byte: ByteArray) {val frame = BitmapFactory.decodeByteArray(byte,0,byte.size)setBitmap(frame)}
}

http://www.ppmy.cn/news/888629.html

相关文章

Nuxt.js--》解密Nuxt.js:构建优雅、高效的现代化Vue.js应用

博主今天开设Nuxt.js专栏&#xff0c;带您深入探索 Nuxt.js 的精髓&#xff0c;学习如何利用其强大功能构建出色的前端应用程序。我们将探讨其核心特点、灵活的路由系统、优化技巧以及常见问题的解决方案。无论您是想了解 Nuxt.js 的基础知识&#xff0c;还是希望掌握进阶技巧&…

大前端学习-Get请求和Post请求的区别

常见的HTTP请求方式有&#xff1a; 1、GET: 请求指定的页面信息&#xff0c;并返回实体主体 2、POST&#xff1a;向指定资源提交数据进行处理请求&#xff08;例如提交表单或者上传文件&#xff09; 3、HEAD&#xff1a;类似于Get请求&#xff0c;返回的响应中没有内容 4、…

C++之final关键字用法(一百六十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

springboot与rabbitmq的整合【演示5种基本交换机】

前言&#xff1a; &#x1f44f;作者简介&#xff1a;我是笑霸final&#xff0c;一名热爱技术的在校学生。 &#x1f4dd;个人主页&#xff1a;个人主页1 || 笑霸final的主页2 &#x1f4d5;系列专栏&#xff1a;后端专栏 &#x1f4e7;如果文章知识点有错误的地方&#xff0c;…

DEVC++伪3D小游戏丧尸城市

//类型&#xff1a;开放世界/丧尸/生存 //地图大小&#xff1a;18*18 //实际大小(除去建筑)&#xff1a;318 #include<algorithm> #include<fstream> #include<iostream> #include<stdio.h> #include<cstdio> #include<iostream> #include…

手柄映射软件_生化危机3该用哪款游戏手柄?北通宙斯给你四维游戏体验

4月3日&#xff0c;生化危机3&#xff1a;重制版重磅上线&#xff0c;不少玩家提出&#xff0c;此作十分适合手柄操作&#xff0c;通过一款好手柄&#xff0c;体验可以达到前所未有的高度。然而,目前手柄市场品种繁多,质量也参差不齐&#xff0c;稍一不慎便会花钱买教训。那么怎…

自创文字小游戏《人类末日·丧尸危机》

这个游戏有很多坑哦&#xff0c;其他就没什么要注意的啦。 你不要以为你以为的就是对的&#xff01; 有些关卡不能通关纯属运气&#xff01;&#xff01;&#xff01;最多10次就可以通关啦&#xff01;&#xff01;&#xff01; 代码在哪里&#xff1f; #include <bits/…

Android Vector(矢量图)介绍

Android Vector(矢量图)介绍 1、vector的宽高属性 <vector xmlns:android"http://schemas.android.com/apk/res/android"android:width"24dp"android:height"24dp"android:viewportWidth"24"android:viewportHeight"24"…