前一篇文章讲述了Android触屏setOnTouchListener实现突破缩放、移动、绘制和添加水印,继续我的"随手拍"项目完成给图片添加相框、圆形圆角显示图片和图像合成的功能介绍.希望文章对大家有所帮助.

一. 打开图片和显示assets文件中图片

首先,对XML中activity_main.xml进行布局,通过使用RelativeLayout相对布局完成(XML代码后面附).然后,在Mainctivity.java中public class MainActivity extends Activity函数添加代码如下,添加点击按钮监听事件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//控件
private Button openImageBn;            //打开图片
private Button showImageBn;            //显示assets资源图片
private Button showImageBn1;           //模式1加成
private Button showImageBn2;           //模式2加成
private Button roundImageBn;           //圆角图片
private ImageView imageShow;           //显示图片
//自定义变量
private Bitmap bmp;                    //原始图片
private final int IMAGE_OPEN = 0 ;      //打开图片
private Canvas canvas;                 //画布
private Paint paint;                   //画刷
         
@Override
protected void onCreate(Bundle savedInstanceState) {
     super .onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
     //打开图片
     openImageBn = (Button)findViewById(R.id.button1);
     imageShow = (ImageView) findViewById(R.id.imageView1);
     openImageBn.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);
         }
     });
     if (savedInstanceState == null ) {
         getFragmentManager().beginTransaction()
                 .add(R.id.container, new PlaceholderFragment())
                 .commit();
     }
}
//打开图片
protected void onActivityResult( int requestCode, int resultCode, Intent data) {
      super .onActivityResult(requestCode, resultCode, data); 
      if (resultCode==RESULT_OK && requestCode==IMAGE_OPEN) { 
         Uri imageFileUri = data.getData();
         DisplayMetrics dm = new DisplayMetrics();
         getWindowManager().getDefaultDisplay().getMetrics(dm); 
         int width = dm.widthPixels;    //手机屏幕水平分辨率  
         int height = dm.heightPixels;  //手机屏幕垂直分辨率
         try
             //载入图片尺寸大小没载入图片本身 true
             BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options(); 
             bmpFactoryOptions.inJustDecodeBounds = true
             bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageFileUri), null , bmpFactoryOptions); 
             int heightRatio = ( int )Math.ceil(bmpFactoryOptions.outHeight/( float )height); 
             int widthRatio = ( int )Math.ceil(bmpFactoryOptions.outWidth/( float )width);   
             //inSampleSize表示图片占原图比例 1表示原图
             if (heightRatio> 1 &&widthRatio> 1 ) { 
                 if (heightRatio>widthRatio) { 
                     bmpFactoryOptions.inSampleSize = heightRatio; 
                
                 else
                     bmpFactoryOptions.inSampleSize = widthRatio; 
                
             }                  
             //图像真正解码 false
             bmpFactoryOptions.inJustDecodeBounds = false ;                
             bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageFileUri), null , bmpFactoryOptions);   
             imageShow.setImageBitmap(bmp);
         }
         catch (FileNotFoundException e) {
             e.printStackTrace(); 
         }
     //end if
}

上面点击"打开"按钮能实现打开图片,而在讲述为图片添加边框时,它其实就是通过两张或多张图片的合成实现的.
在jacpy.may《Android图片处理总结》文档中建议图片不要放在drawable目录下,因为屏幕分辨率会影响图片的大小.最好放在assets目录里,它代表应用无法直接访问的原生资源(通常加载PNG透明图实现边框合成),只能以流的方式读取并且小于1M.
读取assets文件夹中图片的方法如下,首先手动添加PNG图片至assets目录,然后在omCreate函数中添加如下代码:

?
1
2
3
4
5
6
7
8
9
//显示assets中图片
showImageBn = (Button)findViewById(R.id.button2);
showImageBn.setOnClickListener( new OnClickListener() {
     @Override
     public void onClick(View v) {       
         Bitmap bitmap = getImageFromAssets( "image01.png" );
         imageShow.setImageBitmap(bitmap); 
     }
});

再通过自定义函数getImageFromAssets实现获取图片"image01.png":

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//获取assets中资源并转换为Bitmap
private Bitmap getImageFromAssets(String fileName)
{
     //Android中使用assets目录存放资源,它代表应用无法直接访问的原生资源
     Bitmap imageAssets = null ;
     AssetManager am = getResources().getAssets();
     try {
         InputStream is = am.open(fileName);
         imageAssets = BitmapFactory.decodeStream(is);
         is.close();
     } catch (IOException e) {
         e.printStackTrace();
     }
     return imageAssets;
}

显示效果如下图所示:
   
其中XML代码如下:

?
1
2
<relativelayout android:id= "@+id/container" android:layout_height= "match_parent" android:layout_width= "match_parent" tools:context= "com.example.touchimagetest.MainActivity" tools:ignore= "MergeRootFrame" xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http://schemas.android.com/tools" >    <relativelayout android:gravity= "center" android:id= "@+id/MyLayout_bottom" android:layout_alignparentbottom= "true" android:layout_height= "50dp" android:layout_width= "fill_parent" android:orientation= "horizontal" >
</relativelayout></relativelayout><strong style= "font-family: Arial, Verdana, sans-serif;" >二. 添加相框与图片合成</strong>

然后开始完成图片合成的工作,这里我采用两种方法完成.继续在onCreate函数中添加代码:

?
1
2
3
4
5
6
7
8
9
//模式1合成图片
showImageBn1 = (Button)findViewById(R.id.button3);
showImageBn1.setOnClickListener( new OnClickListener() {
     @Override
     public void onClick(View v) {
         Bitmap bitmap = getImageFromAssets( "image01.png" );
         addFrameToImage(bitmap);
     }
});

通过自定义函数addFrameToImage实现加载图片合成.首先创建一个空的可变为图对象,它的大小和配置与打开的图像相同,随后构建一个Canvas对象和一个Paint对象,在画布上绘制第一个位图对象,它成为了合成操作的目标.
现在设置Paint对象上的过渡模式,通过传入一个定义操作模式的常量,实例化一个新的PorterDuffXfermode对象.然后在Canvas对象上绘制第二个位图对象,并将ImageView设置为新的位图对象.代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//图片合成1
private void addFrameToImage(Bitmap bm) //bmp原图(前景) bm资源图片(背景)
{
     Bitmap drawBitmap =Bitmap.createBitmap(bmp.getWidth(),
             bmp.getHeight(), bmp.getConfig());
     canvas = new Canvas(drawBitmap);
     paint = new Paint();
     canvas.drawBitmap(bmp, 0 , 0 , paint);
     paint.setXfermode( new PorterDuffXfermode(android.
             graphics.PorterDuff.Mode.LIGHTEN));
     //对边框进行缩放
     int w = bm.getWidth();
     int h = bm.getHeight();
     //缩放比 如果图片尺寸超过边框尺寸 会自动匹配
     float scaleX = bmp.getWidth()*1F / w;     
     float scaleY = bmp.getHeight()*1F / h;
     Matrix matrix = new Matrix();
     matrix.postScale(scaleX, scaleY);   //缩放图片
     Bitmap copyBitmap =  Bitmap.createBitmap(bm, 0 , 0 , w, h, matrix, true );
     canvas.drawBitmap(copyBitmap, 0 , 0 , paint);
     imageShow.setImageBitmap(drawBitmap);  
}

第二种方法是参照《Android多媒体开发高级编程》,但是它图片十四合成效果不是很好:

?
1
2
3
4
5
6
7
8
9
10
//模式2合成图片
showImageBn2 = (Button)findViewById(R.id.button4);
showImageBn2.setOnClickListener( new OnClickListener() {
     @Override
     public void onClick(View v) {
         Bitmap bitmap = getImageFromAssets( "image07.png" );
         //第二种合成方法
         imageShow.setImageBitmap(addFrameToImageTwo(bitmap));
     }
});

然后通过自定义函数实现:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//图片合成 
private Bitmap addFrameToImageTwo(Bitmap frameBitmap) //bmp原图 frameBitmap资源图片(边框)
{
     //bmp原图 创建新位图
     int width = bmp.getWidth(); 
     int height = bmp.getHeight();
     Bitmap drawBitmap =Bitmap.createBitmap(width, height, Config.RGB_565);
     //对边框进行缩放
     int w = frameBitmap.getWidth();
     int h = frameBitmap.getHeight();
     float scaleX = width*1F / w;        //缩放比 如果图片尺寸超过边框尺寸 会自动匹配
     float scaleY = height*1F / h;
     Matrix matrix = new Matrix();
     matrix.postScale(scaleX, scaleY);   //缩放图片
     Bitmap copyBitmap =  Bitmap.createBitmap(frameBitmap, 0 , 0 , w, h, matrix, true );
     
     int pixColor = 0
     int layColor = 0
     int newColor = 0 ;
     
     int pixR = 0
     int pixG = 0
     int pixB = 0
     int pixA = 0
       
     int newR = 0
     int newG = 0
     int newB = 0
     int newA = 0
       
     int layR = 0
     int layG = 0
     int layB = 0
     int layA = 0
       
     float alpha = 0 .8F;
     float alphaR = 0F; 
     float alphaG = 0F; 
     float alphaB = 0F;
     
     for ( int i = 0 ; i < width; i++) 
    
         for ( int k = 0 ; k < height; k++) 
        
             pixColor = bmp.getPixel(i, k); 
             layColor = copyBitmap.getPixel(i, k); 
             // 获取原图片的RGBA值  
             pixR = Color.red(pixColor); 
             pixG = Color.green(pixColor); 
             pixB = Color.blue(pixColor); 
             pixA = Color.alpha(pixColor); 
             // 获取边框图片的RGBA值  
             layR = Color.red(layColor); 
             layG = Color.green(layColor); 
             layB = Color.blue(layColor); 
             layA = Color.alpha(layColor); 
             // 颜色与纯黑色相近的点  
             if (layR < 20 && layG < 20 && layB < 20
            
                 alpha = 1F; 
            
             else 
            
                 alpha = 0 .3F; 
            
             alphaR = alpha; 
             alphaG = alpha; 
             alphaB = alpha; 
             // 两种颜色叠加  
             newR = ( int ) (pixR * alphaR + layR * ( 1 - alphaR)); 
             newG = ( int ) (pixG * alphaG + layG * ( 1 - alphaG)); 
             newB = ( int ) (pixB * alphaB + layB * ( 1 - alphaB)); 
             layA = ( int ) (pixA * alpha + layA * ( 1 - alpha)); 
             // 值在0~255之间  
             newR = Math.min( 255 , Math.max( 0 , newR)); 
             newG = Math.min( 255 , Math.max( 0 , newG)); 
             newB = Math.min( 255 , Math.max( 0 , newB)); 
             newA = Math.min( 255 , Math.max( 0 , layA)); 
             //绘制
             newColor = Color.argb(newA, newR, newG, newB); 
             drawBitmap.setPixel(i, k, newColor); 
        
    
     return drawBitmap;
}

它的运行效果如下所示,其中前2附图是方法一,但是它的合成效果不是很优秀,而第三张图是第二种方法,但是它的响应时间稍微要长些.
     在第一种方法通过PoterDuffXfermode类作为过渡模式,该类因Thomas Porter和Tom Duff而得名,他们于1984年在ACM SIGGRAPH计算机图形学发表“Compositing digital images(合成数字图像)”的文章,它介绍了彼此重叠绘制图像的不同规则.这些规则定义了哪些图像的哪些部分将出现在结果输出中.
在Android的PorterDuff.Mode类中列举了Porter和Duff及其他更多人制定的规则.
android.graphics.PorterDuff.Mode.SRC:此规则意味着只绘制源图像,当前它正是应用此规则的Paint对象.
android.graphics.PorterDuff.Mode.DST:此规则意味着只显示目标图像,在已有画布上的初始图像.
如下图所示,定义Mode值如下:

其中,有4个规则定义了当一幅图像放置在另一幅图像上时如何合成这两幅图像,它是我们经常使用的值:
android.graphics.PorterDuff.Mode.LIGHTEN:获得每个位置上两幅图像中最亮的像素并显示.
android.graphics.PorterDuff.Mode.DARKEN:获得每个位置上两幅图像中最暗的像素并显示.
an droid.graphics.PorterDuff.Mode.MULTIPLY:将每个位置的两个像素相乘,除以255,使用该值创建一个新的像素进行显示.结果颜色=顶部颜色*底部颜色/255.
android.graphics.PorterDuff.Mode.SCREEN:反转每个颜色,执行相同操作.结果颜色=255-(((255-顶部颜色)*(255-底部颜色))/255)

三. 圆形和圆角矩形显示图片

最后讲述如何实现圆形和圆角矩形显示图片,在onCreate函数中添加如下代码:

?
1
2
3
4
5
6
7
8
//圆角合成图片
roundImageBn = (Button)findViewById(R.id.button5);
roundImageBn.setOnClickListener( new OnClickListener() {
     @Override
     public void onClick(View v) {
         imageShow.setImageBitmap(getRoundedCornerBitmap(bmp) );
     }
});

然后通过自定义函数getRoundedCornerBitmap实现圆形:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//生成圆角图片
private Bitmap getRoundedCornerBitmap(Bitmap bitmap)
{
     Bitmap roundBitmap = Bitmap.createBitmap(bitmap.getWidth(),
          bitmap.getHeight(), Config.ARGB_8888);
      Canvas canvas = new Canvas(roundBitmap);
      int color = 0xff424242 ;
      Paint paint = new Paint();
      //设置圆形半径
      int radius;
      if (bitmap.getWidth()>bitmap.getHeight()) {
          radius = bitmap.getHeight()/ 2 ;
      }
      else {
          radius = bitmap.getWidth()/ 2 ;
      }
      //绘制圆形
      paint.setAntiAlias( true );
      canvas.drawARGB( 0 , 0 , 0 , 0 );
      paint.setColor(color);
      canvas.drawCircle( bitmap.getWidth()/ 2 , bitmap.getHeight() / 2 , radius, paint);
      paint.setXfermode( new PorterDuffXfermode(Mode.SRC_IN));
      canvas.drawBitmap(bitmap, 0 , 0 , paint);
      return roundBitmap;
}

同样,如果把该函数里面内容替换即可实现圆形矩形显示图片:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private Bitmap getRoundedCornerBitmap(Bitmap bitmap)
{
     //绘制圆角矩形
     Bitmap roundBitmap = Bitmap.createBitmap(bitmap.getWidth(),
          bitmap.getHeight(), Config.ARGB_8888);
      Canvas canvas = new Canvas(roundBitmap);
      int color = 0xff424242 ;
      Paint paint = new Paint();
      Rect rect = new Rect( 0 , 0 , bitmap.getWidth(), bitmap.getHeight());
      RectF rectF = new RectF(rect);
      float roundPx = 80 ;      //转角设置80
      //绘制
      paint.setAntiAlias( true );
      canvas.drawARGB( 0 , 0 , 0 , 0 );
      paint.setColor(color);
      canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
      paint.setXfermode( new PorterDuffXfermode(Mode.SRC_IN));
      canvas.drawBitmap(bitmap, rect, rect, paint);
}

运行结果如下图所示:
    总结:
该文章主要讲述如何给图像增加相框,圆角显示图像和图像合成的介绍.里面主要通过源码并有详细的过程,为什么要写这篇文章?因为在图像处理中我认为这种添加边框、改变边框、图片合成都属于同一种类型的变化和渲染.该图像处理软件还没有整合,推荐大家看下面资料中两本书.
最后希望文章对大家有所帮助,如果有不足或错误的地方请见谅!不论如何,我觉得这篇文章自己写得不错,自己先给自己一个赞吧!加油\(^o^)/~
下载地址:
源码基本格式如下图所示:

(By:Eastmount 2014-10-31 夜3点 http://blog.csdn.net/eastmount)
参考资料与推荐博文:   1.最该感谢的是两本书的作者《Android多媒体开发高级编程》和《Android图片处理总结 著:jacpy.may》,网上很多资料都是它们.
2.android图像处理系列之六--给图片添加边框(下)-图片叠加
作者-SJF0115 他是转载了该书的一些文章,也非常不错.
3.Android 图片合成:添加蒙板效果 不规则相框 透明度渐变效果的实现
作者-HappyDelano 非常不错的文章,讲述了4张图实现桃心显示的效果.
4.Android图片合成 作者-johnlxj 讲述了图片合成的实现过程.
5.Android 完美实现图片圆角和圆形(对实现进行分析)
作者-鸿洋_ 该作者很多android文章都非常不错
6.android 画图之setXfermode 作者-lipeng88213 推荐起链接的Android图片倒影
7.Android ImageView点击选中后添加边框 作者-黑米粥 该方法在切换图片中实用
8.android 轻松实现在线即时聊天【图片、语音、表情、文字】

给图像添加相框、圆形圆角显示图片、图像合成知识相关推荐

  1. [Android] 给图像添加相框、圆形圆角显示图片、图像合成知识

        前一篇文章讲述了Android触屏setOnTouchListener实现突破缩放.移动.绘制和添加水印,继续我的"随手拍"项目完成给图片添加相框.圆形圆角显示图片和图像合 ...

  2. Android给图像添加相框、圆形圆角显示图片、图像合成知识

    前一篇文章讲述了Android触屏setOnTouchListener实现突破缩放.移动.绘制和添加水印,继续我的"随手拍"项目完成给图片添加相框.圆形圆角显示图片和图像合成的功能 ...

  3. [Android] 给图像加入相框、圆形圆角显示图片、图像合成知识

        前一篇文章讲述了Android触屏setOnTouchListener实现突破缩放.移动.绘制和加入水印,继续我的"随手拍"项目完毕给图片加入相框.圆形圆角显示图片和图像合 ...

  4. 微信小程序 解决圆形头像显示图片不完全问题

    最近在做微信小程序,遇到这样一个难题,绘制一个圆形的头像,但是有的图片会因为宽度大于高度而致使图片在圆形区域内显示不全,为解决这个问题,我采用了以下办法,现贴出代码共享给大家,大家如果有更好的解决方案 ...

  5. Qt案例:实现显示图片

    效果图: 17.1 组件使用 17.1.1 QDockWidget 含义:停靠区窗口,和状态栏.标题栏是一个等级 属性: allowedAreas:设置允许停靠区域,或者使用代码setAllowedA ...

  6. Android 自定义View 圆形圆角图片

    [Android 自定义View 圆形圆角图片] 基于Xfermode 实现 1.概述 在很久以前也写过一个利用Xfermode 实现圆形.圆角图片的(Android 完美实现图片圆角和圆形(对实现进 ...

  7. Android 圆形/圆角图片的方法

    Android 圆形/圆角图片的方法 眼下网上有非常多圆角图片的实例,Github上也有一些成熟的项目.之前做项目,为了稳定高效都是选用Github上的项目直接用.但这样的结束也是Android开发必 ...

  8. [Android开发]不操作Bitmap实现圆角ImageView、圆形ImageView,支持添加背景圆形或圆角矩形边框、边框支持渐变色

    一.主要解决的使用场景 1.使用Glide加载图片时,我们往往需要设置加载中和加载失败的图片,app中不同的页面的显示的图片可能是圆形,也可能是圆角矩形图,Glide设置placeholder和err ...

  9. pythongui显示图片_opencv2.4.13+python2.7学习笔记--opencv中的Gui特性--图片:读图像,显示图像,保存图像...

    #-*- coding: utf-8 -*- """Created on Tue Mar 14 19:39:11 2017 @author: Thinkpad" ...

最新文章

  1. python类的继承--------类的基础(四)
  2. 创建oracle数据库有哪些方法,oracle11g创建数据库的方法-Oracle
  3. python手机代码识别数字_python实现kNN算法识别手写体数字的示例代码
  4. Java堆和栈的区别
  5. k8s 组件介绍-API Server
  6. springmvc重定向到另一个项目_spring mvc的转发与重定向
  7. 【硬核科技】转行AI,从零出发
  8. eclipse无法运行PHP_eclipse 无法运行php文件怎么办
  9. freebsd mysql utf8_FreeBSD环境下Mysql问题解决方法集锦
  10. VUE下载安装与配置
  11. Web漏洞-Xss跨站
  12. 深圳海关计算机应用岗位进面分数,这是深圳国税和海关的进面分数线,看完你还敢报吗?...
  13. 淘宝新店刚开如何测款?
  14. 影响计算机速度的有哪些配件,影响电脑上网速度的重要因素有哪些?
  15. dw中html文档命名标准,dw中的css是什么意思?
  16. 将私人对话发布到公共空间来寻求正义是否可取
  17. 计算机改显存会有啥影响,显卡显存越大越好吗?显存对电脑速度的影响有哪些?...
  18. RabbitMQ:The channelMax limit is reached. Try later.
  19. excel 求去掉最高分最低分后的平均值
  20. Resource Possword

热门文章

  1. MT940银行对账单怎么解析呢
  2. 斗地主(代码简易版)
  3. 文字绕圆排列:vue
  4. 世界杯电视直播表(及时更新)
  5. python3-xlsx表格文件读取
  6. 一个菜鸡的ACM之路
  7. 如何将整个网页变成灰色
  8. 作业4使用vi编辑器配置网络环境
  9. 如何解除word文档保护的方法
  10. 结构体中元素引用—— “.“ 与 “->“