热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

AndroidBitmap常见的几个操作:缩放,裁剪,旋转,偏移

AndroidBitmap相关操作常见的几个操作:缩放,裁剪,旋转,偏移很多操作需要Matrix来支持;Matrix通过矩阵来处理位图,计算出各个像素点的位置,从而把bitmap显示

Android Bitmap 相关操作

常见的几个操作:缩放,裁剪,旋转,偏移

    

很多操作需要 Matrix 来支持;Matrix 通过矩阵来处理位图,计算出各个像素点的位置,从而把bitmap显示出来。
matrix里有一个3x3的矩阵,用于图像处理:

MSCALE_X MSKEW_X  MTRANS_X
MSKEW_Y MSCALE_Y MTRANS_Y
MPERSP_0 MPERSP_1 MPERSP_2

根据变量名能猜出具体的用途:
缩放X 偏移X 平移X
偏移Y 缩放Y 平移Y
透视0 透视1 透视2

matrix的操作有set,pre和post;set能够直接设置矩阵中的数值;pre类似于矩阵左乘;post类似与矩阵中的右乘

原bitmap经过计算后,会重新生成一张bitmap

代码片段:

    /**
* 根据给定的宽和高进行拉伸
*
*
@param origin 原图
*
@param newWidth 新图的宽
*
@param newHeight 新图的高
*
@return new Bitmap
*/
private Bitmap scaleBitmap(Bitmap origin, int newWidth, int newHeight) {
if (origin == null) {
return null;
}
int height = origin.getHeight();
int width = origin.getWidth();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix
= new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// 使用后乘
Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
if (!origin.isRecycled()) {
origin.recycle();
}
return newBM;
}

/**
* 按比例缩放图片
*
*
@param origin 原图
*
@param ratio 比例
*
@return 新的bitmap
*/
private Bitmap scaleBitmap(Bitmap origin, float ratio) {
if (origin == null) {
return null;
}
int width = origin.getWidth();
int height = origin.getHeight();
Matrix matrix
= new Matrix();
matrix.preScale(ratio, ratio);
Bitmap newBM
= Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
if (newBM.equals(origin)) {
return newBM;
}
origin.recycle();
return newBM;
}

/**
* 裁剪
*
*
@param bitmap 原图
*
@return 裁剪后的图像
*/
private Bitmap cropBitmap(Bitmap bitmap) {
int w = bitmap.getWidth(); // 得到图片的宽,高
int h = bitmap.getHeight();
int cropWidth = w >= h ? h : w;// 裁切后所取的正方形区域边长
cropWidth /= 2;
int cropHeight = (int) (cropWidth / 1.2);
return Bitmap.createBitmap(bitmap, w / 3, 0, cropWidth, cropHeight, null, false);
}

/**
* 选择变换
*
*
@param origin 原图
*
@param alpha 旋转角度,可正可负
*
@return 旋转后的图片
*/
private Bitmap rotateBitmap(Bitmap origin, float alpha) {
if (origin == null) {
return null;
}
int width = origin.getWidth();
int height = origin.getHeight();
Matrix matrix
= new Matrix();
matrix.setRotate(alpha);
// 围绕原地进行旋转
Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
if (newBM.equals(origin)) {
return newBM;
}
origin.recycle();
return newBM;
}

/**
* 偏移效果
*
@param origin 原图
*
@return 偏移后的bitmap
*/
private Bitmap skewBitmap(Bitmap origin) {
if (origin == null) {
return null;
}
int width = origin.getWidth();
int height = origin.getHeight();
Matrix matrix
= new Matrix();
matrix.postSkew(
-0.6f, -0.3f);
Bitmap newBM
= Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
if (newBM.equals(origin)) {
return newBM;
}
origin.recycle();
return newBM;
}

按钮的操作定义:

    @Override
public void onClick(View v) {
Bitmap originBM
= BitmapFactory.decodeResource(getResources(),
R.drawable.littleboygreen_x128);
switch (v.getId()) {
case R.id.btn1: {// 按尺寸缩放
effectTextView.setText(R.string.scale);
Bitmap nBM
= scaleBitmap(originBM, 100, 72);
effectView.setImageBitmap(nBM);
break;
}
case R.id.btn2: {// 按比例缩放,每次点击缩放比例都会不同
effectTextView.setText(R.string.scale_ratio);
if (ratio <3) {
ratio
+= 0.05f;
}
else {
ratio
= 0.1f;
}
Bitmap nBM
= scaleBitmap(originBM, ratio);
effectView.setImageBitmap(nBM);
break;
}
case R.id.btn3: {// 裁剪
effectTextView.setText("剪个头");
Bitmap cropBitmap
= cropBitmap(originBM);
effectView.setImageBitmap(cropBitmap);
break;
}
case R.id.btn4: {// 顺时针旋转效果;每次点击更新旋转角度
if (alpha <345) {
alpha
+= 15;
}
else {
alpha
= 0;
}
effectTextView.setText(
"旋转");
Bitmap rotateBitmap
= rotateBitmap(originBM, alpha);
effectView.setImageBitmap(rotateBitmap);
break;
}
case R.id.btn5: {// 逆时针旋转效果;每次点击更新旋转角度
if (beta > 15) {
beta
-= 15;
}
else {
beta
= 360;
}
effectTextView.setText(
"旋转");
Bitmap rotateBitmap
= rotateBitmap(originBM, beta);
effectView.setImageBitmap(rotateBitmap);
break;
}
case R.id.btn6: {// 偏移效果;偏移量在方法中
Bitmap skewBM = skewBitmap(originBM);
effectView.setImageBitmap(skewBM);
break;
}
}
}

遇到的问题

Matrix matrix = new Matrix();
matrix.preScale(ratio, ratio);
// 当 ratio=1,下面的 newBM 将会等价于 origin
Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
if (!origin.isRecycled()) {
origin.recycle();
}

log如下,当ratio=1时,新bitmap和旧的bitmap同一地址


11-27 05:27:16.086 16723-16723/? D/rust: originBitmap = android.graphics.Bitmap@1e8849e
11-27 05:27:16.086 16723-16723/? D/rust: newBitmap = android.graphics.Bitmap@1e8849e

 


推荐阅读
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讲述了如何通过代码在Android中更改Recycler视图项的背景颜色。通过在onBindViewHolder方法中设置条件判断,可以实现根据条件改变背景颜色的效果。同时,还介绍了如何修改底部边框颜色以及提供了RecyclerView Fragment layout.xml和项目布局文件的示例代码。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
author-avatar
超_级如新公司
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有