标签:android 图像增强处理 intend传值 调用其他类方法 基础知识
经过几门考试之后,终于有时间整合下自己的Anroid项目"随手拍"的图像处理部分了,主要是结合前面几篇文章讲解的各种android图像处理技术和PopupWindow布局,图像初步整合效果如下.由于该软件目前还未答辩,所以结束后会共享所有的源代码,可能需要一个月后吧,抱歉~
在"随手拍"中点击发布,有添加图片按钮,点击出现"选择本地图片"和"照相截拆选择",显示图片至另一个处理界面,底部五个LinearLayout布局(查看|增强|效果|相框|美白)通过PopupWindow实现弹出窗体,各种处理供选择.
在这篇这次整合中我主要想讲解四个问题:
(PS:我也不知道更好的整合方法,希望有好的android项目整合方法与作者探讨)
1.如何通过Intend实现给其他活动传参,并且传递图像路径string,实现在另外一个窗体显示图像;
2.如何实现把具体图像处理算法定义不同类,处理界面通过Import引入并调用;
3.如何通过SeekBar实现图像的ColorMatrix处理,包括饱和度、图像RGB和亮度;
4.最后简单介绍SeekBar和ColorMatrix的使用方法.
显示效果图如下:
该方法主要通过Intent实现,通过其putExtra()方法存储要传递的图片路径于Intent中,启动另外一个活动时通过getStringExtra取出数据即可.核心代码:
//主活动传递图片path给处理活动
Intent intent = new Intent(this, ProcessActivity.class);
intent.putExtra("path", path);
startActivity(intent);
//处理活动中取数据 注意参数对应putExtra("path", path)
Intent intent = getIntent();
String path = intent.getStringExtra("path");
ShowPhotoByImageView(path); //自定义显示图片函数
具体代码操作如下,在activity_main.xml文件中定义一个按钮"button1",再在activity_process.xml中定义图片处理的布局如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="@+id/layout_bottom"
android:layout_width="fill_parent"
android:layout_height="110dp"
android:layout_alignParentBottom="true"
android:gravity="center">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="2dp"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="20px"
android:paddingTop="10px"
android:text="饱和" />
<SeekBar
android:id="@+id/seekBarSaturation"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="255"
android:progress="127"
android:secondaryProgress="75" >
</SeekBar>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="20px"
android:text="色相" />
<SeekBar
android:id="@+id/seekBarHue"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="255"
android:progress="127"
android:secondaryProgress="75" >
</SeekBar>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="20px"
android:text="亮度" />
<SeekBar
android:id="@+id/seekBarLum"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="255"
android:progress="127"
android:secondaryProgress="75" >
</SeekBar>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
<!-- 添加layout_above才显示顶部布局 -->
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="@id/layout_bottom"
android:background="#EFDFDF"
android:layout_alignParentTop="true"
android:gravity="center" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_horizontal" />
</RelativeLayout>
</RelativeLayout>
然后MainActivity.java文件选择图片并给Intent中装载选择图片的路径,传递给ProcessActivity.java文件处理.
public class MainActivity extends Activity {
//自定义变量
private Button selectPhoto; //选择图片
private final int IMAGE_OPEN = 1; //打开图片标记
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//选择图片并传递图片路径信息给处理图片活动
selectPhoto = (Button) findViewById(R.id.button1);
selectPhoto.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, IMAGE_OPEN);
}
});
}
//获取图片路径 响应startActivityForResult
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//打开图片
if(resultCode==RESULT_OK && requestCode==IMAGE_OPEN) {
Uri uri = data.getData();
if (!TextUtils.isEmpty(uri.getAuthority())) {
//查询选择图片
Cursor cursor = getContentResolver().query(
uri,
new String[] { MediaStore.Images.Media.DATA },
null,
null,
null);
//返回 没找到选择图片
if (null == cursor) {
return;
}
//光标移动至开头 获取图片路径
cursor.moveToFirst();
String path = cursor.getString(cursor
.getColumnIndex(MediaStore.Images.Media.DATA));
//Toast.makeText(this, path, Toast.LENGTH_SHORT).show();
//向处理活动传递数据
Intent intent = new Intent(this, ProcessActivity.class); //主活动->处理活动
intent.putExtra("path", path);
startActivity(intent);
} else {
Intent intent = new Intent(this, ProcessActivity.class); //主活动->处理活动
intent.putExtra("path", uri.getPath());
startActivity(intent);
}
} //end if 打开图片
}
} 然后是ProcessActivity.java中具体处理,通过自定义函数ShowPhotoByImageView(String path)获取传递的图像路径并显示,代码如下:public class ProcessActivity extends Activity {
//自定义变量
private ImageView imageShow; //显示图片
private Bitmap bmp; //载入图片
private SeekBar seekBar1; //SeekBar 饱和度
private SeekBar seekBar2; //SeekBar 色相
private SeekBar seekBar3; //SeekBar 亮度
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_process);
//获取控件
imageShow = (ImageView) findViewById(R.id.imageView1);
//载入数据
Intent intent = getIntent();
String path = intent.getStringExtra("path"); //对应putExtra("path", path);
//自定义函数 显示图片
ShowPhotoByImageView(path);
}
/*
* 函数功能 显示图片
* 参数 String path 图片路径,源自MainActivity选择传参
*/
private void ShowPhotoByImageView(String path)
{
if (null == path) {
Toast.makeText(this, "载入图片失败", Toast.LENGTH_SHORT).show();
finish();
}
//获取分辨率
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels; //屏幕水平分辨率
int height = dm.heightPixels; //屏幕垂直分辨率
try {
//Load up the image's dimensions not the image itself
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
bmp = BitmapFactory.decodeFile(path,bmpFactoryOptions);
int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);
int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);
//压缩显示 值为16时很模糊且图片大小没变化
if(heightRatio>1&&widthRatio>1) {
if(heightRatio>widthRatio) {
bmpFactoryOptions.inSampleSize = heightRatio*2;
}
else {
bmpFactoryOptions.inSampleSize = widthRatio*2;
}
}
//图像真正解码
bmpFactoryOptions.inJustDecodeBounds = false;
bmp = BitmapFactory.decodeFile(path,bmpFactoryOptions);
imageShow.setImageBitmap(bmp); //显示照片
} catch(Exception e) {
e.printStackTrace();
}
}
}
同时需要注意需要在AndroidManifest.xml中注册活动,否则会报错无法响应;因为需要操作SD卡,所以还需要声明权限.如下所示:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testimage"
android:versionCode="1"
android:versionName="1.0" >
<!-- 申明权限 操作SD卡 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /></span>
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.testimage.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 注册新活动 -->
<activity android:name=".ProcessActivity">
</activity></span>
</application>
</manifest> 此时运行效果如下图所示,能显示一张图片,第一部分主要是讲述通过Intent传递值并显示图片,其主要内容就是开头部分的核心代码,但是个人认为对初学者来说我认为还是非常有用的. 在使用android时,我发现它引用其它类函数非常方便,具体方法如下:
//自定义类 实现饱和度、色相、亮度图像增强处理
public class IncreaseProcessImage
{
private Bitmap mBitmap;
//构造函数
public IncreaseProcessImage(Bitmap bmp)
{
mBitmap = bmp;
}
//图像增强
//flag=0表示是否改变饱和度 flag=1表示是否改变色相 flag=2表示是否改变亮度
public Bitmap IncreaseProcessing(Bitmap bmp, int flag)
{
...
return bitmap;
}
} 在处理类中调用其它类的方法代码如下:
//引入图像增强处理类
import com.example.testimage.IncreaseProcessImage;
public class ProcessActivity extends Acticity {
...
//调用IncreaseProcessImage类中处理方法
IncreaseProcessImage increaseProcess = null;
increaseProcess = new IncreaseProcessImage(bmp);
Bitmap mbmp = increaseProcess.IncreaseProcessing(bmp,flag);
imageShow.setImageBitmap(mbmp);
...
} 其实我一直都不太会整合项目,不论是C#、C++还是Java的项目,也不知道如何去提高.而且这部分文章也有点少,很多都是技术文章和提高代码质量的,我的"随手拍"基本形式就如下: 在图像增强部分主要通过ColorMatrix图像颜色处理及SeekBar控件实现.直接上代码吧!此部分主要参照那本图像处理的书.
IncreaseProcessImage.java类
//自定义类实现图像增强效果处理 包括:饱和度、色相、亮度
public class IncreaseProcessImage
{
private Bitmap mBitmap;
//构造函数
public IncreaseProcessImage(Bitmap bmp)
{
mBitmap = bmp;
}
//自定义变量
private ColorMatrix mSaturationMatrix; //饱和度
private ColorMatrix mHueMatrix; //色相
private ColorMatrix mLumMatrix; //亮度
private ColorMatrix mAllMatrix;
private float mSaturationValue = 0F;
private float mHueValue = 0F;
private float mLumValue = 0F;
//SeekBar中间值127 [0-255]
private static final int MIDDLE_VALUE = 127;
private static final int MAX_VALUE =255;
/*
* 设置饱和度值
*/
public void setSaturation(int value) {
mSaturationValue = value * 1.0F / MIDDLE_VALUE;
}
/*
* 设置色相值
*/
public void SetHue(int value) {
mHueValue = (value - MIDDLE_VALUE) * 1.0F / MIDDLE_VALUE * 180;
}
/*
* 设置亮度值
*/
public void SetLum(int value) {
mLumValue = value * 1.0F / MIDDLE_VALUE;
}
/*
* 图像增强
* 饱和度处理 色相处理 亮度处理
* flag=0表示是否改变饱和度 flag=1表示是否改变色相 flag=2表示是否改变亮度
*/
public Bitmap IncreaseProcessing(Bitmap bmp, int flag)
{
//创建一个相同尺寸可变的位图区,用于绘制新图
Bitmap bitmap = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setAntiAlias(true); //给Canvas加上抗锯齿标志,边缘平滑处理
if(mAllMatrix == null) {
mAllMatrix = new ColorMatrix();
}
if(mSaturationMatrix == null) {
mSaturationMatrix = new ColorMatrix();
}
if(mHueMatrix == null) {
mHueMatrix = new ColorMatrix();
}
if(mLumMatrix == null) {
mLumMatrix = new ColorMatrix();
}
//图像处理
if(flag==0) { //饱和度
//饱和度值最小可设为0,此时表示灰度图 为1表示饱和度不变,设置大于1就是过饱和
mSaturationMatrix.reset(); //设为默认值
mSaturationMatrix.setSaturation(mSaturationValue);
}
else if(flag==1) { //色相
//hueColor是色轮旋转角度,正值表示顺时针旋转,负值表示逆时针旋转
mHueMatrix.reset();
mHueMatrix.setRotate(0, mHueValue); //红色区在色轮上旋转的角度
mHueMatrix.setRotate(1, mHueValue); //绿色区在色轮上旋转的角度
mHueMatrix.setRotate(2, mHueValue); //蓝色取在色轮上旋转的角度
}
else if(flag==2) { //亮度
mLumMatrix.reset();
//红绿蓝三色按相同比例,最后参数1表示透明度不变
mLumMatrix.setScale(mLumValue, mLumValue, mLumValue, 1);
}
//设置AllMatrix
mAllMatrix.reset();
mAllMatrix.postConcat(mHueMatrix); //效果叠加
mAllMatrix.postConcat(mSaturationMatrix);
mAllMatrix.postConcat(mLumMatrix);
//设置颜色变换效果
paint.setColorFilter(new ColorMatrixColorFilter(mAllMatrix));
canvas.drawBitmap(bmp, 0, 0, paint); //颜色变化后输出到新创建位图区
return bitmap;
}
/*
* End
*/
}
然后修改ProcessActivity.java处理活动,同时需要为活动ProcessActivity添加接口OnSeekBarChangeListener,修改后代码如下:
//引入图像增强处理类
import com.example.testimage.IncreaseProcessImage;
public class ProcessActivity extends Activity implements OnSeekBarChangeListener {
//自定义变量
private ImageView imageShow; //显示图片
private Bitmap bmp; //载入图片
private SeekBar seekBar1; //SeekBar 饱和度
private SeekBar seekBar2; //SeekBar 色相
private SeekBar seekBar3; //SeekBar 亮度
IncreaseProcessImage increaseProcess = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_process);
//获取控件
imageShow = (ImageView) findViewById(R.id.imageView1);
seekBar1 = (SeekBar) findViewById(R.id.seekBarSaturation); //饱和度
seekBar2 = (SeekBar) findViewById(R.id.seekBarHue); //色相
seekBar3 = (SeekBar) findViewById(R.id.seekBarLum); //亮度
//载入数据
Intent intent = getIntent();
String path = intent.getStringExtra("path"); //对应putExtra("path", path);
//自定义函数 显示图片
ShowPhotoByImageView(path);
//自定义函数 设置SeekBar监听事件
SetClickTouchListener();
}
/*
* 函数功能 显示图片
* 参数 String path 图片路径,源自MainActivity选择传参
*/
private void ShowPhotoByImageView(String path)
{
if (null == path) {
Toast.makeText(this, "载入图片失败", Toast.LENGTH_SHORT).show();
finish();
}
//获取分辨率
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels; //屏幕水平分辨率
int height = dm.heightPixels; //屏幕垂直分辨率
try {
//Load up the image's dimensions not the image itself
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
bmp = BitmapFactory.decodeFile(path,bmpFactoryOptions);
int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);
int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);
//压缩显示 值为16时很模糊且图片大小没变化
if(heightRatio>1&&widthRatio>1) {
if(heightRatio>widthRatio) {
bmpFactoryOptions.inSampleSize = heightRatio*2;
}
else {
bmpFactoryOptions.inSampleSize = widthRatio*2;
}
}
//图像真正解码
bmpFactoryOptions.inJustDecodeBounds = false;
bmp = BitmapFactory.decodeFile(path,bmpFactoryOptions);
imageShow.setImageBitmap(bmp); //显示照片
} catch(Exception e) {
e.printStackTrace();
}
}
//设置SeekBar监听事件
private void SetClickTouchListener()
{
/*
* 设置Seekbar变化监听事件
* 注意:此时为活动ProcessActivity添加接口
* ProcessActivity extends Activity implements OnSeekBarChangeListener
*/
seekBar1.setOnSeekBarChangeListener(this);
seekBar2.setOnSeekBarChangeListener(this);
seekBar3.setOnSeekBarChangeListener(this);
increaseProcess = new IncreaseProcessImage(bmp);
}
//拖动值监听
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch)
{
int flag = 0;
switch(seekBar.getId()) {
case R.id.seekBarSaturation: //饱和度
flag = 0;
increaseProcess.setSaturation(progress);
break;
case R.id.seekBarHue: //色相
flag = 1;
increaseProcess.SetHue(progress);
break;
case R.id.seekBarLum: //亮度
flag = 2;
increaseProcess.SetLum(progress);
break;
}
imageShow.setImageBitmap(increaseProcess.IncreaseProcessing(bmp,flag));
}
//SeekBar 开始拖动 否则ProcessActivity报错
public void onStartTrackingTouch(SeekBar seekBar)
{
}
//SeekBar 停止拖动
public void onStopTrackingTouch(SeekBar seekBar)
{
}
} 此时运行效果如下://监听数值改变 通常使用它监听值变化 public void onProgressChanged(SeekBar seekBar,int progress, boolean fromTouch); //监听开始拖动 public void onStartTrackingTouch(SeekBar seekBar); //监听停止拖动 public void onStopTrackingTouch(SeekBar seekBar);
其中在XML中可以设置其SeekBar常用属性如下:
android:max="255" //设置拖动条最大值 android:progress="100" //设置当前进度值 android:secondaryProgress="75" //设置第二进度,通常视频缓冲时会见到该效果 android:progressDrawable="@drawable/" //设置进图条图样 android:thumb="@drawable/" //设置滑块图样 可定义xml设置其变换而ColorMatrix主要介绍下面官方文档常用几个函数(android.graphics.ColorMatrix)
[Android] 图像处理软件整合之处理ColorMatrix和Intend传递路径显示图像
标签:android 图像增强处理 intend传值 调用其他类方法 基础知识
原文地址:http://blog.csdn.net/eastmount/article/details/41668583