第十章

作者: 贤兵 | 来源:发表于2020-12-17 01:16 被阅读0次

    一、矩阵(Matrix)

    1、什么是矩阵

    在数学中,矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合,最早来自于方程组的系数及常数所构成的方阵。矩阵是高等代数学中的常见工具,也常见于统计分析等应用数学学科中。

    2、图片操作中为什么要使用矩阵

    功能强大,Android系统中有成熟api可用。

    3、四种基本操作

    translate(平移)
    rotate(旋转)
    scale(缩放)
    skew(错切、倾斜)


    图片.png

    pre,post,set区别:
    pre是在队列最前面插入,post是在队列最后面追加,而set先清空队列在添加。
    set系列方法:setTranslate,setScale,setRotate,setSkew;设置,会覆盖之前的参数。
    pre系列方法:preTranslate,preScale,preRotate,preSkew;矩阵先乘,如M' = M * T(dx, dy)。
    post系列方法:postTranslate,postScale,postRotate,postSkew;矩阵后乘,如M' = T(dx, dy) * M。

    二、矩阵操纵图片

    layout

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <com.xianbing.matrixdemo.MatrixView
            android:id="@+id/matrix_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
        <LinearLayout
            android:layout_gravity="bottom"
            android:layout_width="match_parent"
            android:orientation="horizontal"
            android:layout_height="wrap_content">
    
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="translate"
                android:layout_weight="1.0"
                android:id="@+id/translate" />
    
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="scale"
                android:layout_weight="1.0"
                android:id="@+id/scale" />
    
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="rotate"
                android:layout_weight="1.0"
                android:id="@+id/rotate" />
    
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="skew"
                android:layout_weight="1.0"
                android:id="@+id/skew" />
    
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="water_mark"
                android:layout_weight="1.0"
                android:id="@+id/water_mark" />
    
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="reset"
                android:layout_weight="1.0"
                android:id="@+id/reset" />
        </LinearLayout>
    </FrameLayout>
    

    自定义view

    public class MatrixView extends View {
        private Matrix mMatrix;
        private Paint mMatrixPaint;
        private Bitmap mBitmap;
    
        public MatrixView(Context context) {
            super(context);
            init();
        }
    
        public MatrixView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public MatrixView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        public MatrixView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
            init();
        }
    
        private void init() {
            mMatrix = new Matrix();
            mMatrixPaint = new Paint();
            mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawBitmap(mBitmap, mMatrix, mMatrixPaint);
        }
    
        public void translate(int x, int y) {
            mMatrix.setTranslate(x, y);
            invalidate();
        }
    
        public void scale(int sx, int sy) {
            mMatrix.setScale(sx, sy);
            invalidate();
        }
    
        public void rotate(float degree) {
            mMatrix.setRotate(degree);
            invalidate();
        }
    
        public void skew(float kx, float ky) {
            mMatrix.setSkew(kx, ky);
            invalidate();
        }
    
        public void waterMark() {
            Bitmap bitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            canvas.drawBitmap(mBitmap, 0, 0, mMatrixPaint);
            mMatrixPaint.setTextSize(50);
            mMatrixPaint.setColor(Color.RED);
            canvas.drawText("wangxianbing", 20,20, mMatrixPaint);
            mBitmap = bitmap;
            invalidate();
        }
        public void reset() {
            mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
            mMatrix.reset();
            invalidate();
        }
    }
    

    MainActivity.java

    public class MainActivity extends AppCompatActivity {
        private MatrixView mMatrixView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mMatrixView = findViewById(R.id.matrix_view);
            findViewById(R.id.translate).setOnClickListener(v -> {
                mMatrixView.translate(300, 300);
            });
            findViewById(R.id.scale).setOnClickListener(v -> {
                mMatrixView.scale(2, 2);
            });
            findViewById(R.id.rotate).setOnClickListener(v -> {
                mMatrixView.rotate(30);
            });
            findViewById(R.id.skew).setOnClickListener(v -> {
                mMatrixView.skew(1, 0);
            });
            findViewById(R.id.water_mark).setOnClickListener(v -> {
                mMatrixView.waterMark();
            });
            findViewById(R.id.reset).setOnClickListener(v -> {
                mMatrixView.reset();
            });
        }
    }
    

    三、倒影实现

    layout

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <com.xianbing.flectionviewdemo.FlectionView
            android:id="@+id/flection_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:id="@+id/button1"
                android:text="button" />
    
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:id="@+id/button2"
                android:text="button2" />
        </LinearLayout>
    </FrameLayout>
    

    FlectionView.java

    public class FlectionView extends View {
        public FlectionView(Context context) {
            super(context);
            init();
        }
    
        public FlectionView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public FlectionView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        public FlectionView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
            init();
        }
    
        private void init() {
            mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.hong20);
            mPaint = new Paint();
        }
    
        private Bitmap mBitmap;
        private Paint mPaint;
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawBitmap(mBitmap, 0f, 0f, mPaint);
        }
    
        public void reset() {
            init();
            invalidate();
        }
    
        public void showRefrection() {
            int width = mBitmap.getWidth();
            int height= mBitmap.getHeight();
            //生成一张新图,新图的高度是原先的3/2,也就是增大了1/2
            Bitmap bitmap = Bitmap.createBitmap(width, height *3 /2, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            Paint paint = new Paint();
            //将老图滑到新图上侧
            canvas.drawBitmap(mBitmap, 0, 0, paint);
    
            //生成倒影
            Matrix matrix = new Matrix();
            matrix.preScale(1, -1);
            Bitmap reflection = Bitmap.createBitmap(mBitmap, 0, height/2, width, height/2, matrix, false);
            //将倒影画到新图上
            canvas.drawBitmap(reflection, 0, height, paint);
    
            Paint shaderPaint = new Paint();
            //线性渐变
            LinearGradient linearGradient = new LinearGradient(0, height, 0, bitmap.getHeight(), 0x70ffffff, 0x00ffffff, Shader.TileMode.MIRROR);
            shaderPaint.setShader(linearGradient);
            shaderPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            canvas.drawRect(0, height, width, height * 3 / 2, shaderPaint);
    
            mBitmap = bitmap;
            invalidate();
        }
    }
    

    MainActivity.java

    public class MainActivity extends AppCompatActivity {
        private FlectionView mFlectionView;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mFlectionView = findViewById(R.id.custom_view);
            findViewById(R.id.reset).setOnClickListener(v -> {
                mFlectionView.reset();
            });
    
            findViewById(R.id.reflection).setOnClickListener(v -> {
                mFlectionView.showRefrection();
            });
        }
    }
    

    四、PhotView的使用

    1、官网:https://github.com/chrisbanes/PhotoView

    2、Features

    Out of the box zooming, using multi-touch and double-tap.
    Scrolling, with smooth scrolling fling.
    Works perfectly when used in a scrolling parent (such as ViewPager).
    Allows the application to be notified when the displayed Matrix has changed. Useful for when you need to update your UI based on the current zoom/scroll position.
    Allows the application to be notified when the user taps on the Photo.

    3,使用

    依赖

    implementation 'com.github.chrisbanes:PhotoView:2.3.0'
    

    layout

        <com.github.chrisbanes.photoview.PhotoView
            android:id="@+id/photo_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/himalaya" />
    

    五、补充

    1、什么是shader

    https://www.jianshu.com/p/1efcc9c9f286
    https://www.jianshu.com/p/5fb82b189094
    https://www.jianshu.com/p/83af13b41bb6

    2、Xfermode,PorterDuffXfermode

    设置两张图片相交时的模式
    我们知道 在正常的情况下,在已有的图像上绘图将会在其上面添加一层新的形状。 如果新的Paint是完全不透明的,那么它将完全遮挡住下面的Paint; 而setXfermode就可以来解决这个问题


    图片.png

    canvas原有的图片 可以理解为背景 就是dst
    新画上去的图片 可以理解为前景 就是src

    相关文章

      网友评论

          本文标题:第十章

          本文链接:https://www.haomeiwen.com/subject/idwogktx.html