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

相关推荐
Aileen_0v011 小时前
【Gemini3.0的国内use教程】
android·人工智能·算法·开源·mariadb
浩浩的代码花园12 小时前
自研端侧推理模型实测效果展示
android·深度学习·计算机视觉·端智能
踢球的打工仔18 小时前
PHP面向对象(7)
android·开发语言·php
安卓理事人18 小时前
安卓socket
android
安卓理事人1 天前
安卓LinkedBlockingQueue消息队列
android
万能的小裴同学1 天前
Android M3U8视频播放器
android·音视频
q***57741 天前
MySql的慢查询(慢日志)
android·mysql·adb
JavaNoober1 天前
Android 前台服务 "Bad Notification" 崩溃机制分析文档
android
城东米粉儿1 天前
关于ObjectAnimator
android
zhangphil1 天前
Android渲染线程Render Thread的RenderNode与DisplayList,引用Bitmap及Open GL纹理上传GPU
android