栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android Bitmap相关知识点——类型、创建、压缩、转换等

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android Bitmap相关知识点——类型、创建、压缩、转换等

Bitmap
  • 一、Bitmap的存储格式以及内存计算
  • 二、Bitmap的加载
  • 三、Bitmap的压缩方法
    • 1、压缩格式
    • 2、采样率压缩
    • 3、质量压缩
  • 四、Bitmap与Drawable相互转换
  • 五、使用Matrix处理图片

一、Bitmap的存储格式以及内存计算

当需要做性能优化或者防止OOM时,我们通常会使用RGB_565这种类型。
因为ALPHA_8类型的bitmap只有透明度,用处不多。ARGB_4444显示图片不清晰。ARGB_8888占用内存空间最多。

BItmap类型一个像素所占内存
ALPHA_81字节 【8位( A:8)】
RGB_5652字节 【16位(R:5;G:6;B:5)】
ARGB_44442字节【16位( A:4;R:4;G:4;B:4)】
ARGB_88884字节【32位( A:8;R:8;G:8;B:8)】

Bitmap所占内存大小 = 宽度像素 × 高度像素 × 一个像素所占的内存大小。

在Bitmap里有两个获取内存占用大小的方法:

  • getByteCount():API12加入,代表存储Bitmap的像素需要的最少内存。
  • getAllocationByteCount():API19加入,代表在内存中为BItmap分配的内存大小,代替了getByteCount()方法。
二、Bitmap的加载

如何加载一张图片呢?BitmapFactory 类提供了四种方法:decodeFile()、decodeResource()、decodeStream()和decodeByteArray(),分别用于从文件系统、资源、输入流以及字节数组中加载一个Bitmap对象,其中decodeFile和decodeResource又间接调用了decodeStream方法,这四种方法对应着底层实现中相应的native方法。

decodeFile():

BitmapFactory.decodeFile(pathName: String!, opts: BitmapFactory.Options!)

decodeResource():

BitmapFactory.decodeResource(res: Resources!, resId: Int, opts: BitmapFactory.Options!)

decodeStream():

BitmapFactory.decodeStream(is: InputStream?, outPadding: Rect?, opts: BitmapFactory.Options?)

decodeByteArray():

BitmapFactory.decodeByteArray(data: ByteArray!, offset: Int,  length: Int, opts: BitmapFactory.Options!)

BitmapFactory.Options类

上面的四个方法都有一个相同的参数BitmapFactory.Options,这个参数作用很大。
通过这个参数可以对bitmap进行一些配置,例如,设置采样率来减少bitmap的像素,防止OOM。

BitmapFactory.Options类中一些重要的成员变量和方法:
inSampleSize:设置采样率,对图片进行缩放,例如:inSampleSize = 2时,加载出来的图片的宽高分别原来的二分之一,内存大小是原来的四分之一,inSampleSize的值需为2的指数。当设置的值不为2的指数时,系统会自动向下选取一个最接近的2的指数来代替。

outWidth:获取图片的宽度。

outHeight:获取图片的高度。

inJustDecodeBounds:布尔类型,当设置为true时,不获取图片,不分配内存,但可以获得图片的高度(options.outHeight)、宽度(options.outWidth)、MIME类型(options.outMineType)等。

inScreenDensity:获取当前屏幕的像素密度。

三、Bitmap的压缩方法 1、压缩格式

当对图片进行压缩时,有以下三种压缩格式:

CompressFormat描述
Bitmap.CompressFormat.JPEG表示以JPEG压缩算法进行图片压缩,压缩后的格式可以是 .jpg 或者 .jpeg,是一种有损压缩
Bitmap.CompressFormat.PNG表示以PNG压缩算法进行压缩,是一种支持透明度的无损压缩格式
Bitmap.CompressFormat.WEBP是一种支持有损压缩和无损压缩的图片文件格式,无损的webp格式图片体积比无损的png图片小
2、采样率压缩

如何压缩一张图片,使其所占内存变小?首先,最简单的方式就是通过设置采样率来缩小图片的尺寸,减小图片内存占用。
例如,ImageView的大小为100×100像素,而图片的原始大小为200×200,那么只需要将采样率inSampleSize设置为2即可。
如何确定采样率的值,可以通过下面这两个方法来计算得到一个适合的采样率。

fun decodeSampledBitmapFromResource(res: Resources, resId: Int, reqWidth: Int, reqHeight: Int): Bitmap{
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        BitmapFactory.decodeResource(res, resId, options)
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
        options.inJustDecodeBounds = false
        return BitmapFactory.decodeResource(res, resId, options)
    }

    private fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
        val width = options.outWidth
        val height = options.outHeight
        println("width: $width ,height: $height")
        var inSampleSize = 1
        if (width > reqWidth || height > reqHeight) {
            val halfHeight = height / 2
            val halfWidth = width / 2
            while ((halfWidth / inSampleSize) >= reqWidth && (halfHeight / inSampleSize) >= reqHeight){
                inSampleSize *= 2
            }
        }
        println("inSampleSize: $inSampleSize")
        return inSampleSize
    }

这里用的是decodeResource()方法来加载图片,其它三个decode方法也支持采样率加载,并且处理方式也是类似的。
所以,想要通过采样率来高效的加载图片,主要的步骤流程是这样的:

  1. 将BitampFactory.Options的inJustDecodeBounds参数设为true;
  2. 从BitampFactory.Options中取出图片的原始宽高信息,它们对应于outWidth和outHeight参数;
  3. 根据采样率的规则并结合目标View的所需大小计算出采样率inSampleSize;
  4. 将BitampFactory.Options的inJustDecodeBounds参数设置为false,然后重新加载图片。
3、质量压缩

采样率压缩会改变图片的原始尺寸,如果你想压缩图片大小的同时保持原来的图片尺寸,那可以采用下面这种方式来处理。
通过Bitmap对象的compress(format:Bitmap.CompressFormat, quality: Int, stream: OutputStream)方法,不仅可以进行图片质量的压缩,可以设置压缩后图片的格式。方法的第一个参数为压缩后的格式,第二个参数为压缩质量(0~100),100为不压缩图片质量,第三个参数就是要写入的输出流。
注意,如果设置格式为Bitmap.CompressFormat.PNG,那设置压缩质量quality是没有效果的,因为png为无损压缩。

具体使用方法,请看代码:

    fun compressBitmap(bitmap: Bitmap, quality: Int): Bitmap?{
        if (bitmap == null) {
            return null
        }
        var baos: ByteArrayOutputStream? = null
        try {
            baos = ByteArrayOutputStream()
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos)
            val bytes = baos.toByteArray()
            val isBm = ByteArrayInputStream(bytes)
            return BitmapFactory.decodeStream(isBm)
        } catch (e: OutOfMemoryError){
            e.printStackTrace()
        } finally {
            try {
                baos?.close()
            } catch (e: IOException){
                e.printStackTrace()
            }
        }
        return null
    }
四、Bitmap与Drawable相互转换
 
    fun drawableToBitmap(drawable: Drawable): Bitmap{
        // 获取drawable的宽高
        val width = drawable.intrinsicWidth
        val height = drawable.intrinsicHeight
        // 获取drawable的颜色类型
        val config = if(drawable.opacity != PixelFormat.OPAQUE) Bitmap.Config.ARGB_8888 else Bitmap.Config.RGB_565
        // 建立bitmap对象
        val bitmap = createBitmap(width, height, config)
        // 创建对应的画布
        val canvas = Canvas(bitmap)
        drawable.setBounds(0, 0, width, height)
        // 将drawable内容画到画布上
        drawable.draw(canvas)
        return bitmap
    }

    
    fun bitmapToDrawable(resources: Resources, bitmap: Bitmap) = BitmapDrawable(resources, bitmap)
五、使用Matrix处理图片

通过Matrix可以对图片进行缩放、旋转、移动、裁剪等操作。
Matrix提供的一些常用方法

方法名作用
setScale(sx:Float,sy:Float)图片缩放,sx 和sy 为缩放的比例
setRotate(degrees:Float,px:Float,py:FLoat)图片旋转,degrees为角度,px,py为旋转中心点坐标
setTranslate(dx:Float,dy:Float)图片平移,dx 和dy 为移动的距离
setSkew(kx:Float,ky:Float)图片倾斜,kx 和ky 为倾斜比例

使用方式:

    fun scaleBitmap(bitmap: Bitmap): Bitmap{
        val matrix = Matrix()
        matrix.setScale(0.6f, 0.6f)
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
    }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/340841.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号