图片
XML
文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.gallery20.app.MyImageView
android:id="@+id/real_iv"
android:layout_gravity="center"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_marginTop="30dp"
android:layout_marginBottom="30dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:background="#00000000"/>
</LinearLayout>
Activity
代码
fun getBitmap(resources : Resources, destRect : RectF, imageId: Int): Bitmap? {
var imageWidth = -1
var imageHeight = -1
val preOption = BitmapFactory.Options().apply {
// 只获取图片的宽高
inJustDecodeBounds = true
BitmapFactory.decodeResource(resources, imageId, this)
}
imageWidth = preOption.outWidth
imageHeight = preOption.outHeight
// 计算缩放比例
val scaleMatrix = Matrix()
// 确定未缩放Bitmap的RectF
var srcRect = RectF(0f, 0f, imageWidth.toFloat(), imageHeight.toFloat())
// 通过目标RectF, 确定缩放数值,存储在scaleMatrix中
scaleMatrix.setRectToRect(srcRect, destRect, Matrix.ScaleToFit.CENTER)
// 缩放数值再映射到原始Bitmap上,得到缩放后的RectF
scaleMatrix.mapRect(srcRect)
val finalOption = BitmapFactory.Options().apply {
if (imageHeight > 0 && imageWidth > 0) {
inPreferredConfig = Bitmap.Config.RGB_565
inSampleSize = calculateInSampleSize(
imageWidth,
imageHeight,
srcRect.width().toInt(),
srcRect.height().toInt()
)
Log.i("yang", "inSampleSize = $inSampleSize")
}
}
return BitmapFactory.decodeResource(resources, imageId, finalOption)
}
fun calculateInSampleSize(fromWidth: Int, fromHeight: Int, toWidth: Int, toHeight: Int): Int {
var bitmapWidth = fromWidth
var bitmapHeight = fromHeight
if (fromWidth > toWidth|| fromHeight > toHeight) {
var inSampleSize = 2
// 计算最大的inSampleSize值,该值是2的幂,并保持原始宽高大于目标宽高
while (bitmapWidth >= toWidth && bitmapHeight >= toHeight) {
bitmapWidth /= 2
bitmapHeight /= 2
inSampleSize *= 2
}
return inSampleSize
}
return 1
}
const val TAG = "Yang"
class MainActivity : AppCompatActivity() {
var mRealView: MyImageView? = null
var tempBitmap: Bitmap? = null
var screenWidth = 0
var screenHeight = 0
var mDestRect = RectF()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mRealView = findViewById(R.id.real_iv)
// 屏幕宽高的一半作为临时RectF, 用于压缩Bitmap
screenWidth = resources.displayMetrics.widthPixels
screenHeight = resources.displayMetrics.heightPixels
val tempRect = RectF(0f, 0f, screenWidth.toFloat() / 2, screenHeight.toFloat() / 2)
CoroutineScope(Dispatchers.IO).launch {
tempBitmap = getBitmap(resources, tempRect, R.drawable.fake)
withContext(Dispatchers.Main) {
mRealView?.post {
mDestRect.set(
0f,
0f,
mRealView?.width?.toFloat()!!,
mRealView?.height?.toFloat()!!
)
tempBitmap?.let {
mRealView?.setBitmap(it, mDestRect)
}
}
}
}
}
}
自定义View
代码
class MyImageView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr){
private val mPaint = Paint().apply {
isAntiAlias = true
}
private var mBitmap : Bitmap? = null
private var mDestRect : RectF = RectF()
fun setBitmap(bitmap : Bitmap, destRect: RectF){
mBitmap = bitmap
mDestRect.set(destRect)
invalidate()
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
Log.i("yang", "canvas.width = ${canvas?.width}, canvas.height = ${canvas?.height}")
Log.i("yang", "mBitmap.width = ${mBitmap?.width} mBitmap.height = ${mBitmap?.height}")
Log.i("yang", "mDestRect.width = ${mDestRect.width()} mDestRect.height = ${mDestRect.height()} mDestRect = $mDestRect")
mBitmap?.let {
canvas?.drawBitmap(it, null, mDestRect, mPaint)
}
}
}
RectF
大小和Bitmap
大小的绘制关系
RectF
的宽高大于Bitmap
的宽高
Bitmap
会被拉伸至整个RectF
区域,不会被裁剪
RectF
没有加上left
和top
- 使用完整大小的
RectF
区域,绘制的是整张Bitmap
CoroutineScope(Dispatchers.IO).launch {
tempBitmap = getBitmap(resources, tempRect, R.drawable.fake)
withContext(Dispatchers.Main) {
mRealView?.post {
mDestRect.set(
0f,
0f,
mRealView?.width?.toFloat()!!,
mRealView?.height?.toFloat()!!
)
tempBitmap?.let {
mRealView?.setBitmap(it, mDestRect)
}
}
}
}
// log reult
2024-06-04 04:48:19.010 9873-9873 yang I canvas.width = 900, canvas.height = 900
2024-06-04 04:48:19.010 9873-9873 yang I mBitmap.width = 768 mBitmap.height = 768
2024-06-04 04:48:19.010 9873-9873 yang I mDestRect.width = 900.0 mDestRect.height = 900.0 mDestRect = RectF(0.0, 0.0, 900.0, 900.0)
RectF
加上left
和top
- 在完整的
RectF
区域上,进行了向左和向下的偏移,绘制的是经过裁剪的Bitmap
CoroutineScope(Dispatchers.IO).launch {
tempBitmap = getBitmap(resources, tempRect, R.drawable.fake)
withContext(Dispatchers.Main) {
mRealView?.post {
mDestRect.set(
mRealView?.left?.toFloat()!!,
mRealView?.top?.toFloat()!!,
mRealView?.left?.toFloat()!! + mRealView?.width?.toFloat()!!,
mRealView?.top?.toFloat()!! + mRealView?.height?.toFloat()!!
)
tempBitmap?.let {
mRealView?.setBitmap(it, mDestRect)
}
}
}
}
// log result
2024-06-04 04:50:49.826 10194-10194 yang I canvas.width = 900, canvas.height = 900
2024-06-04 04:50:49.826 10194-10194 yang I mBitmap.width = 768 mBitmap.height = 768
2024-06-04 04:50:49.826 10194-10194 yang I mDestRect.width = 900.0 mDestRect.height = 900.0 mDestRect = RectF(90.0, 90.0, 990.0, 990.0)
RectF
的宽高小于Bitmap
的宽高
Bitmap
会被缩小至整个RectF
区域,不会被裁剪
RectF
没有加上left
和top
- 使用完整大小的
RectF
区域,绘制的是整张Bitmap
CoroutineScope(Dispatchers.IO).launch {
tempBitmap = getBitmap(resources, tempRect, R.drawable.fake)
withContext(Dispatchers.Main) {
mRealView?.post {
mDestRect.set(
0f,
0f,
mRealView?.width?.toFloat()!!,
mRealView?.height?.toFloat()!!
)
tempBitmap?.let {
mRealView?.setBitmap(it, mDestRect)
}
}
}
}
// log result
2024-06-04 04:57:15.407 11029-11029 yang I canvas.width = 900, canvas.height = 900
2024-06-04 04:57:15.407 11029-11029 yang I mBitmap.width = 3075 mBitmap.height = 3075
2024-06-04 04:57:15.407 11029-11029 yang I mDestRect.width = 900.0 mDestRect.height = 900.0 mDestRect = RectF(0.0, 0.0, 900.0, 900.0)
RectF
加上left
和top
- 在完整的
RectF
区域上,进行了向左和向下的偏移,绘制的是经过裁剪的Bitmap
CoroutineScope(Dispatchers.IO).launch {
tempBitmap = getBitmap(resources, tempRect, R.drawable.fake)
withContext(Dispatchers.Main) {
mRealView?.post {
mDestRect.set(
mRealView?.left?.toFloat()!!,
mRealView?.top?.toFloat()!!,
mRealView?.left?.toFloat()!! + mRealView?.width?.toFloat()!!,
mRealView?.top?.toFloat()!! + mRealView?.height?.toFloat()!!
)
tempBitmap?.let {
mRealView?.setBitmap(it, mDestRect)
}
}
}
}
// log result
2024-06-04 05:04:36.477 11296-11296 yang I canvas.width = 900, canvas.height = 900
2024-06-04 05:04:36.477 11296-11296 yang I mBitmap.width = 3075 mBitmap.height = 3075
2024-06-04 05:04:36.477 11296-11296 yang I mDestRect.width = 900.0 mDestRect.height = 900.0 mDestRect = RectF(90.0, 90.0, 990.0, 990.0)
RectF
的宽高等于Bitmap
的宽高
View
的Canvas
大小小于目标绘制RectF
大小,只能绘制Canvas
对应宽高的区域,所以只能绘制Bitmap
的左上角区域
CoroutineScope(Dispatchers.IO).launch {
tempBitmap = getBitmap(resources, tempRect, R.drawable.fake)
withContext(Dispatchers.Main) {
mRealView?.post {
mDestRect.set(
0f,
0f,
tempBitmap?.width?.toFloat()!!,
tempBitmap?.height?.toFloat()!!
)
tempBitmap?.let {
mRealView?.setBitmap(it, mDestRect)
}
}
}
}
// log result
2024-06-04 07:12:51.487 12197-12197 yang I canvas.width = 900, canvas.height = 900
2024-06-04 07:12:51.487 12197-12197 yang I mBitmap.width = 3075 mBitmap.height = 3075
2024-06-04 07:12:51.487 12197-12197 yang I mDestRect.width = 3075.0 mDestRect.height = 3075.0 mDestRect = RectF(0.0, 0.0, 3075.0, 3075.0)
- 创建一张缩放
Bitmap
使用目标RectF
的大小
CoroutineScope(Dispatchers.IO).launch {
tempBitmap = getBitmap(resources, tempRect, R.drawable.fake)
withContext(Dispatchers.Main) {
mRealView?.post {
mDestRect.set(
0f,
0f,
mRealView!!.width.toFloat(),
mRealView!!.height.toFloat()
)
val scale = min(mDestRect.width()/ tempBitmap?.width!!, mDestRect.height()/ tempBitmap?.height!!)
val scaleBitmap = Bitmap.createScaledBitmap(tempBitmap!!, (tempBitmap?.width!!* scale).toInt(), (tempBitmap?.height!! * scale).toInt(), false)
scaleBitmap?.let {
mRealView?.setBitmap(it, mDestRect)
}
Log.i("yang", "scale = $scale")
}
}
}
// log result
2024-06-04 07:36:39.921 19497-19497 yang I scale = 0.29268292
2024-06-04 07:36:39.924 19497-19497 yang I canvas.width = 900, canvas.height = 900
2024-06-04 07:36:39.924 19497-19497 yang I mBitmap.width = 899 mBitmap.height = 899
2024-06-04 07:36:39.924 19497-19497 yang I mDestRect.width = 900.0 mDestRect.height = 900.0 mDestRect = RectF(0.0, 0.0, 900.0, 900.0)
标签:04,mRealView,RectF,mDestRect,height,width,Bitmap,绘制
From: https://blog.csdn.net/sunshine_guo/article/details/139436679