BitmapUtil.kt 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. package com.grkj.iscs.util
  2. import android.content.Context
  3. import android.graphics.Bitmap
  4. import android.graphics.BitmapFactory
  5. import android.graphics.Canvas
  6. import android.graphics.ImageFormat
  7. import android.graphics.Rect
  8. import android.graphics.YuvImage
  9. import android.os.Environment
  10. import com.bumptech.glide.Glide
  11. import com.bumptech.glide.load.DataSource
  12. import com.bumptech.glide.load.engine.GlideException
  13. import com.bumptech.glide.request.RequestListener
  14. import com.bumptech.glide.request.target.Target
  15. import com.grkj.iscs.util.log.LogUtil
  16. import java.io.ByteArrayOutputStream
  17. import java.io.File
  18. import java.io.FileOutputStream
  19. import java.io.IOException
  20. object BitmapUtil {
  21. fun bitmapToFile(bitmap: Bitmap, fileName: String): File? {
  22. // 创建一个临时文件
  23. val storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
  24. if (!storageDir.exists()) {
  25. storageDir.mkdirs()
  26. }
  27. val file = File(storageDir, fileName)
  28. return try {
  29. // 创建文件输出流
  30. val fos = FileOutputStream(file)
  31. // 将 Bitmap 压缩并写入文件
  32. bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)
  33. // 刷新并关闭输出流
  34. fos.flush()
  35. fos.close()
  36. file
  37. } catch (e: IOException) {
  38. e.printStackTrace()
  39. null
  40. }
  41. }
  42. fun bitmapToByteArray(bitmap: Bitmap, format: Bitmap.CompressFormat = Bitmap.CompressFormat.PNG, quality: Int = 100): ByteArray {
  43. val stream = ByteArrayOutputStream()
  44. // 将 Bitmap 压缩并写入到 ByteArrayOutputStream 中
  45. bitmap.compress(format, quality, stream)
  46. // 获取字节数组
  47. return stream.toByteArray()
  48. }
  49. fun loadBitmapFromUrl(
  50. ctx: Context,
  51. url: String?,
  52. placeholder: Int? = null,
  53. reqWidth: Int? = null,
  54. reqHeight: Int? = null,
  55. callback: (Bitmap?) -> Unit
  56. ) {
  57. try {
  58. val builder = Glide.with(ctx)
  59. .asBitmap()
  60. .load(url)
  61. if (reqWidth != null && reqHeight != null) {
  62. builder.override(reqWidth, reqHeight)
  63. }
  64. if (placeholder != null) {
  65. builder.placeholder(placeholder)
  66. }
  67. builder.listener(object : RequestListener<Bitmap> {
  68. override fun onLoadFailed(
  69. e: GlideException?,
  70. model: Any?,
  71. target: Target<Bitmap>?,
  72. isFirstResource: Boolean
  73. ): Boolean {
  74. Executor.runOnMain {
  75. callback(null)
  76. }
  77. return false
  78. }
  79. override fun onResourceReady(
  80. resource: Bitmap?,
  81. model: Any?,
  82. target: Target<Bitmap>?,
  83. dataSource: DataSource?,
  84. isFirstResource: Boolean
  85. ): Boolean {
  86. Executor.runOnMain {
  87. callback(resource)
  88. }
  89. return false
  90. }
  91. }).submit()
  92. } catch (e: Exception) {
  93. e.printStackTrace()
  94. LogUtil.e("loadBitmapFromUrl error: ${e.message} - $url")
  95. Executor.runOnMain {
  96. callback(null)
  97. }
  98. }
  99. }
  100. fun getResizedBitmapFromMipmap(
  101. context: Context,
  102. resId: Int,
  103. reqWidth: Int,
  104. reqHeight: Int
  105. ): Bitmap {
  106. // First decode with inJustDecodeBounds=true to check dimensions
  107. val options = BitmapFactory.Options()
  108. options.inJustDecodeBounds = true
  109. BitmapFactory.decodeResource(context.resources, resId, options)
  110. // Calculate inSampleSize
  111. options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
  112. // Decode bitmap with inSampleSize set
  113. options.inJustDecodeBounds = false
  114. val scaledBitmap = BitmapFactory.decodeResource(context.resources, resId, options)
  115. // Resize the bitmap if necessary
  116. return Bitmap.createScaledBitmap(scaledBitmap, reqWidth, reqHeight, false)
  117. }
  118. private fun calculateInSampleSize(
  119. options: BitmapFactory.Options,
  120. reqWidth: Int,
  121. reqHeight: Int
  122. ): Int {
  123. // Raw height and width of image
  124. val height = options.outHeight
  125. val width = options.outWidth
  126. var inSampleSize = 1
  127. if (height > reqHeight || width > reqWidth) {
  128. val halfHeight = height / 2
  129. val halfWidth = width / 2
  130. // Calculate the largest inSampleSize value that is a power of 2 and keeps both
  131. // height and width larger than the requested height and width.
  132. while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
  133. inSampleSize *= 2
  134. }
  135. }
  136. return inSampleSize
  137. }
  138. fun getResizedBitmapFromDrawable(
  139. context: Context,
  140. resId: Int,
  141. reqWidth: Int,
  142. reqHeight: Int
  143. ): Bitmap? {
  144. val drawable = context.resources.getDrawable(resId)
  145. if (drawable == null) {
  146. LogUtil.e("Drawable is null for resource ID: $resId")
  147. return null
  148. }
  149. // Create a bitmap with the specified width and height
  150. val bitmap = Bitmap.createBitmap(reqWidth, reqHeight, Bitmap.Config.ARGB_8888)
  151. val canvas = Canvas(bitmap)
  152. // Scale the drawable to fit the bitmap dimensions
  153. drawable.setBounds(0, 0, reqWidth, reqHeight)
  154. drawable.draw(canvas)
  155. return bitmap
  156. }
  157. /**
  158. * 将NV21格式的数据转换为Bitmap。(效率低,用NV21ToBitmap类)
  159. *
  160. * @param nv21 NV21格式的字节数组
  161. * @param width 图像的宽度
  162. * @param height 图像的高度
  163. * @return 转换后的Bitmap对象
  164. */
  165. fun convertNV21ToBitmap(nv21: ByteArray?, width: Int, height: Int): Bitmap? {
  166. val yuvImage = YuvImage(nv21, ImageFormat.NV21, width, height, null)
  167. val outputStream = ByteArrayOutputStream()
  168. yuvImage.compressToJpeg(Rect(0, 0, width, height), 100, outputStream)
  169. val imageBytes = outputStream.toByteArray()
  170. return try {
  171. val bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
  172. outputStream.close()
  173. bitmap
  174. } catch (e: Exception) {
  175. e.printStackTrace()
  176. null
  177. }
  178. }
  179. }