| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- package com.grkj.iscs.util
- import android.content.Context
- import android.graphics.Bitmap
- import android.graphics.BitmapFactory
- import android.graphics.Canvas
- import android.graphics.ImageFormat
- import android.graphics.Rect
- import android.graphics.YuvImage
- import android.os.Environment
- import androidx.annotation.DrawableRes
- import androidx.core.content.ContextCompat
- import com.bumptech.glide.Glide
- import com.bumptech.glide.load.DataSource
- import com.bumptech.glide.load.engine.GlideException
- import com.bumptech.glide.request.RequestListener
- import com.bumptech.glide.request.target.Target
- import com.grkj.iscs.util.log.LogUtil
- import java.io.ByteArrayOutputStream
- import java.io.File
- import java.io.FileOutputStream
- import java.io.IOException
- object BitmapUtil {
- fun bitmapToFile(bitmap: Bitmap, fileName: String): File? {
- // 创建一个临时文件
- val storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
- if (!storageDir.exists()) {
- storageDir.mkdirs()
- }
- val file = File(storageDir, fileName)
- return try {
- // 创建文件输出流
- val fos = FileOutputStream(file)
- // 将 Bitmap 压缩并写入文件
- bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)
- // 刷新并关闭输出流
- fos.flush()
- fos.close()
- file
- } catch (e: IOException) {
- e.printStackTrace()
- null
- }
- }
- fun bitmapToByteArray(bitmap: Bitmap, format: Bitmap.CompressFormat = Bitmap.CompressFormat.PNG, quality: Int = 100): ByteArray {
- val stream = ByteArrayOutputStream()
- // 将 Bitmap 压缩并写入到 ByteArrayOutputStream 中
- bitmap.compress(format, quality, stream)
- // 获取字节数组
- return stream.toByteArray()
- }
- fun loadBitmapFromUrl(
- ctx: Context,
- url: String?,
- placeholder: Int? = null,
- reqWidth: Int? = null,
- reqHeight: Int? = null,
- callback: (Bitmap?) -> Unit
- ) {
- try {
- val builder = Glide.with(ctx)
- .asBitmap()
- .load(url)
- if (reqWidth != null && reqHeight != null) {
- builder.override(reqWidth, reqHeight)
- }
- if (placeholder != null) {
- builder.placeholder(placeholder)
- }
- builder.listener(object : RequestListener<Bitmap> {
- override fun onLoadFailed(
- e: GlideException?,
- model: Any?,
- target: Target<Bitmap>?,
- isFirstResource: Boolean
- ): Boolean {
- Executor.runOnMain {
- callback(null)
- }
- return false
- }
- override fun onResourceReady(
- resource: Bitmap?,
- model: Any?,
- target: Target<Bitmap>?,
- dataSource: DataSource?,
- isFirstResource: Boolean
- ): Boolean {
- Executor.runOnMain {
- callback(resource)
- }
- return false
- }
- }).submit()
- } catch (e: Exception) {
- e.printStackTrace()
- LogUtil.e("loadBitmapFromUrl error: ${e.message} - $url")
- Executor.runOnMain {
- callback(null)
- }
- }
- }
- fun getResizedBitmapFromMipmap(
- context: Context,
- resId: Int,
- reqWidth: Int,
- reqHeight: Int
- ): Bitmap {
- // First decode with inJustDecodeBounds=true to check dimensions
- val options = BitmapFactory.Options()
- options.inJustDecodeBounds = true
- BitmapFactory.decodeResource(context.resources, resId, options)
- // Calculate inSampleSize
- options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
- // Decode bitmap with inSampleSize set
- options.inJustDecodeBounds = false
- val scaledBitmap = BitmapFactory.decodeResource(context.resources, resId, options)
- // Resize the bitmap if necessary
- return Bitmap.createScaledBitmap(scaledBitmap, reqWidth, reqHeight, false)
- }
- private fun calculateInSampleSize(
- options: BitmapFactory.Options,
- reqWidth: Int,
- reqHeight: Int
- ): Int {
- // Raw height and width of image
- val height = options.outHeight
- val width = options.outWidth
- var inSampleSize = 1
- if (height > reqHeight || width > reqWidth) {
- val halfHeight = height / 2
- val halfWidth = width / 2
- // Calculate the largest inSampleSize value that is a power of 2 and keeps both
- // height and width larger than the requested height and width.
- while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
- inSampleSize *= 2
- }
- }
- return inSampleSize
- }
- fun getResizedBitmapFromDrawable(
- context: Context,
- resId: Int,
- reqWidth: Int,
- reqHeight: Int
- ): Bitmap? {
- val drawable = context.resources.getDrawable(resId)
- if (drawable == null) {
- LogUtil.e("Drawable is null for resource ID: $resId")
- return null
- }
- // Create a bitmap with the specified width and height
- val bitmap = Bitmap.createBitmap(reqWidth, reqHeight, Bitmap.Config.ARGB_8888)
- val canvas = Canvas(bitmap)
- // Scale the drawable to fit the bitmap dimensions
- drawable.setBounds(0, 0, reqWidth, reqHeight)
- drawable.draw(canvas)
- return bitmap
- }
- /**
- * 将NV21格式的数据转换为Bitmap。(效率低,用NV21ToBitmap类)
- *
- * @param nv21 NV21格式的字节数组
- * @param width 图像的宽度
- * @param height 图像的高度
- * @return 转换后的Bitmap对象
- */
- fun convertNV21ToBitmap(nv21: ByteArray?, width: Int, height: Int): Bitmap? {
- val yuvImage = YuvImage(nv21, ImageFormat.NV21, width, height, null)
- val outputStream = ByteArrayOutputStream()
- yuvImage.compressToJpeg(Rect(0, 0, width, height), 100, outputStream)
- val imageBytes = outputStream.toByteArray()
- return try {
- val bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
- outputStream.close()
- bitmap
- } catch (e: Exception) {
- e.printStackTrace()
- null
- }
- }
- }
|