|
|
@@ -0,0 +1,167 @@
|
|
|
+package com.grkj.iscs.util
|
|
|
+
|
|
|
+import android.content.Context
|
|
|
+import android.graphics.Bitmap
|
|
|
+import android.graphics.BitmapFactory
|
|
|
+import android.graphics.Canvas
|
|
|
+import android.os.Environment
|
|
|
+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, callback: (Bitmap?) -> Unit) {
|
|
|
+ try {
|
|
|
+ Glide.with(ctx)
|
|
|
+ .asBitmap()
|
|
|
+ .load(url)
|
|
|
+ .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()
|
|
|
+ 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
|
|
|
+ }
|
|
|
+}
|