Android 图片合成:添加蒙板效果 不规则相框 透明度渐变效果的实现

 

Android 图片合成:添加蒙板效果 不规则相框 透明度渐变效果的实现



暂时还未有时间开发这效果,所以先贴出来。

先贴一张效果图,这是一张手机截屏:


左上方的风景图:背景图片

右上方的人物图:前景图片

左边心型透明图:相框图片

右边心型黑色图:蒙板图片


功能:把前景图应用蒙板,添加相框效果,合成到后景图上面:

结果就是下面的那张图片了。


还有一种是透明度渐变的,效果图如下:

因为只有透明度渐变,没有相框。但实现上基本一样。


下面是实现过程,直接贴代码吧,其中写了比较详细的注释。只有一个文件,如下:

[java]  view plain copy
  1. package com.example.androiddemo;  
  2.   
  3.   
  4. import android.os.Bundle;  
  5. import android.os.Environment;  
  6. import android.app.Activity;  
  7. import android.graphics.Bitmap;  
  8. import android.graphics.BitmapFactory;  
  9. import android.graphics.Canvas;  
  10. import android.util.Log;  
  11. import android.view.View;  
  12. import android.view.View.OnClickListener;  
  13. import android.widget.Button;  
  14. import android.widget.ImageView;  
  15.   
  16. public class MainActivity extends Activity {  
  17.   
  18.     private static final String TAG = "liuzw";  
  19.       
  20.     private ImageView picBGView;  
  21.     private ImageView pictureView;  
  22.     private ImageView maskView;  
  23.     private ImageView frameView;  
  24.     private ImageView resultView;  
  25.     private Button startProcess;  
  26.     private Bitmap picBitmap;  
  27.     private Bitmap maskBitmap;  
  28.     private Bitmap frameBitmap;  
  29.     private Bitmap resultBitmap;  
  30.     private Bitmap fengjingBitmap;  
  31.     private Bitmap composedBitmap;  
  32.       
  33.     private final int WITHOUT = -1;  
  34.     private static final int FRAME = 0;  
  35.     private static final int MASK = 1;  
  36.       
  37. //  private int[] resIds = new int[]{       //斜框锯齿  
  38. //          R.drawable.pip_6_frame,  
  39. //          R.drawable.pip_6_frame_mask,  
  40. //  };  
  41.       
  42. //  private int[] resIds = new int[]{       //胶条  
  43. //          R.drawable.pip_1_frame,  
  44. //          R.drawable.pip_1_frame_mask,  
  45. //  };  
  46.       
  47.     private int[] resIds = new int[]{       //渐变  
  48.             WITHOUT,  
  49.             R.drawable.pip_2_frame_mask,  
  50.     };  
  51.       
  52. //  private int[] resIds = new int[]{       //心形  
  53. //          R.drawable.pip_3_frame,  
  54. //          R.drawable.pip_3_frame_mask,  
  55. //  };  
  56.       
  57.     @Override  
  58.     protected void onCreate(Bundle savedInstanceState) {  
  59.         super.onCreate(savedInstanceState);  
  60.         setContentView(R.layout.activity_main);  
  61.           
  62.         picBGView = (ImageView) findViewById(R.id.pic_bg);  
  63.         picBGView.setImageResource(R.drawable.fengjing);  
  64.         pictureView = (ImageView) findViewById(R.id.pic);  
  65.         pictureView.setImageResource(R.drawable.pip_test);  
  66.         maskView = (ImageView) findViewById(R.id.mask);  
  67.         maskView.setImageResource(resIds[MASK]);  
  68.         frameView = (ImageView) findViewById(R.id.frame);  
  69.         frameView.setImageResource(resIds[FRAME]);  
  70.         startProcess = (Button) findViewById(R.id.btnStart);  
  71.         startProcess.setOnClickListener(mListener);  
  72.         resultView = (ImageView) findViewById(R.id.showResult);  
  73.           
  74.     }  
  75.       
  76.     /** 
  77.      * 获得前置照片 
  78.      */  
  79.     private void getFrontPicture(){  
  80.         //蒙板的Bitmap  
  81.         if(maskBitmap == null || maskBitmap.isRecycled() && resIds[MASK] != WITHOUT){  
  82.             maskBitmap = BitmapFactory.decodeResource(this.getResources(), resIds[MASK]);  
  83.         }  
  84.         if(maskBitmap == nullreturn;  
  85.           
  86.         //前置的原图,并将其缩放到跟蒙板大小一直  
  87.         if(picBitmap == null || picBitmap.isRecycled()){  
  88.             picBitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.pip_test);  
  89.             picBitmap = Bitmap.createScaledBitmap(picBitmap, maskBitmap.getWidth(), maskBitmap.getHeight(), false);  
  90.         }  
  91.           
  92.         //相框的Bitmap  
  93.         if(frameBitmap == null || frameBitmap.isRecycled() && resIds[FRAME] != WITHOUT){  
  94.             frameBitmap = BitmapFactory.decodeResource(this.getResources(), resIds[FRAME]);  
  95.         }  
  96.           
  97.         int w = maskBitmap.getWidth();  
  98.         int h = maskBitmap.getHeight();  
  99.           
  100.         int edgeColor = maskBitmap.getPixel(11);  
  101.         int centerColor = maskBitmap.getPixel(w/2, h/2);  
  102.         Log.d(TAG, "edgeColor = " + Integer.toHexString(edgeColor) + ", centerColor = " + Integer.toHexString(centerColor));  
  103.           
  104.         if(resultBitmap == null){  
  105.             resultBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);  
  106.         }  
  107.           
  108.         //这是背景的风景图  
  109.         if(fengjingBitmap == null){  
  110.             fengjingBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fengjing);  
  111.         }  
  112.           
  113.         //前置相片添加蒙板效果  
  114.         int[] picPixels = new int[w*h];  
  115.         int[] maskPixels = new int[w*h];  
  116.         picBitmap.getPixels(picPixels, 0, w, 00, w, h);  
  117.         maskBitmap.getPixels(maskPixels, 0, w, 00, w, h);  
  118.         for(int i = 0; i < maskPixels.length; i++){  
  119.             if(maskPixels[i] == 0xff000000){  
  120.                 picPixels[i] = 0;  
  121.             }else if(maskPixels[i] == 0){  
  122.                 //donothing  
  123.             }else{  
  124.                 //把mask的a通道应用与picBitmap  
  125.                 maskPixels[i] &= 0xff000000;  
  126.                 maskPixels[i] = 0xff000000 - maskPixels[i];   
  127.                 picPixels[i] &= 0x00ffffff;  
  128.                 picPixels[i] |= maskPixels[i];  
  129.             }  
  130.         }  
  131.           
  132.         //生成前置图片添加蒙板后的bitmap:resultBitmap  
  133.         resultBitmap.setPixels(picPixels, 0, w, 00, w, h);  
  134.     }  
  135.       
  136.     /** 
  137.      * 图片合成 
  138.      */  
  139.     private void compose(){  
  140.         if(fengjingBitmap == null || fengjingBitmap.isRecycled()){  
  141.             Log.e(TAG, "compose ERROR: fengjingBitmap is not valuable");  
  142.             return;  
  143.         }  
  144.         composedBitmap = Bitmap.createBitmap(fengjingBitmap.getWidth(), fengjingBitmap.getHeight(), Bitmap.Config.ARGB_8888);  
  145.         if(composedBitmap == null || composedBitmap.isRecycled()){  
  146.             Log.e(TAG, "compose ERROR: composedBitmap is not valuable");  
  147.             return;  
  148.         }  
  149.         if(resultBitmap == null || resultBitmap.isRecycled()){  
  150.             Log.e(TAG, "compose ERROR: resultBitmap is not valuable");  
  151.             return;  
  152.         }  
  153.         Canvas cv = new Canvas(composedBitmap);  
  154.         cv.drawBitmap(fengjingBitmap, 00null);  
  155.         cv.drawBitmap(resultBitmap, 100100null);  
  156.           
  157.         if(frameBitmap != null && !frameBitmap.isRecycled()){  
  158.             cv.drawBitmap(frameBitmap, 100100null);  
  159.         }  
  160.           
  161.         cv.save(Canvas.ALL_SAVE_FLAG);  
  162.         cv.restore();  
  163.         resultView.setImageBitmap(composedBitmap);  
  164.     }  
  165.       
  166.     @Override  
  167.     protected void onDestroy() {  
  168.         // TODO Auto-generated method stub  
  169.         super.onDestroy();  
  170.         //释放资源  
  171.         resultView.setImageBitmap(null);  
  172.         if(picBitmap != null && !picBitmap.isRecycled()){  
  173.             picBitmap.recycle();  
  174.             picBitmap = null;  
  175.         }  
  176.         if(maskBitmap != null && !maskBitmap.isRecycled()){  
  177.             maskBitmap.recycle();  
  178.             maskBitmap = null;  
  179.         }  
  180.         if(frameBitmap != null && !frameBitmap.isRecycled()){  
  181.             frameBitmap.recycle();  
  182.             frameBitmap = null;  
  183.         }  
  184.         if(resultBitmap != null && !resultBitmap.isRecycled()){  
  185.             resultBitmap.recycle();  
  186.             resultBitmap = null;  
  187.         }  
  188.         if(fengjingBitmap != null && !fengjingBitmap.isRecycled()){  
  189.             fengjingBitmap.recycle();  
  190.             fengjingBitmap = null;  
  191.         }  
  192.         if(composedBitmap != null && !composedBitmap.isRecycled()){  
  193.             composedBitmap.recycle();  
  194.             composedBitmap = null;  
  195.         }  
  196.     }  
  197.       
  198.     private OnClickListener mListener = new OnClickListener(){  
  199.   
  200.         @Override  
  201.         public void onClick(View v) {  
  202.             // TODO Auto-generated method stub  
  203.             switch(v.getId()){  
  204.             case R.id.btnStart:  
  205.                 getFrontPicture();  
  206.                 compose();  
  207.                 break;  
  208.             }  
  209.         }  
  210.           
  211.     };  
  212.       
  213. }  

为了完整和方便参考,把布局文件也贴一下,如下:

[html]  view plain copy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="#ffffffff"  
  6.     tools:context=".MainActivity" >  
  7.   
  8.     <LinearLayout   
  9.         android:id="@+id/views1"  
  10.         android:layout_width="match_parent"  
  11.         android:layout_height="150dip"  
  12.         android:orientation="horizontal" >  
  13.           
  14.          <ImageView   
  15.             android:id="@+id/pic_bg"  
  16.             android:layout_width="wrap_content"  
  17.             android:layout_height="wrap_content"  
  18.             android:layout_weight="1.0" />  
  19.            
  20.         <ImageView   
  21.             android:id="@+id/pic"  
  22.             android:layout_width="wrap_content"  
  23.             android:layout_height="wrap_content"  
  24.             android:layout_weight="1.0" />  
  25.     </LinearLayout>  
  26.       
  27.     <LinearLayout   
  28.         android:id="@+id/views2"  
  29.         android:layout_below="@+id/views1"  
  30.         android:layout_width="match_parent"  
  31.         android:layout_height="150dip"  
  32.         android:orientation="horizontal" >  
  33.           
  34.           
  35.         <ImageView   
  36.             android:id="@+id/frame"  
  37.             android:layout_width="wrap_content"  
  38.             android:layout_height="wrap_content"  
  39.             android:layout_weight="1.0" />  
  40.           
  41.         <ImageView   
  42.             android:id="@+id/mask"  
  43.             android:layout_width="wrap_content"  
  44.             android:layout_height="wrap_content"  
  45.             android:layout_weight="1.0" />  
  46.           
  47.     </LinearLayout>  
  48.   
  49.     <Button   
  50.         android:id="@+id/btnStart"  
  51.         android:layout_below="@+id/views2"  
  52.         android:layout_width="wrap_content"  
  53.         android:layout_height="wrap_content"  
  54.         android:text="Start" />  
  55.       
  56.     <ImageView   
  57.         android:id="@+id/showResult"  
  58.         android:layout_below="@+id/btnStart"  
  59.         android:layout_width="wrap_content"  
  60.         android:layout_height="wrap_content"/>  
  61.       
  62. </RelativeLayout>  



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值