方法列表
id2Bitmap :获取资源图片的 Bitmapstring2Bitmap :string -> bitmap 通过 Base64 实现bitmap2String :bitmap -> string 通过 Base64实现bytes2Bitmap :把byte字节流转成bitmapbitmap2Bytes :把bitmap转成byte字节流drawable2Bitmap :drawable 转 bitmapdrawable2Bitmap2:drawable 转 bitmapbitmap2Drawable :bitmap -> drawableword2Bitmap :根据文字获取图片bitmap2Round :获取圆角图片bitmap2Semicircle:bitmap -> semicircle(半圆)uri2Bitmap :uri -> bitmapview2Bitmap2 :通过 View 获取 bitmap,view绘制出来后才行view2Bitmap :单个View 参数,绘制已经测量过的View,已经显示在界面上,要等控件可以获取到宽高后才行view2Bitmap :先测量和布局,再生成Bitmap, 没有显示在界面上,针对不可见 View,可以 View 也可以使用zoomImage :图片的缩放方法,尺寸压缩compressPathSize:压缩文件读取图片的尺寸大小compressBitmap :质量压缩方法compressPathFileSize:压缩图片的内存大小,使文件占据更小的空间saveFile :保存Bitmap图片为本地文件
完整代码
object BitmapUtils { /** * 获取资源图片的 Bitmap */ fun id2Bitmap(resId: Int): Bitmap? { var bitmap: Bitmap? = null if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { val vectorDrawable: Drawable = getContext().getDrawable(resId) ?: return bitmap bitmap = Bitmap.createBitmap( vectorDrawable.intrinsicWidth, vectorDrawable.intrinsicHeight, Bitmap.Config.ARGB_8888 ) val canvas = Canvas(bitmap!!) vectorDrawable.setBounds(0, 0, canvas.width, canvas.height) vectorDrawable.draw(canvas) } else { bitmap = BitmapFactory.decodeResource(getResources(), resId) } return bitmap } /** * string -> bitmap 通过 Base64 实现 * * @param string * @return */ fun string2Bitmap(string: String?): Bitmap? {// 将字符串转换成Bitmap类型 var bitmap: Bitmap? = null try { val bitmapArray: ByteArray = Base64.decode(string, Base64.DEFAULT) bitmap = BitmapFactory.decodeByteArray( bitmapArray, 0, bitmapArray.size ) } catch (e: Exception) { e.printStackTrace() } return bitmap } /** * bitmap -> string 通过 Base64实现 * * @param bitmap * @return */ fun bitmap2String(bitmap: Bitmap): String? {//将Bitmap转换成字符串 var string: String? = null val bStream = ByteArrayOutputStream() bitmap.compress(CompressFormat.PNG, 100, bStream) val bytes = bStream.toByteArray() string = Base64.encodeToString(bytes, Base64.DEFAULT) return string } /** * 把byte字节流转成bitmap * @param bytes */ fun bytes2Bitmap(bytes: ByteArray): Bitmap? { val opts = BitmapFactory.Options() opts.inJustDecodeBounds = false //为true时,返回的bitmap为null return BitmapFactory.decodeByteArray(bytes, 0, bytes.size, opts) } /** * 把bitmap转成byte字节流 * @param bm */ fun bitmap2Bytes(bm: Bitmap): ByteArray { val baos = ByteArrayOutputStream() bm.compress(Bitmap.CompressFormat.PNG, 100, baos) return baos.toByteArray() } /** * drawable 转 bitmap * * @param drawable * @return */ fun drawable2Bitmap(drawable: Drawable): Bitmap { val bd = drawable as BitmapDrawable return bd.bitmap } /** * drawable 转 bitmap * * @param drawable * @return */ fun drawable2Bitmap2(drawable: Drawable): Bitmap { // 取 drawable 的长宽 val w = drawable.intrinsicWidth val h = drawable.intrinsicHeight // 取 drawable 的颜色格式 val config = if (drawable.opacity != PixelFormat.OPAQUE) Bitmap.Config.ARGB_8888 else Bitmap.Config.RGB_565 // 建立对应 bitmap val bitmap = Bitmap.createBitmap(w, h, config) // 建立对应 bitmap 的画布 val canvas = Canvas(bitmap) drawable.setBounds(0, 0, w, h) // 把 drawable 内容画到画布中 drawable.draw(canvas) return bitmap } /** * bitmap -> drawable * * @param bitmap * @return */ fun bitmap2Drawable(bitmap: Bitmap): Drawable { val drawable: Drawable = BitmapDrawable(bitmap) drawable.setBounds(0, 0, bitmap.width, bitmap.height) return drawable } /** * 根据文字获取图片 * * @param text * @return */ fun word2Bitmap(context: Context, text: String?, drawableId: Int): Bitmap { val color = "#ffeeeade" val src = BitmapFactory.decodeResource( context.getResources(), drawableId ) val x = src.width val y = src.height val bmp = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888) val canvasTemp = Canvas(bmp) canvasTemp.drawColor(Color.parseColor(color)) val p = Paint(Paint.FAKE_BOLD_TEXT_FLAG or Paint.ANTI_ALIAS_FLAG) p.color = Color.parseColor("#ff4e0a13") p.alpha = 45 p.isFilterBitmap = true val size = (18 * context.resources.displayMetrics.density) p.textSize = size val tX: Float = (x - getFontlength(p, text)) / 2 val tY: Float = (y - getFontHeight(p)) / 2 + getFontLeading(p) canvasTemp.drawText(text!!, tX, tY, p) return bmp } /** * @return 返回指定笔和指定字符串的长度 */ fun getFontlength(paint: Paint, str: String?): Float { return paint.measureText(str) } /** * @return 返回指定笔的文字高度 */ fun getFontHeight(paint: Paint): Float { val fm = paint.fontMetrics return fm.descent - fm.ascent } /** * @return 返回指定笔离文字顶部的基准距离 */ fun getFontLeading(paint: Paint): Float { val fm = paint.fontMetrics return fm.leading - fm.ascent } /** * 获取圆角图片 * * @param bitmap * @param pixels * @return */ fun bitmap2Round(bitmap: Bitmap, pixels: Float): Bitmap { val output = Bitmap.createBitmap( bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888 ) val canvas = Canvas(output) val color = -0xbdbdbe val paint = Paint() val rect = Rect(0, 0, bitmap.width, bitmap.height) val rectF = RectF(rect) paint.isAntiAlias = true canvas.drawARGB(0, 0, 0, 0) paint.color = color canvas.drawRoundRect(rectF, pixels, pixels, paint) paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN) canvas.drawBitmap(bitmap, rect, rect, paint) return output } /** * bitmap -> semicircle(半圆) * * @param bitmap * @return */ fun bitmap2Semicircle(bitmap: Bitmap): Bitmap? { val output = Bitmap.createBitmap( bitmap.width, bitmap .height, Bitmap.Config.ARGB_8888 ) val canvas = Canvas(output) val color = -0xbdbdbe val paint = Paint() val rect = Rect(0, 0, bitmap.width, bitmap.height) val rectF = RectF(rect) paint.isAntiAlias = true canvas.drawARGB(0, 0, 0, 0) paint.color = color canvas.drawOval(rectF, paint) paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN) canvas.drawBitmap(bitmap, rect, rect, paint) return output } /** * uri -> bitmap * * @param context * @param uri * @return */ fun uri2Bitmap(context: Context, uri: Uri?): Bitmap? { var bp: Bitmap? = null bp = try { BitmapFactory.decodeStream( uri?.let { context.contentResolver .openInputStream(it) } ) //CompressPic.compressBitmap(bitmap, 400, 400) } catch (e: FileNotFoundException) { e.printStackTrace() return null } return bp } /*** * 图片的缩放方法 * * @param bitmap :源图片资源 * @param newWidth:缩放后宽度 * @param newHeight 缩放后高度 * @return */ fun zoomImage(bitmap: Bitmap, newWidth: Double, newHeight: Double): Bitmap { // 获取这个图片的宽和高 val width = bitmap.width.toFloat() val height = bitmap.height.toFloat() // 创建操作图片用的matrix对象 val matrix = Matrix() // 计算宽高缩放率 val scaleWidth = newWidth.toFloat() / width val scaleHeight = newHeight.toFloat() / height // 缩放图片动作 matrix.postScale(scaleWidth, scaleHeight) return Bitmap.createBitmap( bitmap, 0, 0, width.toInt(), height.toInt(), matrix, true ) } fun zoomBitmap(bitmap: Bitmap, scale: Float): Bitmap { return zoomBitmap(bitmap, scale, scale) } /** * 图片的缩放方法 * * @param bitmap * @param scaleWidth * @param scaleHeight * @return */ fun zoomBitmap(bitmap: Bitmap, scaleWidth: Float, scaleHeight: Float): Bitmap { // 获取这个图片的宽和高 val width = bitmap.width.toFloat() val height = bitmap.height.toFloat() // 创建操作图片用的matrix对象 val matrix = Matrix() // 缩放图片动作 matrix.postScale(scaleWidth, scaleHeight) return Bitmap.createBitmap( bitmap, 0, 0, width.toInt(), height.toInt(), matrix, true ) } /** * 压缩图片的尺寸大小 * * @param path * @param newWidth * @param newHight * @return */ fun compressPathSize(path: String?, newWidth: Int, newHight: Int): Bitmap { //先获取图片的尺寸大小 //获取解析bitmap的选项参数 val options = BitmapFactory.Options() //仅仅解析图片的边框 options.inJustDecodeBounds = true //从路径或文件中获取图片bitmap对象 val bitmap = BitmapFactory.decodeFile(path, options) //解析后,bitmap为空,会将长度和宽度放到options中, //此时取得bitmap的宽高 val oldWidth = Math.ceil(options.outWidth.toDouble()).toInt() //向上取整 val oldHight = Math.ceil(options.outHeight.toDouble()).toInt() //获取宽高的比例 val sizeWidth = oldWidth / newWidth val sizeHight = oldHight / newHight val sampleSize = if (sizeHight > sizeWidth) sizeHight else sizeWidth //如果超出指定的大小,就压缩图片 if (sizeHight > 1 && sizeWidth > 1) { //如同前面的步骤,向选项参数中放入新的压缩比例 options.inSampleSize = sampleSize } //需要完整解析整张图片 options.inJustDecodeBounds = false //按照新的缩放比例重新解析 return BitmapFactory.decodeFile(path, options) } /** * 质量压缩方法 * * @param image * @return */ fun compressBitmap(image: Bitmap): Bitmap? { val baos = ByteArrayOutputStream() image.compress(Bitmap.CompressFormat.JPEG, 100, baos) //质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 var options = 90 var bytes: Int = baos.toByteArray().size while (bytes / 1024 > 100 && options >= 20) { //循环判断如果压缩后图片是否大于10kb,大于继续压缩 baos.reset() //重置baos即清空baos options -= 10 //每次都减少10 //第一个参数 :图片格式 ,第二个参数: 图片质量,100为最高,0为最差 ,第三个参数:保存压缩后的数据的流 image.compress(Bitmap.CompressFormat.JPEG, options, baos) //这里压缩options%,把压缩后的数据存放到baos中 bytes = baos.toByteArray().size } image.recycle() val isBm = ByteArrayInputStream(baos.toByteArray()) //把压缩后的数据baos存放到ByteArrayInputStream中 return BitmapFactory.decodeStream(isBm, null, null) //把ByteArrayInputStream数据生成图片 } /** * 压缩图片的内存大小,使文件占据更小的空间 * * @param path * @param newFileName * @param size * @return */ fun compressPathFileSize(path: String, newFileName: String, size: Int): String { //size单位kb //先获取图片bitmap val bitmap = BitmapFactory.decodeFile(path) //将图片压缩到想要的内存以内 //第一次,不压缩图片,先判断图片内存是否符合要求 val baos = ByteArrayOutputStream() var compressQuality = 100 bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos) while (baos.toByteArray().size / 1024 > size) { //清空已经写入的流 baos.reset() //大于想要的尺寸继续压缩 compressQuality -= 10 bitmap.compress(Bitmap.CompressFormat.JPEG, compressQuality, baos) } //跳出循环,表示图片尺寸已经小于size,往文件中写 var fos: FileOutputStream? = null try { fos = FileOutputStream(File(path, "$newFileName.jpg")) val bytes = baos.toByteArray() fos.write(bytes, 0, bytes.size) fos.flush() return path.replace(".jpg", "$newFileName.jpg") } catch (e: FileNotFoundException) { e.printStackTrace() } catch (e: IOException) { e.printStackTrace() } finally { try { baos.close() } catch (e: IOException) { e.printStackTrace() } if (fos != null) { try { fos.close() } catch (e: IOException) { e.printStackTrace() } } } return path } /** * 保存Bitmap图片为本地文件 */ fun saveFile(bitmap: Bitmap, filename: String?) { var fileOutputStream: FileOutputStream? = null try { fileOutputStream = FileOutputStream(filename) bitmap.compress(CompressFormat.PNG, 90, fileOutputStream) fileOutputStream.flush() fileOutputStream.close() } catch (e: FileNotFoundException) { e.printStackTrace() } catch (e: IOException) { e.printStackTrace() } } /** * 通过 View 获取 bitmap,view绘制出来后才行 * * @param v * @return */ fun view2Bitmap2(v: View): Bitmap? { v.clearFocus() // v.isPressed = false // // 能画缓存就返回false val willNotCache: Boolean = v.willNotCacheDrawing() v.setWillNotCacheDrawing(false) val color: Int = v.drawingCacheBackgroundColor v.drawingCacheBackgroundColor = 0 if (color != 0) { v.destroyDrawingCache() } v.buildDrawingCache() val cacheBitmap: Bitmap = v.drawingCache ?: return null val bitmap = Bitmap.createBitmap(cacheBitmap) // Restore the view v.destroyDrawingCache() v.setWillNotCacheDrawing(willNotCache) v.drawingCacheBackgroundColor = color return bitmap } /** * 绘制已经测量过的View,已经显示在界面上,要等控件可以获取到宽高后才行 */ fun view2Bitmap(view: View): Bitmap? { val width = view.width val height = view.height if (width <= 0 || height <= 0) return null val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565) val canvas = Canvas(bitmap) view.draw(canvas) return bitmap } /** * 先测量和布局,再生成Bitmap, 没有显示在界面上,针对不可见 View,可以 View 也可以使用 */ fun view2Bitmap(view: View, context: Activity): Bitmap? { val metric = DisplayMetrics() context.windowManager.defaultDisplay.getMetrics(metric) val screenWidth = metric.widthPixels // 屏幕宽度(像素) val screenHeight = metric.heightPixels // 屏幕高度(像素) // 测量 val widthSpec = View.MeasureSpec.makeMeasureSpec(screenWidth, View.MeasureSpec.AT_MOST) val heightSpec = View.MeasureSpec.makeMeasureSpec(screenHeight, View.MeasureSpec.AT_MOST) view.measure(widthSpec, heightSpec) // 布局 val measuredWidth = view.measuredWidth val measuredHeight = view.measuredHeight view.layout(0, 0, measuredWidth, measuredHeight) // 绘制 val width = view.width val height = view.height val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) val canvas = Canvas(bitmap) //canvas.drawColor(ResUtils.INSTANCE.getColor(R.color.black_5)); view.draw(canvas) return bitmap }}