Android挖取原图手指触点区域RectF(并框线标记)放大到ImageView宽高与矩阵mapRadius,Kotlin

Android挖取原图手指触点区域RectF(并框线标记)放大到ImageView宽高与矩阵mapRadius,Kotlin

这里 Android挖取原图中心区域RectF(并框线标记)放大到ImageView宽高,Kotlin-CSDN博客 实现的是把原图中心区域的一片小图挖取出来放大放到下面的ImageView里面,现在不再固定中心位置,而是以手指在上图的触点位置为中心位置,挖取一片区域图放大,然后放到下面的ImageView里面。

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/darker_gray"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <com.pkg.MyImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:clickable="true"
        android:scaleType="fitCenter"
        android:src="@mipmap/image" />

    <ImageView
        android:id="@+id/result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>
Kotlin 复制代码
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Matrix
import android.graphics.Paint
import android.graphics.Path
import android.graphics.RectF
import android.os.Bundle
import android.util.AttributeSet
import android.util.Log
import android.util.SizeF
import android.view.MotionEvent
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.content.ContextCompat
import androidx.core.graphics.toRect


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val miv = findViewById<MyImageView>(R.id.iv)
        val iv = findViewById<ImageView>(R.id.result)
        miv.setResultImage(iv)
    }
}

class MyImageView : AppCompatImageView {
    private var W = 0
    private var H = 0
    private val mSizeF = SizeF(400f, 200f)
    private var mOriginBmp: Bitmap? = null
    private var mPaint = Paint()
    private var result: ImageView? = null

    private var mTouchX = 0f
    private var mTouchY = 0f
    private var mCanDraw = false
    private var mCircleRadius = 30f

    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) {
        mPaint.style = Paint.Style.STROKE
        mPaint.strokeWidth = 5f
        mPaint.isAntiAlias = true
        mPaint.color = Color.RED

        mOriginBmp = getOriginalBitmap(ctx, R.mipmap.image)
        Log.d("fly", "origin bmp w=${mOriginBmp!!.width} h=${mOriginBmp!!.height}")
    }

    private fun getOriginalBitmap(ctx: Context, resId: Int): Bitmap {
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true //只解析原始图片的宽高,不decode原始文件装载到内存的Bitmap。
        BitmapFactory.decodeResource(resources, resId, options)

        //这一阶段,最关键的是获取原始图的真实宽高。
        val srcBmpWidth = options.outWidth
        val srcBmpHeight = options.outHeight

        val d = ContextCompat.getDrawable(ctx, resId)

        //根据原始图片的宽高创建一个空的Bitmap
        val bitmap = Bitmap.createBitmap(srcBmpWidth, srcBmpHeight, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        d?.setBounds(0, 0, srcBmpWidth, srcBmpHeight)
        d?.draw(canvas) //至此,bitmap即为原始图片。

        return bitmap
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        if (event == null) {
            return false
        }

        mTouchX = event.x
        mTouchY = event.y

        when (event.action) {
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                mCanDraw = true

                myInvalidate()
            }
        }

        return super.onTouchEvent(event)
    }

    private fun myInvalidate() {
        this.invalidate()
    }

    fun setResultImage(iv: ImageView) {
        result = iv
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        W = w
        H = h
        Log.d("fly", "W=$W H=$H")
    }

    //从原始的Bitmap图中抠出一块SizeF大小的图。
    private fun getCenterBmp(): Bitmap {
        val bmp = Bitmap.createBitmap(W, H, Bitmap.Config.ARGB_8888)
        val c = Canvas(bmp)

        val dstRectF = RectF(0f, 0f, bmp.width.toFloat(), bmp.height.toFloat())

        //需要特别注意,要把手指在屏幕上触点坐标,经过比例映射到原始图Bitmap的对应位置。
        val mapToOriginBmpX = mOriginBmp!!.width * (mTouchX / W)
        val mapToOriginBmpY = mOriginBmp!!.height * (mTouchY / H)

        val centerRectF =
            RectF(
                mapToOriginBmpX - mSizeF.width / 2f,
                mapToOriginBmpY - mSizeF.height / 2f,
                mapToOriginBmpX + mSizeF.width / 2f,
                mapToOriginBmpY + mSizeF.height / 2f
            )

        c.drawBitmap(mOriginBmp!!, centerRectF.toRect(), dstRectF, null)

        val mx = Matrix()
        mx.setScale(dstRectF.width() / centerRectF.width(), dstRectF.width() / centerRectF.width())

        //下面图中的中心圆圈。
        mPaint.color = Color.YELLOW
        c.drawCircle(
            W / 2f, H / 2f,
            mx.mapRadius(mCircleRadius), //注意同步放大小图的圆圈半径。
            mPaint
        )

        return bmp
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        if (mCanDraw) {
            //绘制中心圆圈。
            mPaint.color = Color.YELLOW
            canvas.drawCircle(mTouchX, mTouchY, mCircleRadius, mPaint)

            drawRoundRectLine(canvas)

            result?.setImageBitmap(getCenterBmp())


            mCanDraw = false
        }
    }

    private fun drawRoundRectLine(canvas: Canvas) {
        val lineRectF = RectF(
            0f,
            0f,
            mSizeF.width,
            mSizeF.height
        )

        //原始图被Android系统拉伸放到屏幕上,所以lineRectF也需要进行相同的拉伸。
        val originBmpSizeMapMatrix = Matrix()
        originBmpSizeMapMatrix.setScale(getOriginBmpScaleToImageViewFactor(), getOriginBmpScaleToImageViewFactor())
        originBmpSizeMapMatrix.mapRect(lineRectF)

        lineRectF.offset(mTouchX - lineRectF.width() / 2f, mTouchY - lineRectF.height() / 2f)

        //绘制红色的lineRectF线框。
        val path = Path()
        path.addRoundRect(lineRectF, 20f, 20f, Path.Direction.CW)
        mPaint.color = Color.RED
        canvas.drawPath(path, mPaint)
    }

    private fun getOriginBmpScaleToImageViewFactor(): Float {
        return (W.toFloat()) / (mOriginBmp!!.width)
    }
}

运行后,点击上图不同位置点:

Android BitmapFactory.decodeResource读取原始图片装载成原始宽高Bitmap,Kotlin_bitmapfactory解码宽高-CSDN博客文章浏览阅读856次。文章浏览阅读1.8k次。/*Java代码 将Drawable转化为Bitmap */ Bitmap drawableToBitmap(Drawable drawable) { int width = drawable.getIntrinsicWidth();Android Drawable 转化成 Bitmap-CSDN博客。_bitmapfactory解码宽高https://blog.csdn.net/zhangphil/article/details/134449577

Android挖取原图中心区域RectF(并框线标记)放大到ImageView宽高,Kotlin-CSDN博客文章浏览阅读395次,点赞11次,收藏11次。文章浏览阅读853次。【代码】Android矩阵setRectToRect裁剪Bitmap原图Matrix放大,mapRect标记中心区域,Kotlin。Android BitmapFactory.decodeResource读取原始图片装载成原始宽高Bitmap,Kotlin_bitmapfactory解码宽高-CSDN博客。Android矩阵setRectToRect裁剪Bitmap原图Matrix放大,mapRect标记中心区域,Kotlin-CSDN博客。https://blog.csdn.net/zhangphil/article/details/136157116

相关推荐
2501_9151063211 分钟前
iOS App 测试方法,通过 Xcode、Instruments、Safari Inspector、克魔(KeyMob)等工具
android·ios·小程序·uni-app·iphone·xcode·safari
游戏开发爱好者815 分钟前
对 iOS IPA 文件进行深度混淆的一种实现路径
android·ios·小程序·https·uni-app·iphone·webview
成都大菠萝20 分钟前
2-2-5 快速掌握Kotlin-语言的泛型函数
android
成都大菠萝20 分钟前
2-2-4 快速掌握Kotlin-定义泛型类
android
掘我的金22 分钟前
加载状态优化实践:如何让用户始终知道当前状态
android
成都大菠萝23 分钟前
2-2-6 快速掌握Kotlin-语言的多泛型参数学习
android
掘我的金27 分钟前
空状态优化实践:如何让"白屏"变成友好的提示
android
_李小白33 分钟前
【Android FrameWork】第三十四天:系统设置项(Settings)与系统属性(System Properties)
android·jvm·oracle
、BeYourself1 小时前
GridLayoutManager 网格布局与 RecyclerView 拖拽侧滑实战
android·android-studio
Kapaseker1 小时前
如何写出高性能的Java Stream
android·java