zoukankan      html  css  js  c++  java
  • Android 图片合成:添加蒙板效果 不规则相框 透明度渐变效果的实现

     

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



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

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


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

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

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

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


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

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


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

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


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

    [java] view plaincopy
    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 plaincopy
    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>  



  • 相关阅读:
    GitHub统计
    不错的第三方控件
    仿射变换(CGAffineTransform)使用小结
    AffineTransform(仿射变换)
    使用CAShapeLayer实现复杂的View的遮罩效果
    使用CAShapeLayer实现一个音量大小动态改变的控件
    window10 Docker仓库访问
    postgresql从timestamp(6)复制到timestamp(0),时间会变
    在编译Dll文件的时候遇到dll 链接不一致的问题
    qtquery 取列的值
  • 原文地址:https://www.cnblogs.com/new0801/p/6175810.html
Copyright © 2011-2022 走看看