【Android】Bitmap图片旋转、缩放、翻转等变换(90/100)

请添加图片描述
自定义BitmapChangeView:

package top.lc951.myandroid.views;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import top.lc951.myandroid.utils.BitmapUtil;

/**
 * @author lichong
 * 2022年07月27日15:38:28
 */
public class BitmapChangeView extends View {
    public static final String TAG = BitmapChangeView.class.getSimpleName();

    private float mScaleRatio=1.0f;
    private float mRotateDegree=0;
    private Bitmap mBitmap;
    private int mBitmapWidth;
    private int mBitmapHeight;
    private int mOffsetX;
    private int mOffsetY;

    public BitmapChangeView(Context context) {
        super(context);
    }

    public BitmapChangeView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    // 设置位图对象
    public void setImageBitmap(Bitmap bitmap) {
        mBitmap = bitmap;
        mBitmapWidth = mBitmap.getWidth();
        mBitmapHeight = mBitmap.getHeight();
        postInvalidate(); // 立即刷新视图(线程安全方式)
    }

    // 左右翻转图像
    public void flip() {
        // 水平翻转图像,也就是把镜中像左右翻过来
        mBitmap = BitmapUtil.getFlipBitmap(mBitmap);
        postInvalidate(); // 立即刷新视图(线程安全方式)
    }

    // 设置缩放比例。isReset为true表示按照原始尺寸进行缩放,为false表示按照当前尺寸进行缩放
    public void setScaleRatio(float ratio, boolean isReset) {
        if (isReset) {
            mScaleRatio = ratio;
        } else {
            mScaleRatio *= ratio;
        }
        postInvalidate(); // 立即刷新视图(线程安全方式)
    }
    // 设置旋转角度。isReset为true表示按照原始方向进行旋转,为false表示按照当前方向进行缩放
    public void setRotateDegree(int degree, boolean isReset) {
        if (isReset) {
            mRotateDegree = degree;
        } else {
            mRotateDegree += degree;
        }
        postInvalidate(); // 立即刷新视图(线程安全方式)
    }

    // 设置偏移距离。isReset为true表示按照原始位置进行移动,为false表示按照当前位置进行移动
    public void setOffset(int offsetX, int offsetY, boolean isReset) {
        if (isReset) {
            mOffsetX = offsetX;
            mOffsetY = offsetY;
        } else {
            mOffsetX += offsetX;
            mOffsetY += offsetY;
        }
        postInvalidate(); // 立即刷新视图(线程安全方式)
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mBitmap == null) {
            return;
        }
        int width = getMeasuredWidth(); // 获取视图的实际宽度
        int height = getMeasuredHeight(); // 获取视图的实际高度
        int new_width = (int) (mBitmapWidth * mScaleRatio);
        int new_height = (int) (mBitmapHeight * mScaleRatio);
        Bitmap bitmap = mBitmap;
        if (mScaleRatio != 1) {
            // 生成缩放后的位图对象
            bitmap = BitmapUtil.getScaleBitmap(mBitmap, mScaleRatio);
        }
        if (mRotateDegree != 0) {
            // 生成旋转后的位图对象
            bitmap = BitmapUtil.getRotateBitmap(bitmap, mRotateDegree);
        }
        // 在画布上的指定位置绘制位图对象
        canvas.drawBitmap(bitmap, (width - new_width) / 2 + mOffsetX,
                (height - new_height) / 2 + mOffsetY, new Paint());
    }
}

工具类:

// 水平翻转图像,也就是把镜中像左右翻过来
    public static Bitmap getFlipBitmap(Bitmap bitmap) {
        Matrix matrix = new Matrix(); // 创建操作图片用的矩阵对象
        matrix.postScale(-1, 1); // 执行图片的旋转动作
        // 创建并返回旋转后的位图对象
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                bitmap.getHeight(), matrix, false);
    }
// 获得比例缩放之后的位图对象
    public static Bitmap getScaleBitmap(Bitmap bitmap, double scaleRatio) {
        Matrix matrix = new Matrix(); // 创建操作图片用的矩阵对象
        matrix.postScale((float) scaleRatio, (float) scaleRatio);
        // 创建并返回缩放后的位图对象
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                bitmap.getHeight(), matrix, false);
    }


// 获得旋转角度之后的位图对象
    public static Bitmap getRotateBitmap(Bitmap bitmap, float rotateDegree) {
        Matrix matrix = new Matrix(); // 创建操作图片用的矩阵对象
        matrix.postRotate(rotateDegree); // 执行图片的旋转动作
        // 创建并返回旋转后的位图对象
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                bitmap.getHeight(), matrix, false);
    }

布局引用:

<top.lc951.myandroid.views.BitmapChangeView
        android:id="@+id/view_bitmap_change"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        app:layout_constraintStart_toStartOf="@id/tv_scale"
        app:layout_constraintTop_toBottomOf="@id/ck_flip" />

应用如下:

package top.lc951.myandroid.activity;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.Spinner;
import android.widget.Toast;

import top.lc951.myandroid.R;
import top.lc951.myandroid.utils.BitmapUtil;
import top.lc951.myandroid.views.BitmapChangeView;

/**
 * 图片翻转、缩放、旋转等
 * */
public class BitmapChangeActivity extends AppCompatActivity {

    private BitmapChangeView bitmapChangeView;
    public static void actionActivity(Context context) {
        Intent intent = new Intent(context, BitmapChangeActivity.class);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bitmap_change);

        CheckBox flipCb = findViewById(R.id.ck_flip);
        bitmapChangeView=findViewById(R.id.view_bitmap_change);
        flipCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                bitmapChangeView.flip();
            }
        });

        Button saveBtn=findViewById(R.id.btn_save_image);
        saveBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Bitmap bitmap = bitmapChangeView.getDrawingCache(); // 从绘图缓存获取位图对象
                // 生成图片文件的保存路径
//                String path = String.format("%s/%s.jpg",
//                        getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString(),
//                        DateUtil.getNowDateTime());
//                BitmapUtil.saveImage(path, bitmap); // 把位图保存为图片文件
//                BitmapUtil.notifyPhotoAlbum(this, path); // 通知相册来了张新图片
//                Toast.makeText(this, "成功保存图片文件:" + path, Toast.LENGTH_LONG).show();
            }
        });

        initScaleSpinner();
        initRotateSpinner();
    }

    @Override
    protected void onStart() {
        super.onStart();
        bitmapChangeView.setDrawingCacheEnabled(true);
        Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.mipmap.ic_img06);
        bitmapChangeView.setImageBitmap(bitmap);
    }

    @Override
    protected void onStop() {
        super.onStop();
        bitmapChangeView.setDrawingCacheEnabled(false);
    }
    private String[] scaleArray = {"0.25", "0.5", "0.75", "1.0", "1.5", "2.0", "4.0"};
    private String[] rotateArray = {"0", "45", "90", "135", "180", "225", "270", "315"};

    private void initRotateSpinner() {
        ArrayAdapter<String> scaleAdapter = new ArrayAdapter<>(this,
                android.R.layout.simple_list_item_1, rotateArray);
        Spinner sp_scale = findViewById(R.id.spinner_rotate);
        sp_scale.setPrompt("请选择旋转角度");
        sp_scale.setAdapter(scaleAdapter);
        sp_scale.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                bitmapChangeView.setRotateDegree(Integer.parseInt(rotateArray[position]), true);

            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
        sp_scale.setSelection(0);
    }

    private void initScaleSpinner() {
        ArrayAdapter<String> scaleAdapter = new ArrayAdapter<>(this,
                android.R.layout.simple_list_item_1, scaleArray);
        Spinner sp_scale = findViewById(R.id.spinner_scale);
        sp_scale.setPrompt("请选择缩放比率");
        sp_scale.setAdapter(scaleAdapter);
        sp_scale.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                bitmapChangeView.setScaleRatio(Float.parseFloat(scaleArray[position]), true);

            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
        sp_scale.setSelection(3);
    }
}

自研产品推荐

推荐理由

postman在国内使用已经越来越困难:
1、登录问题严重
2、Mock功能服务基本没法使用
3、版本更新功能已很匮乏
4、某些外力因素导致postman以后能否使用风险较大
出于以上考虑因此笔者自己开发了一款api调试开发工具SmartApi,满足基本日常开发调试api需求

简介

历时一年半多开发终于smartApi-v1.0.0版本在2023-09-15晚十点正式上线
smartApi是一款对标国外的postman的api调试开发工具,由于开发人力就作者一个所以人力有限,因此v1.0.0版本功能进行精简,大功能项有:

  • api参数填写
  • api请求响应数据展示
  • PDF形式的分享文档
  • Mock本地化解决方案
  • api列表数据本地化处理
  • 再加上UI方面的打磨

下面是一段smartApi使用介绍:
在这里插入图片描述

下载地址:

https://pan.baidu.com/s/1kFAGbsFIk3dDR64NwM5y2A?pwd=csdn

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lichong951

你的鼓励决定更新的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值