BitmapUtil.kt 6.6 KB

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