Android第十三站 众多豪华控件 图片处理进阶
来源:互联网 发布:ubuntu启动后显示grub 编辑:程序博客网 时间:2024/04/28 11:35
目录
4.22 加载手机磁盘里的图片文件
4.23 动态放大缩小ImageView里的图片
运用Matrix对象来缩放图片文件
4.24 动态旋转图片 Bitmap与Matrix旋转ImageView
4.22 加载手机磁盘里的图片文件
范例说明
在Android程序中,只要将图片文件存放在 /res/drawable/ 目录下,即可以通过R.drawable.id来取得图片id,并使用图片。如果不是存放在这个目录下面的图片文件,例如,用户想要从存储卡中读取刚拍的照片,又该如何实现呢?Android API中提供了Bitmap(Android.graphics.Bitmap)与BitmapFactory(Android.graphics.BitmapFactory)对象,可以读取存储卡或手机文件系统里的图片文件。
实现本范例前需先准备两张图片,分别存放在“/res/drawable/”文件夹与手机文件系统的另一个文件夹中。以本范例而言,两张图片文件的路径分别为 /res/drawable/ex04_22_1.png与/data/data/irdc. ex04_22_2.png。范例中会先将drawable目录里的图片文件显示于ImageView中,再设计一个Button,当用户单击Button后,将ImageView里的图片换成另一张存在手机文件系统里的图形文件。
src/irdc.ex04_22/EX04_22.java
程序中以BitmapFactory.decodeFile(fileName)来取得Bitmap对象,再将Bitmap对象以setImage Bitmap()来设置给ImageView。
package irdc.ex04_22;
/* import程序略 */
public class EX04_22 extends Activity
{
/*声明对象变量*/
private ImageView mImageView;
private Button mButton;
private TextView mTextView;
private String fileName="/data/data/irdc.ex04_22/ex04_22_2.png";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
/*加载main.xml Layout */
setContentView(R.layout.main);
/* 取得Button对象,并添加onClickListener */
mButton = (Button)findViewById(R.id.mButton);
mButton.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View v)
{
/* 取得对象 */
mImageView = (ImageView)findViewById(R.id.mImageView);
mTextView=(TextView)findViewById(R.id.mTextView);
/* 检查文件是否存在 */
File f=new File(fileName);
if(f.exists())
{
/* 产生Bitmap对象,并放入mImageView中 */
Bitmap bm = BitmapFactory.decodeFile(fileName);
mImageView.setImageBitmap(bm);
mTextView.setText(fileName);
}
else
{
mTextView.setText("文件不存在");
}
}
});
}
}
扩展学习
BitmapFactory(android.graphics.BitmapFactory)是Android API提供的对象,可以将图片文件转换成Bitmap(android.graphics.Bitmap)对象,范例中使用的decodeFile()可以将手机文件系统中的图片文件转换成Bitmap对象。另外,BitmapFactory也提供了其他的方法,如decodeResource()可以将 /res/drawable/内预先存入的图片文件转换成Bitmap对象,decodeStream()方法则可将InputStream转换成Bitmap对象。
4.23 动态放大缩小ImageView里的图片
运用Matrix对象来缩放图片文件
本范例将运用Martix(android.graphics.Matrix)对象的postScale()方法来实现在手机上缩放图片的功能,在实现本范例前,需先在/res/drawable/中放入一张图片。以本范例而言,图片文件路径为/res/drawable/ex04_23.png,程序会预先将图片加载到ImageView Widget中,并设计两个Button,一个有放大的功能、一个有缩小的功能,以显示图片放大缩小的效果。为了避免ImageView在放大的过程中,无止境地超过屏幕的尺寸,程序将在放大阶段控制图片的最大宽高。
主程序设计
程序中的small()方法会将图片缩小为原尺寸的4/5,big()方法会将图片放大为原尺寸的1.25倍,当放大按钮的onClick事件被触发时,会运行big()方法;缩小按钮的onClick事件被触发时,则运行small()方法。
程序中以Matrix对象搭配Bitmap的createBitmap()方法来对图片进行缩放,并利用DisplayMetrics对象来取得屏幕显示大小,用以控制图片放大后的尺寸不会超过屏幕显示的区域。
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.AbsoluteLayout;
import android.widget.Button;
import android.widget.ImageView;
public class ex4_23 extends Activity {
/* 相关变量声明 */
private ImageView mImageView;
private Button mButton01;
private Button mButton02;
private AbsoluteLayout layout1;
private Bitmap bmp;
private int id=0;
private int displayWidth;
private int displayHeight;
private float scaleWidth=1;
private float scaleHeight=1;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
/*加载main.xml Layout */
setContentView(R.layout.main);
/* 取得屏幕分辨率大小 */
DisplayMetrics dm=new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
displayWidth=dm.widthPixels;
/* 屏幕高度须扣除下方Button高度 */
displayHeight=dm.heightPixels-80;
/* 初始化相关变量 */
bmp=BitmapFactory.decodeResource(getResources(),R.drawable.ex04_23);
mImageView = (ImageView)findViewById(R.id.myImageView);
layout1 = (AbsoluteLayout)findViewById(R.id.layout1);
mButton01 = (Button)findViewById(R.id.myButton1);
mButton02 = (Button)findViewById(R.id.myButton2);
/* 缩小按钮onClickListener */
mButton01.setOnClickListener(new Button.OnClickListener()
{
@Override
public void onClick(View v)
{
small();
}
});
/* 放大按钮onClickListener */
mButton02.setOnClickListener(new Button.OnClickListener()
{
@Override
public void onClick(View v)
{
big();
}
});
}
/* 图片缩小的method */
private void small()
{
int bmpWidth=bmp.getWidth();
int bmpHeight=bmp.getHeight();
/* 设置图片缩小的比例 */
double scale=0.8;
/* 计算出这次要缩小的比例 */
scaleWidth=(float) (scaleWidth*scale);
scaleHeight=(float) (scaleHeight*scale);
/* 产生reSize后的Bitmap对象 */
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizeBmp = Bitmap.createBitmap(bmp,0,0,bmpWidth,bmpHeight,matrix,true);
if(id==0)
{
/* 如果是第一次按,就删除原来默认的ImageView */
layout1.removeView(mImageView);
}
else
{
/* 如果不是第一次按,就删除上次放大缩小所产生的ImageView */
layout1.removeView((ImageView)findViewById(id));
}
/* 产生新的ImageView,放入reSize的Bitmap对象,再放入Layout中 */
id++;
ImageView imageView = new ImageView(ex4_23.this);
imageView.setId(id);
imageView.setImageBitmap(resizeBmp);
layout1.addView(imageView);
setContentView(layout1);
/* 因为图片放到最大时放大按钮会disable,所以在缩小时把它重设为enable */
mButton02.setEnabled(true);
}
/* 图片放大的method */
private void big()
{
int bmpWidth=bmp.getWidth();
int bmpHeight=bmp.getHeight();
/* 设置图片放大的比例 */
double scale=1.25;
/* 计算这次要放大的比例 */
scaleWidth=(float)(scaleWidth*scale);
scaleHeight=(float)(scaleHeight*scale);
/* 产生reSize后的Bitmap对象 */
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizeBmp = Bitmap.createBitmap(bmp,0,0,bmpWidth,bmpHeight,matrix,true);
if(id==0)
{
/* 如果是第一次按,就删除原来设置的ImageView */
layout1.removeView(mImageView);
}
else
{
/* 如果不是第一次按,就删除上次放大缩小所产生的ImageView */
layout1.removeView((ImageView)findViewById(id));
}
/* 产生新的ImageView,放入reSize的Bitmap对象,再放入Layout中 */
id++;
ImageView imageView = new ImageView(ex4_23.this);
imageView.setId(id);
imageView.setImageBitmap(resizeBmp);
layout1.addView(imageView);
setContentView(layout1);
/* 如果再放大会超过屏幕大小,就把Button disable */
if(scaleWidth*scale*bmpWidth>displayWidth||scaleHeight*scale*bmpHeight>displayHeight)
{
mButton02.setEnabled(false);
}
}
}
因为在Android中不允许ImageView在产生后,动态修改其长度与宽度,所以为了实现图片放大、缩小的功能,使用的方式是当用户在单击放大或缩小的按钮时,除了将图片作放大或缩小的动作外,并将原来Layout中的ImageView删除,重新产生一个新的ImageView,指定图片给它后,再放入Layout里。用户看起来,就好像是同一张图片在放大或缩小。
在放大、缩小图片文件时使用的Martix对象,除了可以用来作图片的缩放外,还有非常实用的旋转效果,我们将会在后面的范例中示范。
4.24 动态旋转图片
Bitmap与Matrix旋转ImageView
要旋转ImageView其实很简单,先将前一次ImageView里的图片放入暂存Bitmap,接着再利用Bitmap.createBitmap来创建新的Bitmap对象,在创建新的Bitmap对象的同时,搭配Matrix对象里的setRotate()方法动态旋转新创建的Bitmap。然后,再将旋转好的Bitmap对象,以新构造的方式创建新的Bitmap对象,最后再“放入”ImageView中显示,就可以达到旋转ImageView的效果,这个范例的学习重点则在于如何操作BitmapFactory.decodeResource()方法来使用Matrix对图像的控制,为了让旋转能够通过事件来进行,所以在Layout中配置了两个Button Widget,以及一个ImageView Widget。当单击“向左旋转”按钮时,画面的小河马就会向左倾斜;当单击“向右旋转”按钮时,画面的小河马就会向右倾斜。
范例程序
程序设置了两个按钮,分别处理向左及向右旋转的语句,而为了防止旋转角度超过数值范围,所以默认参考值(ScaleAngle)向左最多为−5、向右则最多为5,再利用Matrix对象里的matrix.setRotate()方法,将5*ScaleAngle的计算结果传入作为参数,使其产生每次至少5°的变化,在−20°和20°之间。
Bitmap.createBitmap()方法所扮演的角色为产生暂存的Bitmap,使之每一次(单击按钮时)都“复制”来自原始图“mySourceBmp”的数据,自坐标(0,0)-(原图宽,原图高)复制成为新图,而由于createBitmap()方法的第六个参数可指定Matrix对象,这也就是本范例程序旋转画面的唯一关键。
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
public class ex4_24 extends Activity {
private Button mButton1;
private Button mButton2;
private TextView mTextView1;
private ImageView mImageView1;
private int ScaleTimes;
private int ScaleAngle;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mButton1 =(Button) findViewById(R.id.myButton1);
mButton2 =(Button) findViewById(R.id.myButton2);
mTextView1 = (TextView) findViewById(R.id.myTextView1);
mImageView1 = (ImageView) findViewById(R.id.myImageView1);
ScaleTimes = 1;
ScaleAngle = 1;
final Bitmap mySourceBmp = BitmapFactory.decodeResource(getResources(), R.drawable.hippo);
final int widthOrig = mySourceBmp.getWidth();
final int heightOrig = mySourceBmp.getHeight();
/* 程序刚运行,加载默认的Drawable */
mImageView1.setImageBitmap(mySourceBmp);
/* 向左旋转按钮 */
mButton1.setOnClickListener(new Button.OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
ScaleAngle--;
if(ScaleAngle<-5)
{
ScaleAngle = -5;
}
/* ScaleTimes=1,维持1:1的宽高比例*/
int newWidth = widthOrig * ScaleTimes;
int newHeight = heightOrig * ScaleTimes;
float scaleWidth = ((float) newWidth) / widthOrig;
float scaleHeight = ((float) newHeight) / heightOrig;
Matrix matrix = new Matrix();
/* 使用Matrix.postScale设置维度 */
matrix.postScale(scaleWidth, scaleHeight);
/* 使用Matrix.postRotate方法旋转Bitmap*/
//matrix.postRotate(5*ScaleAngle);
matrix.setRotate(5*ScaleAngle);
/* 创建新的Bitmap对象 */
Bitmap resizedBitmap = Bitmap.createBitmap(mySourceBmp, 0, 0, widthOrig, heightOrig, matrix, true);
/**/
BitmapDrawable myNewBitmapDrawable = new BitmapDrawable(resizedBitmap);
mImageView1.setImageDrawable(myNewBitmapDrawable);
mTextView1.setText(Integer.toString(5*ScaleAngle));
}
});
/* 向右旋转按钮 */
mButton2.setOnClickListener(new Button.OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
ScaleAngle++;
if(ScaleAngle>5)
{
ScaleAngle = 5;
}
/* ScaleTimes=1,维持1:1的宽高比例*/
int newWidth = widthOrig * ScaleTimes;
int newHeight = heightOrig * ScaleTimes;
/* 计算旋转的Matrix比例 */
float scaleWidth = ((float) newWidth) / widthOrig;
float scaleHeight = ((float) newHeight) / heightOrig;
Matrix matrix = new Matrix();
/* 使用Matrix.postScale设置维度 */
matrix.postScale(scaleWidth, scaleHeight);
/* 使用Matrix.postRotate方法旋转Bitmap*/
//matrix.postRotate(5*ScaleAngle);
matrix.setRotate(5*ScaleAngle);
/* 创建新的Bitmap对象 */
Bitmap resizedBitmap = Bitmap.createBitmap(mySourceBmp, 0, 0, widthOrig, heightOrig, matrix, true);
/**/
BitmapDrawable myNewBitmapDrawable = new BitmapDrawable(resizedBitmap);
mImageView1.setImageDrawable(myNewBitmapDrawable);
mTextView1.setText(Integer.toString(5*ScaleAngle));
}
});
}
}
扩展学习
Matrix类的设计,不仅是二维空间的结构,事实上,它原始的设计是3´3的矩阵,由于Matrix类并不需要构造器,因此在声明Matrix对象之后,可以调用reset()方法或set()方法产生新的矩阵,如同本范例的setRotate一样。
回来看看,我们在这个范例程序中,也放上了添加注释的语句matrix.postRotate(5*ScaleAngle),经测试后,无论是使用postRotate()方法或setRotate()方法,效果都是相同的,但较困惑的是Google的官方SDK文件中,所描述的postRotate()方法的原型如下:
boolean postRotate(float degrees, float px, float py)
经测试postRotate()方法并没有第二、第三个参数需要传递,这是在Android SDK 1.0_r2才发现的,未来可能会因为改版而有所改变。
另外,Matrix还有一个常用的postScale()方法,可通过矩阵的方式用以指定其缩放大小,其原型如下:
public boolean postScale(float sx, float sy, float px, float py)
使用的公式为:M' = S(sx, sy, px, py)* M,示意的片段程序如下。
final Bitmap mySourceBmp =
BitmapFactory.decodeResource(getResources(), R.drawable.hippo)
Matrix mx = new Matrix();
mx.postScale
(
(float)20/mySourceBmp.getWidth(),
(float)20/mySourceBmp.getHeight()
);
mySourceBmp = Bitmap.createBitmap
(bm, 0, 0, bm.getWidth(), bm.getHeight(), mx, true);
mImageView1.setImageBitmap(mySourceBmp);
- Android第十三站 众多豪华控件 图片处理进阶
- Android第十四站 众多豪华控件 对话框进阶
- Android第六站 众多豪华控件 RadioGroup 菜单
- Android第十二站 众多豪华控件 列表应用
- Android第十二站 众多豪华控件 列表应用
- Android RenderScript的应用和进阶 图片高效处理
- Android进阶图片处理之三级缓存方案
- Android进阶处理图片之压缩图片大小、Lru内存解决方案
- Android进阶图片处理之DiskLruCache解析 硬盘缓存方案
- Android自定义控件进阶
- 我的Android进阶之旅------>Android 众多的布局属性详解
- Android进阶图片处理内存优化系列之图片墙案例
- Android进阶图片处理之三级缓存图片框架BitmapUtil的使用方法
- Android[初级教程]第十三章 ProgressDialog控件
- Qt使用一张图片上的众多icon作为控件图标
- 我的Android进阶之旅------>Android图片处理(Matrix,ColorMatrix)
- Android进阶-自定义控件一
- UI基础第十三弹: UIScrollView控件图片缩放
- Hadoop FAQ
- 做个无畏、有闯劲的程序员
- 文件加密的一种方式-压缩
- P2P之UDP穿透NAT的原理和实现
- Get CLR call stack in dump analysis
- Android第十三站 众多豪华控件 图片处理进阶
- 3des
- 各种Soft Shadow Mapping算法及推导过程
- 法线贴图、视差贴图和普通着色
- 生活乱了,看论语调节调节
- 40个UI设计工具和资源
- JavaScript对象及继承教程
- PowerDesigner中name和comment互換
- Android第十四站 众多豪华控件 对话框进阶