方法列表

  1. id2Bitmap :获取资源图片的 Bitmap
  2. string2Bitmap :string -> bitmap 通过 Base64 实现
  3. bitmap2String :bitmap -> string 通过 Base64实现
  4. bytes2Bitmap :把byte字节流转成bitmap
  5. bitmap2Bytes :把bitmap转成byte字节流
  6. drawable2Bitmap :drawable bitmap
  7. drawable2Bitmap2:drawable bitmap
  8. bitmap2Drawable :bitmap -> drawable
  9. word2Bitmap :根据文字获取图片
  10. bitmap2Round :获取圆角图片
  11. bitmap2Semicircle:bitmap -> semicircle(半圆)
  12. uri2Bitmap :uri -> bitmap
  13. view2Bitmap2 :通过 View 获取 bitmap,view绘制出来后才行
  14. view2Bitmap :单个View 参数,绘制已经测量过的View,已经显示在界面上,要等控件可以获取到宽高后才行
  15. view2Bitmap :先测量和布局,再生成Bitmap, 没有显示在界面上,针对不可见 View,可以 View 也可以使用
  16. zoomImage :图片的缩放方法,尺寸压缩
  17. compressPathSize:压缩文件读取图片的尺寸大小
  18. compressBitmap :质量压缩方法
  19. compressPathFileSize:压缩图片的内存大小,使文件占据更小的空间
  20. saveFile :保存Bitmap图片为本地文件

完整代码

  1. object BitmapUtils {
  2. /**
  3. * 获取资源图片的 Bitmap
  4. */
  5. fun id2Bitmap(resId: Int): Bitmap? {
  6. var bitmap: Bitmap? = null
  7. if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
  8. val vectorDrawable: Drawable = getContext().getDrawable(resId) ?: return bitmap
  9. bitmap = Bitmap.createBitmap(
  10. vectorDrawable.intrinsicWidth,
  11. vectorDrawable.intrinsicHeight, Bitmap.Config.ARGB_8888
  12. )
  13. val canvas = Canvas(bitmap!!)
  14. vectorDrawable.setBounds(0, 0, canvas.width, canvas.height)
  15. vectorDrawable.draw(canvas)
  16. } else {
  17. bitmap = BitmapFactory.decodeResource(getResources(), resId)
  18. }
  19. return bitmap
  20. }
  21. /**
  22. * string -> bitmap 通过 Base64 实现
  23. *
  24. * @param string
  25. * @return
  26. */
  27. fun string2Bitmap(string: String?): Bitmap? {
  28. // 将字符串转换成Bitmap类型
  29. var bitmap: Bitmap? = null
  30. try {
  31. val bitmapArray: ByteArray = Base64.decode(string, Base64.DEFAULT)
  32. bitmap = BitmapFactory.decodeByteArray(
  33. bitmapArray, 0,
  34. bitmapArray.size
  35. )
  36. } catch (e: Exception) {
  37. e.printStackTrace()
  38. }
  39. return bitmap
  40. }
  41. /**
  42. * bitmap -> string 通过 Base64实现
  43. *
  44. * @param bitmap
  45. * @return
  46. */
  47. fun bitmap2String(bitmap: Bitmap): String? {
  48. //将Bitmap转换成字符串
  49. var string: String? = null
  50. val bStream = ByteArrayOutputStream()
  51. bitmap.compress(CompressFormat.PNG, 100, bStream)
  52. val bytes = bStream.toByteArray()
  53. string = Base64.encodeToString(bytes, Base64.DEFAULT)
  54. return string
  55. }
  56. /**
  57. * 把byte字节流转成bitmap
  58. * @param bytes
  59. */
  60. fun bytes2Bitmap(bytes: ByteArray): Bitmap? {
  61. val opts = BitmapFactory.Options()
  62. opts.inJustDecodeBounds = false //为true时,返回的bitmap为null
  63. return BitmapFactory.decodeByteArray(bytes, 0, bytes.size, opts)
  64. }
  65. /**
  66. * 把bitmap转成byte字节流
  67. * @param bm
  68. */
  69. fun bitmap2Bytes(bm: Bitmap): ByteArray {
  70. val baos = ByteArrayOutputStream()
  71. bm.compress(Bitmap.CompressFormat.PNG, 100, baos)
  72. return baos.toByteArray()
  73. }
  74. /**
  75. * drawable 转 bitmap
  76. *
  77. * @param drawable
  78. * @return
  79. */
  80. fun drawable2Bitmap(drawable: Drawable): Bitmap {
  81. val bd = drawable as BitmapDrawable
  82. return bd.bitmap
  83. }
  84. /**
  85. * drawable 转 bitmap
  86. *
  87. * @param drawable
  88. * @return
  89. */
  90. fun drawable2Bitmap2(drawable: Drawable): Bitmap {
  91. // 取 drawable 的长宽
  92. val w = drawable.intrinsicWidth
  93. val h = drawable.intrinsicHeight
  94. // 取 drawable 的颜色格式
  95. val config =
  96. if (drawable.opacity != PixelFormat.OPAQUE) Bitmap.Config.ARGB_8888 else Bitmap.Config.RGB_565
  97. // 建立对应 bitmap
  98. val bitmap = Bitmap.createBitmap(w, h, config)
  99. // 建立对应 bitmap 的画布
  100. val canvas = Canvas(bitmap)
  101. drawable.setBounds(0, 0, w, h)
  102. // 把 drawable 内容画到画布中
  103. drawable.draw(canvas)
  104. return bitmap
  105. }
  106. /**
  107. * bitmap -> drawable
  108. *
  109. * @param bitmap
  110. * @return
  111. */
  112. fun bitmap2Drawable(bitmap: Bitmap): Drawable {
  113. val drawable: Drawable = BitmapDrawable(bitmap)
  114. drawable.setBounds(0, 0, bitmap.width, bitmap.height)
  115. return drawable
  116. }
  117. /**
  118. * 根据文字获取图片
  119. *
  120. * @param text
  121. * @return
  122. */
  123. fun word2Bitmap(context: Context, text: String?, drawableId: Int): Bitmap {
  124. val color = "#ffeeeade"
  125. val src = BitmapFactory.decodeResource(
  126. context.getResources(),
  127. drawableId
  128. )
  129. val x = src.width
  130. val y = src.height
  131. val bmp = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888)
  132. val canvasTemp = Canvas(bmp)
  133. canvasTemp.drawColor(Color.parseColor(color))
  134. val p = Paint(Paint.FAKE_BOLD_TEXT_FLAG or Paint.ANTI_ALIAS_FLAG)
  135. p.color = Color.parseColor("#ff4e0a13")
  136. p.alpha = 45
  137. p.isFilterBitmap = true
  138. val size = (18 * context.resources.displayMetrics.density)
  139. p.textSize = size
  140. val tX: Float = (x - getFontlength(p, text)) / 2
  141. val tY: Float = (y - getFontHeight(p)) / 2 + getFontLeading(p)
  142. canvasTemp.drawText(text!!, tX, tY, p)
  143. return bmp
  144. }
  145. /**
  146. * @return 返回指定笔和指定字符串的长度
  147. */
  148. fun getFontlength(paint: Paint, str: String?): Float {
  149. return paint.measureText(str)
  150. }
  151. /**
  152. * @return 返回指定笔的文字高度
  153. */
  154. fun getFontHeight(paint: Paint): Float {
  155. val fm = paint.fontMetrics
  156. return fm.descent - fm.ascent
  157. }
  158. /**
  159. * @return 返回指定笔离文字顶部的基准距离
  160. */
  161. fun getFontLeading(paint: Paint): Float {
  162. val fm = paint.fontMetrics
  163. return fm.leading - fm.ascent
  164. }
  165. /**
  166. * 获取圆角图片
  167. *
  168. * @param bitmap
  169. * @param pixels
  170. * @return
  171. */
  172. fun bitmap2Round(bitmap: Bitmap, pixels: Float): Bitmap {
  173. val output = Bitmap.createBitmap(
  174. bitmap.width,
  175. bitmap.height, Bitmap.Config.ARGB_8888
  176. )
  177. val canvas = Canvas(output)
  178. val color = -0xbdbdbe
  179. val paint = Paint()
  180. val rect = Rect(0, 0, bitmap.width, bitmap.height)
  181. val rectF = RectF(rect)
  182. paint.isAntiAlias = true
  183. canvas.drawARGB(0, 0, 0, 0)
  184. paint.color = color
  185. canvas.drawRoundRect(rectF, pixels, pixels, paint)
  186. paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
  187. canvas.drawBitmap(bitmap, rect, rect, paint)
  188. return output
  189. }
  190. /**
  191. * bitmap -> semicircle(半圆)
  192. *
  193. * @param bitmap
  194. * @return
  195. */
  196. fun bitmap2Semicircle(bitmap: Bitmap): Bitmap? {
  197. val output = Bitmap.createBitmap(
  198. bitmap.width, bitmap
  199. .height, Bitmap.Config.ARGB_8888
  200. )
  201. val canvas = Canvas(output)
  202. val color = -0xbdbdbe
  203. val paint = Paint()
  204. val rect = Rect(0, 0, bitmap.width, bitmap.height)
  205. val rectF = RectF(rect)
  206. paint.isAntiAlias = true
  207. canvas.drawARGB(0, 0, 0, 0)
  208. paint.color = color
  209. canvas.drawOval(rectF, paint)
  210. paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
  211. canvas.drawBitmap(bitmap, rect, rect, paint)
  212. return output
  213. }
  214. /**
  215. * uri -> bitmap
  216. *
  217. * @param context
  218. * @param uri
  219. * @return
  220. */
  221. fun uri2Bitmap(context: Context, uri: Uri?): Bitmap? {
  222. var bp: Bitmap? = null
  223. bp = try {
  224. BitmapFactory.decodeStream(
  225. uri?.let {
  226. context.contentResolver
  227. .openInputStream(it)
  228. }
  229. )
  230. //CompressPic.compressBitmap(bitmap, 400, 400)
  231. } catch (e: FileNotFoundException) {
  232. e.printStackTrace()
  233. return null
  234. }
  235. return bp
  236. }
  237. /***
  238. * 图片的缩放方法
  239. *
  240. * @param bitmap :源图片资源
  241. * @param newWidth:缩放后宽度
  242. * @param newHeight 缩放后高度
  243. * @return
  244. */
  245. fun zoomImage(bitmap: Bitmap, newWidth: Double, newHeight: Double): Bitmap {
  246. // 获取这个图片的宽和高
  247. val width = bitmap.width.toFloat()
  248. val height = bitmap.height.toFloat()
  249. // 创建操作图片用的matrix对象
  250. val matrix = Matrix()
  251. // 计算宽高缩放率
  252. val scaleWidth = newWidth.toFloat() / width
  253. val scaleHeight = newHeight.toFloat() / height
  254. // 缩放图片动作
  255. matrix.postScale(scaleWidth, scaleHeight)
  256. return Bitmap.createBitmap(
  257. bitmap, 0, 0, width.toInt(),
  258. height.toInt(), matrix, true
  259. )
  260. }
  261. fun zoomBitmap(bitmap: Bitmap, scale: Float): Bitmap {
  262. return zoomBitmap(bitmap, scale, scale)
  263. }
  264. /**
  265. * 图片的缩放方法
  266. *
  267. * @param bitmap
  268. * @param scaleWidth
  269. * @param scaleHeight
  270. * @return
  271. */
  272. fun zoomBitmap(bitmap: Bitmap, scaleWidth: Float, scaleHeight: Float): Bitmap {
  273. // 获取这个图片的宽和高
  274. val width = bitmap.width.toFloat()
  275. val height = bitmap.height.toFloat()
  276. // 创建操作图片用的matrix对象
  277. val matrix = Matrix()
  278. // 缩放图片动作
  279. matrix.postScale(scaleWidth, scaleHeight)
  280. return Bitmap.createBitmap(
  281. bitmap, 0, 0, width.toInt(),
  282. height.toInt(), matrix, true
  283. )
  284. }
  285. /**
  286. * 压缩图片的尺寸大小
  287. *
  288. * @param path
  289. * @param newWidth
  290. * @param newHight
  291. * @return
  292. */
  293. fun compressPathSize(path: String?, newWidth: Int, newHight: Int): Bitmap {
  294. //先获取图片的尺寸大小
  295. //获取解析bitmap的选项参数
  296. val options = BitmapFactory.Options()
  297. //仅仅解析图片的边框
  298. options.inJustDecodeBounds = true
  299. //从路径或文件中获取图片bitmap对象
  300. val bitmap = BitmapFactory.decodeFile(path, options)
  301. //解析后,bitmap为空,会将长度和宽度放到options中,
  302. //此时取得bitmap的宽高
  303. val oldWidth = Math.ceil(options.outWidth.toDouble()).toInt() //向上取整
  304. val oldHight = Math.ceil(options.outHeight.toDouble()).toInt()
  305. //获取宽高的比例
  306. val sizeWidth = oldWidth / newWidth
  307. val sizeHight = oldHight / newHight
  308. val sampleSize = if (sizeHight > sizeWidth) sizeHight else sizeWidth
  309. //如果超出指定的大小,就压缩图片
  310. if (sizeHight > 1 && sizeWidth > 1) {
  311. //如同前面的步骤,向选项参数中放入新的压缩比例
  312. options.inSampleSize = sampleSize
  313. }
  314. //需要完整解析整张图片
  315. options.inJustDecodeBounds = false
  316. //按照新的缩放比例重新解析
  317. return BitmapFactory.decodeFile(path, options)
  318. }
  319. /**
  320. * 质量压缩方法
  321. *
  322. * @param image
  323. * @return
  324. */
  325. fun compressBitmap(image: Bitmap): Bitmap? {
  326. val baos = ByteArrayOutputStream()
  327. image.compress(Bitmap.CompressFormat.JPEG, 100, baos) //质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
  328. var options = 90
  329. var bytes: Int = baos.toByteArray().size
  330. while (bytes / 1024 > 100 && options >= 20) { //循环判断如果压缩后图片是否大于10kb,大于继续压缩
  331. baos.reset() //重置baos即清空baos
  332. options -= 10 //每次都减少10
  333. //第一个参数 :图片格式 ,第二个参数: 图片质量,100为最高,0为最差 ,第三个参数:保存压缩后的数据的流
  334. image.compress(Bitmap.CompressFormat.JPEG, options, baos) //这里压缩options%,把压缩后的数据存放到baos中
  335. bytes = baos.toByteArray().size
  336. }
  337. image.recycle()
  338. val isBm = ByteArrayInputStream(baos.toByteArray()) //把压缩后的数据baos存放到ByteArrayInputStream中
  339. return BitmapFactory.decodeStream(isBm, null, null) //把ByteArrayInputStream数据生成图片
  340. }
  341. /**
  342. * 压缩图片的内存大小,使文件占据更小的空间
  343. *
  344. * @param path
  345. * @param newFileName
  346. * @param size
  347. * @return
  348. */
  349. fun compressPathFileSize(path: String, newFileName: String, size: Int): String { //size单位kb
  350. //先获取图片bitmap
  351. val bitmap = BitmapFactory.decodeFile(path)
  352. //将图片压缩到想要的内存以内
  353. //第一次,不压缩图片,先判断图片内存是否符合要求
  354. val baos = ByteArrayOutputStream()
  355. var compressQuality = 100
  356. bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
  357. while (baos.toByteArray().size / 1024 > size) {
  358. //清空已经写入的流
  359. baos.reset()
  360. //大于想要的尺寸继续压缩
  361. compressQuality -= 10
  362. bitmap.compress(Bitmap.CompressFormat.JPEG, compressQuality, baos)
  363. }
  364. //跳出循环,表示图片尺寸已经小于size,往文件中写
  365. var fos: FileOutputStream? = null
  366. try {
  367. fos = FileOutputStream(File(path, "$newFileName.jpg"))
  368. val bytes = baos.toByteArray()
  369. fos.write(bytes, 0, bytes.size)
  370. fos.flush()
  371. return path.replace(".jpg", "$newFileName.jpg")
  372. } catch (e: FileNotFoundException) {
  373. e.printStackTrace()
  374. } catch (e: IOException) {
  375. e.printStackTrace()
  376. } finally {
  377. try {
  378. baos.close()
  379. } catch (e: IOException) {
  380. e.printStackTrace()
  381. }
  382. if (fos != null) {
  383. try {
  384. fos.close()
  385. } catch (e: IOException) {
  386. e.printStackTrace()
  387. }
  388. }
  389. }
  390. return path
  391. }
  392. /**
  393. * 保存Bitmap图片为本地文件
  394. */
  395. fun saveFile(bitmap: Bitmap, filename: String?) {
  396. var fileOutputStream: FileOutputStream? = null
  397. try {
  398. fileOutputStream = FileOutputStream(filename)
  399. bitmap.compress(CompressFormat.PNG, 90, fileOutputStream)
  400. fileOutputStream.flush()
  401. fileOutputStream.close()
  402. } catch (e: FileNotFoundException) {
  403. e.printStackTrace()
  404. } catch (e: IOException) {
  405. e.printStackTrace()
  406. }
  407. }
  408. /**
  409. * 通过 View 获取 bitmap,view绘制出来后才行
  410. *
  411. * @param v
  412. * @return
  413. */
  414. fun view2Bitmap2(v: View): Bitmap? {
  415. v.clearFocus() //
  416. v.isPressed = false //
  417. // 能画缓存就返回false
  418. val willNotCache: Boolean = v.willNotCacheDrawing()
  419. v.setWillNotCacheDrawing(false)
  420. val color: Int = v.drawingCacheBackgroundColor
  421. v.drawingCacheBackgroundColor = 0
  422. if (color != 0) {
  423. v.destroyDrawingCache()
  424. }
  425. v.buildDrawingCache()
  426. val cacheBitmap: Bitmap = v.drawingCache ?: return null
  427. val bitmap = Bitmap.createBitmap(cacheBitmap)
  428. // Restore the view
  429. v.destroyDrawingCache()
  430. v.setWillNotCacheDrawing(willNotCache)
  431. v.drawingCacheBackgroundColor = color
  432. return bitmap
  433. }
  434. /**
  435. * 绘制已经测量过的View,已经显示在界面上,要等控件可以获取到宽高后才行
  436. */
  437. fun view2Bitmap(view: View): Bitmap? {
  438. val width = view.width
  439. val height = view.height
  440. if (width <= 0 || height <= 0) return null
  441. val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
  442. val canvas = Canvas(bitmap)
  443. view.draw(canvas)
  444. return bitmap
  445. }
  446. /**
  447. * 先测量和布局,再生成Bitmap, 没有显示在界面上,针对不可见 View,可以 View 也可以使用
  448. */
  449. fun view2Bitmap(view: View, context: Activity): Bitmap? {
  450. val metric = DisplayMetrics()
  451. context.windowManager.defaultDisplay.getMetrics(metric)
  452. val screenWidth = metric.widthPixels // 屏幕宽度(像素)
  453. val screenHeight = metric.heightPixels // 屏幕高度(像素)
  454. // 测量
  455. val widthSpec = View.MeasureSpec.makeMeasureSpec(screenWidth, View.MeasureSpec.AT_MOST)
  456. val heightSpec = View.MeasureSpec.makeMeasureSpec(screenHeight, View.MeasureSpec.AT_MOST)
  457. view.measure(widthSpec, heightSpec)
  458. // 布局
  459. val measuredWidth = view.measuredWidth
  460. val measuredHeight = view.measuredHeight
  461. view.layout(0, 0, measuredWidth, measuredHeight)
  462. // 绘制
  463. val width = view.width
  464. val height = view.height
  465. val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
  466. val canvas = Canvas(bitmap)
  467. //canvas.drawColor(ResUtils.INSTANCE.getColor(R.color.black_5));
  468. view.draw(canvas)
  469. return bitmap
  470. }
  471. }