当您从意图中获取路径时,请使用它。CompressBitMap().execute(Uri.fromFile(File(mImagePath)))
inner class CompressBitMap : AsyncTask<Uri, Int, File>() {
override fun doInBackground(vararg p0: Uri?): File? {
val bitmap: Bitmap?
val filename = "${Date().time}profile.png"
val fileDir = File(Environment.getExternalStorageDirectory(), getString(R.string.app_name))
if (!fileDir.exists()) {
fileDir.mkdir()
}
val destPath = File(fileDir, filename)
val outPutStream = FileOutputStream(destPath)
try {
bitmap = ScaledPicture(p0[0], activity.contentResolver).getBitmap(400, 400)
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outPutStream)
outPutStream.flush()
outPutStream.close()
} catch (e: Exception) {
e.printStackTrace()
}
return destPath
}
override fun onPostExecute(result: File?) {
super.onPostExecute(result)
result?.let {
mImagePath = result.absolutePath
setProfileImage(mImagePath, image_circle, null)
}
}
}
ScaledPicture 和 ImageScalingUtil 是减小图像大小的两个重要类。
比例图片:=>
import android.content.ContentResolver
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.graphics.RectF
import android.media.ExifInterface
import android.net.Uri
import com.silverskysoft.skysalon.imageUtils.ImageScalingUtils
import java.io.FileNotFoundException
import java.io.IOException
import java.io.InvalidObjectException
class ScaledPicture(private var uri: Uri?, private var resolver: ContentResolver) {
private var path: String? = null
private var orientation: Matrix? = null
private var storedHeight: Int = 0
private var storedWidth: Int = 0
@Throws(IOException::class)
private fun getInformation(): Boolean {
/*if (getInformationFromMediaDatabase())
return true;*/
return getInformationFromFileSystem()
}
/* Support for file managers and dropbox */
@Throws(IOException::class)
private fun getInformationFromFileSystem(): Boolean {
path = uri?.path
if (path == null)
return false
val exif = ExifInterface(path.toString())
val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL)
this.orientation = Matrix()
when (orientation) {
ExifInterface.ORIENTATION_NORMAL -> {
}
ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> this.orientation?.setScale(-1f, 1f)
ExifInterface.ORIENTATION_ROTATE_180 -> this.orientation?.setRotate(180f)
ExifInterface.ORIENTATION_FLIP_VERTICAL -> this.orientation?.setScale(1f, -1f)
ExifInterface.ORIENTATION_TRANSPOSE -> {
this.orientation?.setRotate(90f)
this.orientation?.postScale(-1f, 1f)
}
ExifInterface.ORIENTATION_ROTATE_90 -> this.orientation?.setRotate(90f)
ExifInterface.ORIENTATION_TRANSVERSE -> {
this.orientation?.setRotate(-90f)
this.orientation?.postScale(-1f, 1f)
}
ExifInterface.ORIENTATION_ROTATE_270 -> this.orientation?.setRotate(-90f)
}/* Identity matrix */
return true
}
@Throws(IOException::class)
private fun getStoredDimensions(): Boolean {
val input = resolver.openInputStream(uri)
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options)
/* The input stream could be reset instead of closed and reopened if it were possible
to reliably wrap the input stream on a buffered stream, but it's not possible because
decodeStream() places an upper read limit of 1024 bytes for a reset to be made (it calls
mark(1024) on the stream). */
input?.close()
if (options.outHeight <= 0 || options.outWidth <= 0)
return false
storedHeight = options.outHeight
storedWidth = options.outWidth
return true
}
@Throws(IOException::class)
fun getBitmap(reqWidth: Int, reqHeight: Int): Bitmap {
val heightWidth = 1000
if (!getInformation())
throw FileNotFoundException()
if (!getStoredDimensions())
throw InvalidObjectException(null)
val rect = RectF(0f, 0f, storedWidth.toFloat(), storedHeight.toFloat())
orientation?.mapRect(rect)
var width = rect.width().toInt()
var height = rect.height().toInt()
var subSample = 1
while (width > heightWidth || height > heightWidth) {
width /= 2
height /= 2
subSample *= 2
}
if (width == 0 || height == 0)
throw InvalidObjectException(null)
val options = BitmapFactory.Options()
options.inSampleSize = subSample
val subSampled = BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options)
val picture: Bitmap
if (orientation?.isIdentity == false) {
picture = Bitmap.createBitmap(subSampled, 0, 0, options.outWidth, options.outHeight,
orientation, false)
subSampled.recycle()
} else
picture = subSampled
return ImageScalingUtils.decodeBitmap(picture, reqWidth, reqHeight, ImageScalingUtils.ScalingLogic.CROP)
}
}
ImageScalingUtils:=>
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import java.io.ByteArrayOutputStream
/**
* Created by Avinash on 7/8/19.
* ImageScalingUtils responsible for compressing the bitmap efficiently
*/
object ImageScalingUtils {
/**
* Utility function for decoding an image resource. The decoded bitmap will
* be optimized for further scaling to the requested destination dimensions
* and scaling logic.
*
* @param dstWidth Width of destination area
* @param dstHeight Height of destination area
* @param scalingLogic Logic to use to avoid image stretching
* @return Decoded bitmap
*/
fun decodeBitmap(bm: Bitmap, dstWidth: Int, dstHeight: Int,
scalingLogic: ScalingLogic): Bitmap {
val stream = ByteArrayOutputStream()
bm.compress(Bitmap.CompressFormat.PNG, 100, stream)
val byteArray = stream.toByteArray()
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size, options)
options.inJustDecodeBounds = false
options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,
dstHeight, scalingLogic)
return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size, options)
}
/**
* ScalingLogic defines how scaling should be carried out if source and
* destination image has different aspect ratio.
*
* CROP: Scales the image the minimum amount while making sure that at least
* one of the two dimensions fit inside the requested destination area.
* Parts of the source image will be cropped to realize this.
*
* FIT: Scales the image the minimum amount while making sure both
* dimensions fit inside the requested destination area. The resulting
* destination dimensions might be adjusted to a smaller size than
* requested.
*/
enum class ScalingLogic {
CROP, FIT
}
/**
* Calculate optimal down-sampling factor given the dimensions of a source
* image, the dimensions of a destination area and a scaling logic.
*
* @param srcWidth Width of source image
* @param srcHeight Height of source image
* @param dstWidth Width of destination area
* @param dstHeight Height of destination area
* @param scalingLogic Logic to use to avoid image stretching
* @return Optimal down scaling sample size for decoding
*/
private fun calculateSampleSize(srcWidth: Int, srcHeight: Int, dstWidth: Int, dstHeight: Int,
scalingLogic: ScalingLogic): Int {
if (scalingLogic == ScalingLogic.FIT) {
val srcAspect = srcWidth.toFloat() / srcHeight.toFloat()
val dstAspect = dstWidth.toFloat() / dstHeight.toFloat()
return if (srcAspect > dstAspect) {
srcWidth / dstWidth
} else {
srcHeight / dstHeight
}
} else {
val srcAspect = srcWidth.toFloat() / srcHeight.toFloat()
val dstAspect = dstWidth.toFloat() / dstHeight.toFloat()
return if (srcAspect > dstAspect) {
srcHeight / dstHeight
} else {
srcWidth / dstWidth
}
}
}
}