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

相关推荐
晓梦林19 小时前
cp520靶场学习笔记
android·笔记·学习
有味道的男人21 小时前
Open Claw对接1688平台
android·rxjava
_李小白1 天前
【android opencv学习笔记】Day 17: 目标追踪(MeanShift)
android·opencv·学习
用户86022504674721 天前
AI 分析头部APP系统优化框架
android
用户86022504674721 天前
AI分析头部APP优化框架
android
2501_916007471 天前
iOS开发中抓取HTTPS请求的完整解决方法与步骤详解
android·网络协议·ios·小程序·https·uni-app·iphone
lvronglee1 天前
【数字图传第四步】Android App查看图传视频
android·音视频
90后的晨仔1 天前
Android 程序入口与核心组件详解
android
90后的晨仔1 天前
Kotlin 简介与开发环境搭建
android
BU摆烂会噶1 天前
【LangGraph】House_Agent 实战(四):预定流程 —— 中断与人工干预
android·人工智能·python·langchain