|
@@ -0,0 +1,873 @@
|
|
|
+//package com.kdanmobile.android.common.utils.image
|
|
|
+//
|
|
|
+//import android.R
|
|
|
+//import android.annotation.SuppressLint
|
|
|
+//import android.content.Context
|
|
|
+//import android.content.res.ColorStateList
|
|
|
+//import android.content.res.Resources
|
|
|
+//import android.graphics.*
|
|
|
+//import android.graphics.drawable.BitmapDrawable
|
|
|
+//import android.graphics.drawable.Drawable
|
|
|
+//import android.graphics.drawable.StateListDrawable
|
|
|
+//import android.media.ExifInterface
|
|
|
+//import android.net.Uri
|
|
|
+//import android.os.Build
|
|
|
+//import android.text.TextUtils
|
|
|
+//import android.view.View
|
|
|
+//import android.widget.ImageView
|
|
|
+//import androidx.annotation.DrawableRes
|
|
|
+//import androidx.annotation.RequiresApi
|
|
|
+//import androidx.appcompat.widget.AppCompatImageButton
|
|
|
+//import androidx.appcompat.widget.AppCompatImageView
|
|
|
+//import androidx.core.content.ContextCompat
|
|
|
+//import androidx.core.graphics.drawable.DrawableCompat
|
|
|
+//import com.kdan.pdfbaselibrary.utils.systemui.ScreenUtil.Companion.getDensity
|
|
|
+//import com.kdan.pdfbaselibrary.utils.file.FileUtils
|
|
|
+//import kotlinx.coroutines.Dispatchers
|
|
|
+//import kotlinx.coroutines.withContext
|
|
|
+//import java.io.*
|
|
|
+//import java.text.SimpleDateFormat
|
|
|
+//import java.util.*
|
|
|
+//
|
|
|
+//
|
|
|
+///**
|
|
|
+// * @classname:BitmapUtils
|
|
|
+// * @author:wangzhe
|
|
|
+// * @date:2018/9/13 下午2:19
|
|
|
+// * @description:
|
|
|
+// */
|
|
|
+//object BitmapUtils {
|
|
|
+//
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 从资源中解码经过采样处理后的bitmap
|
|
|
+// */
|
|
|
+// fun decodeSampledBitmapFromResource(res: Resources?, resId: Int, reqWidth: Int, reqHeight: Int): Bitmap? {
|
|
|
+// // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
|
|
|
+// val options = BitmapFactory.Options()
|
|
|
+// options.inJustDecodeBounds = true
|
|
|
+// BitmapFactory.decodeResource(res, resId, options)
|
|
|
+// // 调用上面定义的方法计算inSampleSize值
|
|
|
+// options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
|
|
|
+// // 使用获取到的inSampleSize值再次解析图片
|
|
|
+// options.inJustDecodeBounds = false
|
|
|
+// return BitmapFactory.decodeResource(res, resId, options)
|
|
|
+// }
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 从文件
|
|
|
+// */
|
|
|
+// fun decodeSampledBitmapFromPath(path: String?, reqWidth: Int, reqHeight: Int): Bitmap? {
|
|
|
+// // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
|
|
|
+// val options = BitmapFactory.Options()
|
|
|
+// options.inJustDecodeBounds = true
|
|
|
+// BitmapFactory.decodeFile(path, options)
|
|
|
+// // 调用上面定义的方法计算inSampleSize值
|
|
|
+// options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
|
|
|
+// // 使用获取到的inSampleSize值再次解析图片
|
|
|
+// options.inJustDecodeBounds = false
|
|
|
+// return BitmapFactory.decodeFile(path, options)
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+// fun getBitmapByResource(context: Context?,@DrawableRes resId: Int): Bitmap? {
|
|
|
+// val drawable = ContextCompat.getDrawable(context!!, resId)
|
|
|
+// val bd = drawable as BitmapDrawable?
|
|
|
+// return bd!!.bitmap
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 计算图片的采样大小
|
|
|
+// */
|
|
|
+// fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
|
|
|
+// // 源图片的高度和宽度
|
|
|
+// val height = options.outHeight
|
|
|
+// val width = options.outWidth
|
|
|
+// var inSampleSize = 1
|
|
|
+// if (height > reqHeight || width > reqWidth) {
|
|
|
+// // 计算出实际宽高和目标宽高的比率
|
|
|
+// val heightRatio = Math.round(height.toFloat() / reqHeight.toFloat())
|
|
|
+// val widthRatio = Math.round(width.toFloat() / reqWidth.toFloat())
|
|
|
+// // 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高
|
|
|
+// // 一定都会大于等于目标的宽和高。
|
|
|
+// inSampleSize = if (heightRatio > widthRatio) heightRatio else widthRatio
|
|
|
+// }
|
|
|
+// return inSampleSize
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+//
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * @param image
|
|
|
+// * @param percent 压缩百分比
|
|
|
+// * @return
|
|
|
+// * @方法说明:质量压缩方法
|
|
|
+// * @方法名称:compressImage
|
|
|
+// * @返回值:Bitmap
|
|
|
+// */
|
|
|
+// fun compressImage(image: Bitmap, percent: Int): Bitmap? {
|
|
|
+// val baos = ByteArrayOutputStream()
|
|
|
+// image.compress(Bitmap.CompressFormat.JPEG, percent, baos) // 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
|
|
|
+// var options = 60
|
|
|
+// while (baos.toByteArray().size / 1024 > 80) { // 循环判断如果压缩后图片是否大于80kb,大于继续压缩
|
|
|
+// baos.reset() // 重置baos即清空baos
|
|
|
+// image.compress(Bitmap.CompressFormat.JPEG, options, baos) // 这里压缩options%,把压缩后的数据存放到baos中
|
|
|
+// options -= 10 // 每次都减少10
|
|
|
+// }
|
|
|
+// val isBm = ByteArrayInputStream(baos.toByteArray()) // 把压缩后的数据baos存放到ByteArrayInputStream中
|
|
|
+// return BitmapFactory.decodeStream(isBm, null, null)
|
|
|
+// }
|
|
|
+//
|
|
|
+// @JvmStatic
|
|
|
+// fun getBitmapFromFile(file: File?): Bitmap? = if (file?.exists() == true) getBitmapFromFilePath(file.absolutePath) else null
|
|
|
+//
|
|
|
+// @JvmStatic
|
|
|
+// fun getBitmapFromFilePath(filePath: String?): Bitmap? {
|
|
|
+// return try {
|
|
|
+// when {
|
|
|
+// filePath.isNullOrEmpty() -> null
|
|
|
+// !File(filePath).exists() -> null
|
|
|
+// else -> {
|
|
|
+// val opts = BitmapFactory.Options()
|
|
|
+// opts.inJustDecodeBounds = false
|
|
|
+// opts.inSampleSize = 1
|
|
|
+// opts.inPreferredConfig = Bitmap.Config.RGB_565
|
|
|
+// BitmapFactory.decodeFile(filePath, opts)
|
|
|
+// }
|
|
|
+// }
|
|
|
+// } catch (e: Exception) {
|
|
|
+// null
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// @JvmStatic
|
|
|
+// fun saveBitmapToFile(bitmap: Bitmap?, file: File?, quality: Int = 80, type: String = "png"): Boolean {
|
|
|
+// bitmap ?: return false
|
|
|
+// file ?: return false
|
|
|
+// if (bitmap.isRecycled) return false
|
|
|
+//
|
|
|
+// if (!file.exists()) FileUtils.createFile(file, true)
|
|
|
+// if (!file.exists()) return false
|
|
|
+//
|
|
|
+// return try {
|
|
|
+// FileOutputStream(file)
|
|
|
+// .run {
|
|
|
+// try {
|
|
|
+// bitmap.compress(if ("png".equals(type, ignoreCase = true)) Bitmap.CompressFormat.PNG else Bitmap.CompressFormat.JPEG, quality, this)
|
|
|
+// flush()
|
|
|
+// true
|
|
|
+// } catch (e: Exception) {
|
|
|
+// false
|
|
|
+// } finally {
|
|
|
+// runCatching { close() }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// } catch (e: Exception) {
|
|
|
+// //基本出现这里就异常的是File 文件区域没有读写权限导致的。
|
|
|
+// return false
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// @SuppressLint("SimpleDateFormat")
|
|
|
+// @JvmStatic
|
|
|
+// fun saveBitmapToFile(bitmap: Bitmap?, dir: String, type: String): String? {
|
|
|
+// bitmap ?: return null
|
|
|
+// if (bitmap.isRecycled) return null
|
|
|
+//
|
|
|
+// val tempType = when (type) {
|
|
|
+// "png" -> ".png"
|
|
|
+// else -> ".jpeg"
|
|
|
+// }
|
|
|
+//
|
|
|
+// val file = File(dir, "${SimpleDateFormat("yyyyMMddHHmmss").format(Date(System.currentTimeMillis()))}$tempType")
|
|
|
+// if (!file.exists()) FileUtils.createFile(file, true)
|
|
|
+// if (!file.exists()) return null
|
|
|
+// return saveBitmapToFile(bitmap = bitmap, file = file, type = tempType).run {
|
|
|
+// when {
|
|
|
+// this -> file.canonicalPath
|
|
|
+// else -> null
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * @methodName:rotateImage created by liujiyuan on 2019-12-03 18:30.
|
|
|
+// * @description:把图片顺时针旋转
|
|
|
+// */
|
|
|
+// @JvmStatic
|
|
|
+// fun rotateImage(bitmap: Bitmap?, degrees: Float): Bitmap? {
|
|
|
+// return try {
|
|
|
+// if (degrees == 0f || null == bitmap) {
|
|
|
+// return bitmap
|
|
|
+// }
|
|
|
+// val matrix = Matrix()
|
|
|
+// matrix.setRotate(degrees)
|
|
|
+// val bmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
|
|
|
+// bitmap.recycle()
|
|
|
+// bmp
|
|
|
+// } catch (e: Exception) {
|
|
|
+// null
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 读取图片的旋转的角度
|
|
|
+// *
|
|
|
+// * @param path 图片绝对路径
|
|
|
+// * @return 图片的逆时针旋转角度
|
|
|
+// */
|
|
|
+// @JvmStatic
|
|
|
+// fun getBitmapDegree(path: String?): Int {
|
|
|
+// var degree = 0
|
|
|
+// if (TextUtils.isEmpty(path)) {
|
|
|
+// return degree
|
|
|
+// }
|
|
|
+// return try { // 从指定路径下读取图片,并获取其EXIF信息
|
|
|
+// val exifInterface = ExifInterface(path!!)
|
|
|
+// // 获取图片的旋转信息
|
|
|
+// val orientation = exifInterface.getAttributeInt(
|
|
|
+// ExifInterface.TAG_ORIENTATION,
|
|
|
+// ExifInterface.ORIENTATION_NORMAL
|
|
|
+// )
|
|
|
+// when (orientation) {
|
|
|
+// ExifInterface.ORIENTATION_ROTATE_90 -> degree = 90
|
|
|
+// ExifInterface.ORIENTATION_ROTATE_180 -> degree = 180
|
|
|
+// ExifInterface.ORIENTATION_ROTATE_270 -> degree = 270
|
|
|
+// }
|
|
|
+// degree
|
|
|
+// } catch (e: Exception) {
|
|
|
+// degree
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// @RequiresApi(Build.VERSION_CODES.N)
|
|
|
+// @JvmStatic
|
|
|
+// fun getBitmapDegree(input: InputStream?): Int {
|
|
|
+// var degree = 0
|
|
|
+// if (input == null) {
|
|
|
+// return 0
|
|
|
+// }
|
|
|
+// return try { // 从指定路径下读取图片,并获取其EXIF信息
|
|
|
+// val exifInterface = ExifInterface(input)
|
|
|
+// // 获取图片的旋转信息
|
|
|
+// val orientation = exifInterface.getAttributeInt(
|
|
|
+// ExifInterface.TAG_ORIENTATION,
|
|
|
+// ExifInterface.ORIENTATION_NORMAL
|
|
|
+// )
|
|
|
+// when (orientation) {
|
|
|
+// ExifInterface.ORIENTATION_ROTATE_90 -> degree = 90
|
|
|
+// ExifInterface.ORIENTATION_ROTATE_180 -> degree = 180
|
|
|
+// ExifInterface.ORIENTATION_ROTATE_270 -> degree = 270
|
|
|
+// }
|
|
|
+// degree
|
|
|
+// } catch (e: Exception) {
|
|
|
+// degree
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * @methodName:rotatePicture created by liujiyuan on 2019-12-03 18:06.
|
|
|
+// * @description:把图片的旋转角度变为0,使图片不是颠倒的
|
|
|
+// */
|
|
|
+// @JvmStatic
|
|
|
+// suspend fun rotatePicture(path: String?): Boolean {
|
|
|
+// if (path.isNullOrEmpty()) return false
|
|
|
+//
|
|
|
+// return withContext(Dispatchers.IO) {
|
|
|
+// var bitmap: Bitmap? = getBitmapFromFile(File(path))
|
|
|
+// bitmap?.run {
|
|
|
+// try {
|
|
|
+// bitmap = rotateImage(bitmap, getBitmapDegree(path).toFloat())
|
|
|
+// saveBitmapToFile(bitmap, File(path))
|
|
|
+// } catch (e: Exception) {
|
|
|
+// false
|
|
|
+// } finally {
|
|
|
+// bitmap?.apply { if (!isRecycled) recycle() }
|
|
|
+// }
|
|
|
+// } ?: false
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * @methodName: created by liujiyuan on 2020/7/23 下午2:01.
|
|
|
+// * @description:通过uri把bitmap保存到指定路径
|
|
|
+// */
|
|
|
+// @JvmStatic
|
|
|
+// fun saveBitmapFromUri(context: Context, uri: Uri, path: String?) {
|
|
|
+// try {
|
|
|
+// context.contentResolver.let { resolver ->
|
|
|
+// var degree = 0
|
|
|
+// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
|
+// degree = getBitmapDegree(resolver.openInputStream(uri))
|
|
|
+// }
|
|
|
+// resolver.openFileDescriptor(uri, "r")?.run {
|
|
|
+// var bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor)
|
|
|
+// close()
|
|
|
+// bitmap = rotateImage(bitmap, degree.toFloat())
|
|
|
+// saveBitmapToFile(bitmap, File(path ?: "ø"))
|
|
|
+// }
|
|
|
+// }
|
|
|
+// } catch (e: java.lang.Exception) {
|
|
|
+// e.printStackTrace()
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * @methodName: created by liujiyuan on 2020/11/3 上午9:13.
|
|
|
+// * @description:设置透明背景色
|
|
|
+// */
|
|
|
+// fun createTransparentBitmapFromBitmap(bitmap: Bitmap?, replaceThisColor: Int): Bitmap? {
|
|
|
+// bitmap?.apply {
|
|
|
+// if (isRecycled) {
|
|
|
+// return null
|
|
|
+// }
|
|
|
+// val picw = width
|
|
|
+// val pich = height
|
|
|
+// val pix = IntArray(picw * pich)
|
|
|
+// getPixels(pix, 0, picw, 0, 0, picw, pich)
|
|
|
+// for (y in 0 until pich) {
|
|
|
+// for (x in 0 until picw) {
|
|
|
+// val index = y * picw + x
|
|
|
+// if (pix[index] == replaceThisColor) {
|
|
|
+// pix[index] = Color.TRANSPARENT
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// recycle()
|
|
|
+// return Bitmap.createBitmap(pix, picw, pich, Bitmap.Config.ARGB_8888)
|
|
|
+// }
|
|
|
+// return null
|
|
|
+// }
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * @methodName: created by liujiyuan on 2020/11/3 上午9:13.
|
|
|
+// * @description:压缩图片
|
|
|
+// */
|
|
|
+// fun compressImageForSize(image: Bitmap?, size: Int): Bitmap? {
|
|
|
+// if (image == null || image.isRecycled) {
|
|
|
+// return null
|
|
|
+// }
|
|
|
+// synchronized(image) {
|
|
|
+// val baos = ByteArrayOutputStream()
|
|
|
+// // 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
|
|
|
+// image.compress(Bitmap.CompressFormat.PNG, 100, baos)
|
|
|
+// var options = 100
|
|
|
+// val len: Int = baos.toByteArray().size / 1024
|
|
|
+// if (len > size) {
|
|
|
+// options = options * size / len
|
|
|
+// if (options == 0) {
|
|
|
+// options = 1
|
|
|
+// }
|
|
|
+// }
|
|
|
+// baos.reset() // 重置baos即清空baos
|
|
|
+// // 这里压缩options%,把压缩后的数据存放到baos中
|
|
|
+// image.compress(Bitmap.CompressFormat.PNG, options, baos)
|
|
|
+//
|
|
|
+// // 把压缩后的数据baos存放到ByteArrayInputStream中
|
|
|
+// val isBm = ByteArrayInputStream(baos.toByteArray())
|
|
|
+// // 把ByteArrayInputStream数据生成图片
|
|
|
+// val bitmap = BitmapFactory.decodeStream(isBm, null, null)
|
|
|
+// try {
|
|
|
+// baos.close()
|
|
|
+// } catch (e: IOException) {
|
|
|
+// e.printStackTrace()
|
|
|
+// }
|
|
|
+// try {
|
|
|
+// isBm.close()
|
|
|
+// } catch (e: IOException) {
|
|
|
+// e.printStackTrace()
|
|
|
+// }
|
|
|
+// if (!image.isRecycled) {
|
|
|
+// image.recycle()
|
|
|
+// }
|
|
|
+// return bitmap
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * @methodName: created by liujiyuan on 2020/11/3 上午9:16.
|
|
|
+// * @description:裁剪bitmap
|
|
|
+// */
|
|
|
+// @JvmStatic
|
|
|
+// fun createBitmapFitRect(temp: Bitmap?, width: Float, height: Float): Bitmap? {
|
|
|
+// if (temp == null || temp.isRecycled || width <= 0 || height <= 0) {
|
|
|
+// return null
|
|
|
+// }
|
|
|
+// val imageHeight = temp.height
|
|
|
+// val imageWidth = temp.width
|
|
|
+// //String imageType = options.outMimeType;
|
|
|
+// val radio: Float = when {
|
|
|
+// imageHeight / height > imageWidth / width -> height / imageHeight
|
|
|
+// else -> width / imageWidth
|
|
|
+// }
|
|
|
+// val matrix = Matrix()
|
|
|
+// matrix.preScale(radio, radio)
|
|
|
+// return Bitmap.createBitmap(temp, 0, 0, imageWidth, imageHeight, matrix, true)
|
|
|
+// }
|
|
|
+//
|
|
|
+// fun fitBitmap(target: Bitmap?, newWidth: Int, isRecycle: Boolean): Bitmap? {
|
|
|
+// var bmp: Bitmap? = null
|
|
|
+// target?.run {
|
|
|
+// val width = width
|
|
|
+// val height = height
|
|
|
+// val matrix = Matrix()
|
|
|
+// val scaleWidth = newWidth.toFloat() / width
|
|
|
+// matrix.postScale(scaleWidth, scaleWidth)
|
|
|
+// bmp = Bitmap.createBitmap(
|
|
|
+// this, 0, 0, width, height, matrix,
|
|
|
+// true
|
|
|
+// )
|
|
|
+// if (isRecycle) if (this != bmp && !isRecycled) recycle()
|
|
|
+// }
|
|
|
+// return bmp
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 缩放图片
|
|
|
+// */
|
|
|
+// fun scaleImage(bitmap: Bitmap?, width : Int) : Bitmap?{
|
|
|
+// if (bitmap == null){
|
|
|
+// return null
|
|
|
+// }
|
|
|
+//
|
|
|
+// val scale = (width * 1F) / bitmap.width
|
|
|
+// if (scale > 1){
|
|
|
+// return bitmap
|
|
|
+// }
|
|
|
+// return scaleImage(bitmap, scale, scale)
|
|
|
+//
|
|
|
+// }
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 图片缩放
|
|
|
+// *
|
|
|
+// * @param bitmap
|
|
|
+// * @param sx
|
|
|
+// * @param sy
|
|
|
+// * @return
|
|
|
+// */
|
|
|
+// fun scaleImage(bitmap: Bitmap?, sx: Float, sy: Float): Bitmap? {
|
|
|
+// if (bitmap == null) {
|
|
|
+// return null
|
|
|
+// }
|
|
|
+// val matrix = Matrix()
|
|
|
+// matrix.setScale(sx, sy)
|
|
|
+// return Bitmap.createBitmap(
|
|
|
+// bitmap, 0, 0, bitmap.width,
|
|
|
+// bitmap.height, matrix, false
|
|
|
+// )
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+// fun rotateImageCanvas(bm: Bitmap, orientationDegree: Int): Bitmap? {
|
|
|
+// val m = Matrix()
|
|
|
+// m.setRotate(orientationDegree.toFloat(), bm.width.toFloat() / 2, bm.height.toFloat() / 2)
|
|
|
+// val targetX: Float
|
|
|
+// val targetY: Float
|
|
|
+// if (orientationDegree == 90) {
|
|
|
+// targetX = bm.height.toFloat()
|
|
|
+// targetY = 0f
|
|
|
+// } else {
|
|
|
+// targetX = bm.height.toFloat()
|
|
|
+// targetY = bm.width.toFloat()
|
|
|
+// }
|
|
|
+// val values = FloatArray(9)
|
|
|
+// m.getValues(values)
|
|
|
+// val x1 = values[Matrix.MTRANS_X]
|
|
|
+// val y1 = values[Matrix.MTRANS_Y]
|
|
|
+// m.postTranslate(targetX - x1, targetY - y1)
|
|
|
+// val bm1 = Bitmap.createBitmap(bm.height, bm.width, Bitmap.Config.ARGB_8888)
|
|
|
+// val paint = Paint()
|
|
|
+// val canvas = Canvas(bm1)
|
|
|
+// canvas.drawBitmap(bm, m, paint)
|
|
|
+// return bm1
|
|
|
+// }
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 获取圆形图片
|
|
|
+// *
|
|
|
+// * @param bitmap
|
|
|
+// * @param length 返回图片的宽高
|
|
|
+// * @param l 图片粘贴的左上角位置
|
|
|
+// * @param t
|
|
|
+// * @return
|
|
|
+// */
|
|
|
+// fun getRoundedCornerBitmap(context: Context?, bitmap: Bitmap?, length: Int, l: Int, t: Int): Bitmap? {
|
|
|
+// if (bitmap == null) {
|
|
|
+// return null
|
|
|
+// }
|
|
|
+// val output = Bitmap.createBitmap(length, length, Bitmap.Config.ARGB_8888)
|
|
|
+// val canvas = Canvas(output)
|
|
|
+// val color = -0x1000000
|
|
|
+// val paint = Paint()
|
|
|
+// val rect = Rect(0, 0, length, length)
|
|
|
+// val rectF = RectF(rect)
|
|
|
+// val roundPx = length * 0.5f
|
|
|
+// paint.isAntiAlias = true
|
|
|
+// canvas.drawARGB(0, 0, 0, 0)
|
|
|
+// paint.color = color
|
|
|
+// canvas.drawRoundRect(rectF, roundPx, roundPx, paint)
|
|
|
+// paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
|
|
|
+// canvas.drawBitmap(bitmap, l.toFloat(), t.toFloat(), paint)
|
|
|
+// paint.color = Color.GREEN
|
|
|
+// val len = 10
|
|
|
+// canvas.drawLine((length / 2 - len).toFloat(), (length / 2).toFloat(), (length / 2 + len).toFloat(), (length / 2).toFloat(), paint)
|
|
|
+// canvas.drawLine((length / 2).toFloat(), (length / 2 - len).toFloat(), (length / 2).toFloat(), (length / 2 + len).toFloat(), paint)
|
|
|
+// paint.strokeWidth = 2 * getDensity(context)
|
|
|
+// paint.color = Color.WHITE
|
|
|
+// paint.style = Paint.Style.STROKE
|
|
|
+// canvas.drawCircle((length / 2).toFloat(), (length / 2).toFloat(), length / 2 - 1 * getDensity(context), paint)
|
|
|
+// return output
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 图片灰度处理
|
|
|
+// *
|
|
|
+// * @param bitmap
|
|
|
+// * @return
|
|
|
+// */
|
|
|
+// fun greyscale(bitmap: Bitmap?): Bitmap? {
|
|
|
+// if (bitmap == null) {
|
|
|
+// return null
|
|
|
+// }
|
|
|
+// val colorMatrix = ColorMatrix()
|
|
|
+// colorMatrix.setSaturation(0f)
|
|
|
+// val width = bitmap.width
|
|
|
+// val height = bitmap.height
|
|
|
+// val buffer: Bitmap
|
|
|
+// try {
|
|
|
+// buffer = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
|
|
|
+// val canvas = Canvas(buffer)
|
|
|
+// val paint = Paint()
|
|
|
+// paint.colorFilter = ColorMatrixColorFilter(colorMatrix)
|
|
|
+// canvas.drawBitmap(bitmap, 0f, 0f, paint)
|
|
|
+// } catch (e: java.lang.Exception) {
|
|
|
+// e.printStackTrace()
|
|
|
+// return bitmap
|
|
|
+// }
|
|
|
+// return buffer
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 图片透明度处理
|
|
|
+// *
|
|
|
+// * @param bitmap 原始图片
|
|
|
+// * @param alpha 透明度
|
|
|
+// * @return
|
|
|
+// */
|
|
|
+// fun setAlpha(bitmap: Bitmap?, alpha: Int): Bitmap? {
|
|
|
+// if (bitmap == null) {
|
|
|
+// return null
|
|
|
+// }
|
|
|
+// val argb = IntArray(bitmap.width * bitmap.height)
|
|
|
+// bitmap.getPixels(
|
|
|
+// argb, 0, bitmap.width, 0, 0, bitmap.width,
|
|
|
+// bitmap.height
|
|
|
+// ) // 获得图片的ARGB值
|
|
|
+// var al: Int
|
|
|
+// for (i in argb.indices) {
|
|
|
+// al = (Color.alpha(argb[i]) * alpha / 100f).toInt()
|
|
|
+// argb[i] = al shl 24 or (argb[i] and 0x00FFFFFF) // 修改最高2位的值
|
|
|
+// }
|
|
|
+// return Bitmap.createBitmap(
|
|
|
+// argb, bitmap.width,
|
|
|
+// bitmap.height, Bitmap.Config.ARGB_8888
|
|
|
+// )
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 图片进行亮度和对比度的处理
|
|
|
+// *
|
|
|
+// * @param src
|
|
|
+// * @param light
|
|
|
+// * @param contrast
|
|
|
+// * @return
|
|
|
+// */
|
|
|
+// fun filter(src: Bitmap?, light: Int, contrast: Int): Bitmap? {
|
|
|
+// if (src == null) {
|
|
|
+// return null
|
|
|
+// }
|
|
|
+// return if (light == -1 && contrast == -1) { //默认值
|
|
|
+// src
|
|
|
+// } else {
|
|
|
+// val width = src.width
|
|
|
+// val height = src.height
|
|
|
+// val b = light / 50f
|
|
|
+// val c = (contrast + 20) / 40f
|
|
|
+// val inPixels: IntArray
|
|
|
+// val outPixels: IntArray
|
|
|
+// try {
|
|
|
+// inPixels = IntArray(width * height)
|
|
|
+// outPixels = IntArray(width * height)
|
|
|
+// } catch (e: OutOfMemoryError) {
|
|
|
+// // TODO Auto-generated catch block
|
|
|
+// e.printStackTrace()
|
|
|
+// return src
|
|
|
+// }
|
|
|
+// src.getPixels(inPixels, 0, width, 0, 0, width, height)
|
|
|
+//
|
|
|
+// // calculate RED, GREEN, BLUE means of pixel
|
|
|
+// var index = 0
|
|
|
+// val rgbmeans = IntArray(3)
|
|
|
+// var redSum = 0.0
|
|
|
+// var greenSum = 0.0
|
|
|
+// var blueSum = 0.0
|
|
|
+// val total = (height * width).toDouble()
|
|
|
+// for (row in 0 until height) {
|
|
|
+// // int ta = 0;
|
|
|
+// var tr = 0
|
|
|
+// var tg = 0
|
|
|
+// var tb = 0
|
|
|
+// for (col in 0 until width) {
|
|
|
+// index = row * width + col
|
|
|
+// // ta = (inPixels[index] >> 24) & 0xff;
|
|
|
+// tr = inPixels[index] shr 16 and 0xff
|
|
|
+// tg = inPixels[index] shr 8 and 0xff
|
|
|
+// tb = inPixels[index] and 0xff
|
|
|
+// redSum += tr.toDouble()
|
|
|
+// greenSum += tg.toDouble()
|
|
|
+// blueSum += tb.toDouble()
|
|
|
+// }
|
|
|
+// }
|
|
|
+// rgbmeans[0] = (redSum / total).toInt()
|
|
|
+// rgbmeans[1] = (greenSum / total).toInt()
|
|
|
+// rgbmeans[2] = (blueSum / total).toInt()
|
|
|
+//
|
|
|
+// // adjust contrast and brightness algorithm, here
|
|
|
+// for (row in 0 until height) {
|
|
|
+// var ta = 0
|
|
|
+// var tr = 0
|
|
|
+// var tg = 0
|
|
|
+// var tb = 0
|
|
|
+// for (col in 0 until width) {
|
|
|
+// index = row * width + col
|
|
|
+// ta = inPixels[index] shr 24 and 0xff
|
|
|
+// tr = inPixels[index] shr 16 and 0xff
|
|
|
+// tg = inPixels[index] shr 8 and 0xff
|
|
|
+// tb = inPixels[index] and 0xff
|
|
|
+//
|
|
|
+// // remove means
|
|
|
+// tr -= rgbmeans[0]
|
|
|
+// tg -= rgbmeans[1]
|
|
|
+// tb -= rgbmeans[2]
|
|
|
+//
|
|
|
+// // adjust contrast now !!!
|
|
|
+// tr = (tr * c).toInt()
|
|
|
+// tg = (tg * c).toInt()
|
|
|
+// tb = (tb * c).toInt()
|
|
|
+//
|
|
|
+// // adjust brightness
|
|
|
+// tr += (rgbmeans[0] * b).toInt()
|
|
|
+// tg += (rgbmeans[1] * b).toInt()
|
|
|
+// tb += (rgbmeans[2] * b).toInt()
|
|
|
+// outPixels[index] = (ta shl 24 or (clamp(tr) shl 16)
|
|
|
+// or (clamp(tg) shl 8) or clamp(tb))
|
|
|
+// }
|
|
|
+// }
|
|
|
+// val dest: Bitmap
|
|
|
+// dest = try {
|
|
|
+// Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
|
|
+// } catch (e: OutOfMemoryError) {
|
|
|
+// // TODO Auto-generated catch block
|
|
|
+// e.printStackTrace()
|
|
|
+// return null
|
|
|
+// }
|
|
|
+// dest.setPixels(outPixels, 0, width, 0, 0, width, height)
|
|
|
+// dest
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// fun clamp(value: Int): Int {
|
|
|
+// return if (value > 255) 255 else if (value < 0) 0 else value
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 二值化处理
|
|
|
+// *
|
|
|
+// * @param img
|
|
|
+// * @return
|
|
|
+// */
|
|
|
+// fun binarization(img: Bitmap?): Bitmap? {
|
|
|
+// if (img == null) {
|
|
|
+// return null
|
|
|
+// }
|
|
|
+// val width = img.width
|
|
|
+// val height = img.height
|
|
|
+// val area = width * height
|
|
|
+// val gray = Array(width) { IntArray(height) }
|
|
|
+// var average = 0 // 灰度平均值
|
|
|
+// var graysum = 0
|
|
|
+// var graymean = 0
|
|
|
+// var grayfrontmean = 0
|
|
|
+// var graybackmean = 0
|
|
|
+// var pixelGray: Int
|
|
|
+// var front = 0
|
|
|
+// var back = 0
|
|
|
+// val pix = IntArray(width * height)
|
|
|
+// img.getPixels(pix, 0, width, 0, 0, width, height)
|
|
|
+// for (i in 1 until width) { // 不算边界行和列,为避免越界
|
|
|
+// for (j in 1 until height) {
|
|
|
+// val x = j * width + i
|
|
|
+// val r = pix[x] shr 16 and 0xff
|
|
|
+// val g = pix[x] shr 8 and 0xff
|
|
|
+// val b = pix[x] and 0xff
|
|
|
+// pixelGray = (0.3 * r + 0.59 * g + 0.11 * b).toInt() // 计算每个坐标点的灰度
|
|
|
+// gray[i][j] = (pixelGray shl 16) + (pixelGray shl 8) + pixelGray
|
|
|
+// graysum += pixelGray
|
|
|
+// }
|
|
|
+// }
|
|
|
+// graymean = graysum / area // 整个图的灰度平均值
|
|
|
+// average = graymean
|
|
|
+// for (i in 0 until width) { // 计算整个图的二值化阈值
|
|
|
+// for (j in 0 until height) {
|
|
|
+// if (gray[i][j] and 0x0000ff < graymean) {
|
|
|
+// graybackmean += gray[i][j] and 0x0000ff
|
|
|
+// back++
|
|
|
+// } else {
|
|
|
+// grayfrontmean += gray[i][j] and 0x0000ff
|
|
|
+// front++
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// var frontvalue = 0
|
|
|
+// var backvalue = 0
|
|
|
+// if (front <= 0 || back <= 0) {
|
|
|
+// return img
|
|
|
+// }
|
|
|
+// frontvalue = grayfrontmean / front // 前景中心
|
|
|
+// backvalue = graybackmean / back // 背景中心
|
|
|
+// val G = FloatArray(frontvalue - backvalue + 1) // 方差数组
|
|
|
+// var s = 0
|
|
|
+// for (i1 in backvalue until frontvalue + 1) // 以前景中心和背景中心为区间采用大津法算法(OTSU算法)
|
|
|
+// {
|
|
|
+// back = 0
|
|
|
+// front = 0
|
|
|
+// grayfrontmean = 0
|
|
|
+// graybackmean = 0
|
|
|
+// for (i in 0 until width) {
|
|
|
+// for (j in 0 until height) {
|
|
|
+// if (gray[i][j] and 0x0000ff < i1 + 1) {
|
|
|
+// graybackmean += gray[i][j] and 0x0000ff
|
|
|
+// back++
|
|
|
+// } else {
|
|
|
+// grayfrontmean += gray[i][j] and 0x0000ff
|
|
|
+// front++
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// if (front <= 0 || back <= 0) {
|
|
|
+// return img
|
|
|
+// }
|
|
|
+// grayfrontmean = grayfrontmean / front
|
|
|
+// graybackmean = graybackmean / back
|
|
|
+// G[s] = (back.toFloat() / area * (graybackmean - average)
|
|
|
+// * (graybackmean - average)) + (front.toFloat() / area
|
|
|
+// * (grayfrontmean - average) * (grayfrontmean - average))
|
|
|
+// s++
|
|
|
+// }
|
|
|
+// var max = G[0]
|
|
|
+// var index = 0
|
|
|
+// for (i in 1 until frontvalue - backvalue + 1) {
|
|
|
+// if (max < G[i]) {
|
|
|
+// max = G[i]
|
|
|
+// index = i
|
|
|
+// }
|
|
|
+// }
|
|
|
+// for (i in 0 until width) {
|
|
|
+// for (j in 0 until height) {
|
|
|
+// val `in` = j * width + i
|
|
|
+// if (gray[i][j] and 0x0000ff < index + backvalue) {
|
|
|
+// pix[`in`] = Color.rgb(0, 0, 0)
|
|
|
+// } else {
|
|
|
+// pix[`in`] = Color.rgb(255, 255, 255)
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// val temp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
|
|
|
+// temp.setPixels(pix, 0, width, 0, 0, width, height)
|
|
|
+// return temp
|
|
|
+// }
|
|
|
+//
|
|
|
+// fun getTintDrawableList(context: Context?, srcResourceId: Int, colorResId: Int, colorPressedResId: Int): Drawable? {
|
|
|
+// var drawable = ContextCompat.getDrawable(context!!, srcResourceId)
|
|
|
+// val colors = intArrayOf(
|
|
|
+// ContextCompat.getColor(context, colorPressedResId),
|
|
|
+// ContextCompat.getColor(context, colorPressedResId),
|
|
|
+// ContextCompat.getColor(context, colorResId)
|
|
|
+// )
|
|
|
+// val states = arrayOfNulls<IntArray>(3)
|
|
|
+// states[0] = intArrayOf(R.attr.state_pressed)
|
|
|
+// states[1] = intArrayOf(R.attr.state_selected)
|
|
|
+// states[2] = intArrayOf()
|
|
|
+// val colorList = ColorStateList(states, colors)
|
|
|
+// val stateListDrawable = StateListDrawable()
|
|
|
+// stateListDrawable.addState(states[0], drawable) //注意顺序
|
|
|
+// stateListDrawable.addState(states[1], drawable)
|
|
|
+// stateListDrawable.addState(states[2], drawable)
|
|
|
+// val state = stateListDrawable.constantState
|
|
|
+// drawable = DrawableCompat.wrap(state?.newDrawable() ?: stateListDrawable).mutate()
|
|
|
+// DrawableCompat.setTintList(drawable, colorList)
|
|
|
+// drawable.setBounds(0, 0, drawable.minimumWidth, drawable.minimumHeight)
|
|
|
+// return drawable
|
|
|
+// }
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * @param:
|
|
|
+// * @author: luozhipeng
|
|
|
+// * @Decreption:通过tint实现图片selector
|
|
|
+// * @create at: 8/8/16 16:17
|
|
|
+// */
|
|
|
+// fun setTintDrawableList(context: Context?, view: View?, srcResourceId: Int, colorResId: Int, colorPressedResId: Int) {
|
|
|
+// var drawable = ContextCompat.getDrawable(context!!, srcResourceId)
|
|
|
+// val colors = intArrayOf(
|
|
|
+// ContextCompat.getColor(context, colorPressedResId),
|
|
|
+// ContextCompat.getColor(context, colorPressedResId),
|
|
|
+// ContextCompat.getColor(context, colorResId)
|
|
|
+// )
|
|
|
+// val states = arrayOfNulls<IntArray>(3)
|
|
|
+// states[0] = intArrayOf(R.attr.state_pressed)
|
|
|
+// states[1] = intArrayOf(R.attr.state_selected)
|
|
|
+// states[2] = intArrayOf()
|
|
|
+// val colorList = ColorStateList(states, colors)
|
|
|
+// val stateListDrawable = StateListDrawable()
|
|
|
+// stateListDrawable.addState(states[0], drawable) //注意顺序
|
|
|
+// stateListDrawable.addState(states[1], drawable)
|
|
|
+// stateListDrawable.addState(states[2], drawable)
|
|
|
+// val state = stateListDrawable.constantState
|
|
|
+// drawable = DrawableCompat.wrap(state?.newDrawable() ?: stateListDrawable).mutate()
|
|
|
+// DrawableCompat.setTintList(drawable, colorList)
|
|
|
+// drawable.setBounds(0, 0, drawable.minimumWidth, drawable.minimumHeight)
|
|
|
+// if (view is AppCompatImageView) {
|
|
|
+// view.setImageDrawable(drawable)
|
|
|
+// }
|
|
|
+// if (view is ImageView) {
|
|
|
+// view.setImageDrawable(drawable)
|
|
|
+// }
|
|
|
+// if (view is AppCompatImageButton) {
|
|
|
+// view.setImageDrawable(drawable)
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * bitmap文件是否可用
|
|
|
+// */
|
|
|
+// fun bitmapFileIsAvailable(bitmapFilePath : String) : Boolean{
|
|
|
+// return try {
|
|
|
+// val options = BitmapFactory.Options()
|
|
|
+// options.inJustDecodeBounds = false
|
|
|
+// val bitmap = BitmapFactory.decodeFile(bitmapFilePath, options)
|
|
|
+// bitmap != null
|
|
|
+// }catch (e : Exception){
|
|
|
+// false
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+//}
|