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

相关推荐
每次的天空6 小时前
Android学习总结之算法篇四(字符串)
android·学习·算法
x-cmd8 小时前
[250331] Paozhu 发布 1.9.0:C++ Web 框架,比肩脚本语言 | DeaDBeeF 播放器发布 1.10.0
android·linux·开发语言·c++·web·音乐播放器·脚本语言
高林雨露9 小时前
Java 与 Kotlin 对比示例学习(三)
java·kotlin
lc9991029 小时前
基于kotlin native的C与kotlin互相调用
开发语言·kotlin
tangweiguo0305198711 小时前
Android BottomNavigationView 完全自定义指南:图标、文字颜色与选中状态
android
遥不可及zzz12 小时前
Android 应用程序包的 adb 命令
android·adb
无知的前端12 小时前
Flutter 一文精通Isolate,使用场景以及示例
android·flutter·性能优化
_一条咸鱼_12 小时前
Android Compose 入门之字符串与本地化深入剖析(五十三)
android
ModestCoder_13 小时前
将一个新的机器人模型导入最新版isaacLab进行训练(以unitree H1_2为例)
android·java·机器人
robin_suli14 小时前
Spring事务的传播机制
android·java·spring