1. 程式人生 > >Android 圖片合成:新增蒙板效果 不規則相框 透明度漸變效果的實現

Android 圖片合成:新增蒙板效果 不規則相框 透明度漸變效果的實現

先貼一張效果圖,這是一張手機截圖:

左上方的風景圖:背景圖片

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

左邊心型透明圖:相框圖片

右邊心型黑色圖:蒙板圖片

功能:把前景圖應用蒙板,新增相框效果,合成到後景圖上面:

結果就是下面的那張圖片了。

還有一種是透明度漸變的,效果圖如下:

因為只有透明度漸變,沒有相框。但實現上基本一樣。

下面是實現過程,直接貼程式碼吧,其中寫了比較詳細的註釋。只有一個檔案,如下:

package com.example.androiddemo;


import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity {

	private static final String TAG = "liuzw";
	
	private ImageView picBGView;
	private ImageView pictureView;
	private ImageView maskView;
	private ImageView frameView;
	private ImageView resultView;
	private Button startProcess;
	private Bitmap picBitmap;
	private Bitmap maskBitmap;
	private Bitmap frameBitmap;
	private Bitmap resultBitmap;
	private Bitmap fengjingBitmap;
	private Bitmap composedBitmap;
	
	private final int WITHOUT = -1;
	private static final int FRAME = 0;
	private static final int MASK = 1;
	
//	private int[] resIds = new int[]{		//斜框鋸齒
//			R.drawable.pip_6_frame,
//			R.drawable.pip_6_frame_mask,
//	};
	
//	private int[] resIds = new int[]{		//膠條
//			R.drawable.pip_1_frame,
//			R.drawable.pip_1_frame_mask,
//	};
	
	private int[] resIds = new int[]{		//漸變
			WITHOUT,
			R.drawable.pip_2_frame_mask,
	};
	
//	private int[] resIds = new int[]{		//心形
//			R.drawable.pip_3_frame,
//			R.drawable.pip_3_frame_mask,
//	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		picBGView = (ImageView) findViewById(R.id.pic_bg);
		picBGView.setImageResource(R.drawable.fengjing);
		pictureView = (ImageView) findViewById(R.id.pic);
		pictureView.setImageResource(R.drawable.pip_test);
		maskView = (ImageView) findViewById(R.id.mask);
		maskView.setImageResource(resIds[MASK]);
		frameView = (ImageView) findViewById(R.id.frame);
		frameView.setImageResource(resIds[FRAME]);
		startProcess = (Button) findViewById(R.id.btnStart);
		startProcess.setOnClickListener(mListener);
		resultView = (ImageView) findViewById(R.id.showResult);
		
	}
	
	/**
	 * 獲得前置照片
	 */
	private void getFrontPicture(){
		//蒙板的Bitmap
		if(maskBitmap == null || maskBitmap.isRecycled() && resIds[MASK] != WITHOUT){
			maskBitmap = BitmapFactory.decodeResource(this.getResources(), resIds[MASK]);
		}
		if(maskBitmap == null) return;
		
		//前置的原圖,並將其縮放到跟蒙板大小一直
		if(picBitmap == null || picBitmap.isRecycled()){
			picBitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.pip_test);
			picBitmap = Bitmap.createScaledBitmap(picBitmap, maskBitmap.getWidth(), maskBitmap.getHeight(), false);
		}
		
		//相框的Bitmap
		if(frameBitmap == null || frameBitmap.isRecycled() && resIds[FRAME] != WITHOUT){
			frameBitmap = BitmapFactory.decodeResource(this.getResources(), resIds[FRAME]);
		}
		
		int w = maskBitmap.getWidth();
		int h = maskBitmap.getHeight();
		
		int edgeColor = maskBitmap.getPixel(1, 1);
		int centerColor = maskBitmap.getPixel(w/2, h/2);
		Log.d(TAG, "edgeColor = " + Integer.toHexString(edgeColor) + ", centerColor = " + Integer.toHexString(centerColor));
		
		if(resultBitmap == null){
			resultBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
		}
		
		//這是背景的風景圖
		if(fengjingBitmap == null){
			fengjingBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fengjing);
		}
		
		//前置相片新增蒙板效果
		int[] picPixels = new int[w*h];
		int[] maskPixels = new int[w*h];
		picBitmap.getPixels(picPixels, 0, w, 0, 0, w, h);
		maskBitmap.getPixels(maskPixels, 0, w, 0, 0, w, h);
		for(int i = 0; i < maskPixels.length; i++){
			if(maskPixels[i] == 0xff000000){
				picPixels[i] = 0;
			}else if(maskPixels[i] == 0){
				//donothing
			}else{
				//把mask的a通道應用與picBitmap
				maskPixels[i] &= 0xff000000;
				maskPixels[i] = 0xff000000 - maskPixels[i];	
				picPixels[i] &= 0x00ffffff;
				picPixels[i] |= maskPixels[i];
			}
		}
		
		//生成前置圖片新增蒙板後的bitmap:resultBitmap
		resultBitmap.setPixels(picPixels, 0, w, 0, 0, w, h);
	}
	
	/**
	 * 圖片合成
	 */
	private void compose(){
		if(fengjingBitmap == null || fengjingBitmap.isRecycled()){
			Log.e(TAG, "compose ERROR: fengjingBitmap is not valuable");
			return;
		}
		composedBitmap = Bitmap.createBitmap(fengjingBitmap.getWidth(), fengjingBitmap.getHeight(), Bitmap.Config.ARGB_8888);
		if(composedBitmap == null || composedBitmap.isRecycled()){
			Log.e(TAG, "compose ERROR: composedBitmap is not valuable");
			return;
		}
		if(resultBitmap == null || resultBitmap.isRecycled()){
			Log.e(TAG, "compose ERROR: resultBitmap is not valuable");
			return;
		}
		Canvas cv = new Canvas(composedBitmap);
		cv.drawBitmap(fengjingBitmap, 0, 0, null);
		cv.drawBitmap(resultBitmap, 100, 100, null);
		
		if(frameBitmap != null && !frameBitmap.isRecycled()){
			cv.drawBitmap(frameBitmap, 100, 100, null);
		}
		
		cv.save(Canvas.ALL_SAVE_FLAG);
		cv.restore();
		resultView.setImageBitmap(composedBitmap);
	}
	
	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		//釋放資源
		resultView.setImageBitmap(null);
		if(picBitmap != null && !picBitmap.isRecycled()){
			picBitmap.recycle();
			picBitmap = null;
		}
		if(maskBitmap != null && !maskBitmap.isRecycled()){
			maskBitmap.recycle();
			maskBitmap = null;
		}
		if(frameBitmap != null && !frameBitmap.isRecycled()){
			frameBitmap.recycle();
			frameBitmap = null;
		}
		if(resultBitmap != null && !resultBitmap.isRecycled()){
			resultBitmap.recycle();
			resultBitmap = null;
		}
		if(fengjingBitmap != null && !fengjingBitmap.isRecycled()){
			fengjingBitmap.recycle();
			fengjingBitmap = null;
		}
		if(composedBitmap != null && !composedBitmap.isRecycled()){
			composedBitmap.recycle();
			composedBitmap = null;
		}
	}
	
	private OnClickListener mListener = new OnClickListener(){

		@Override
		public void onClick(View v) {
			// TODO Auto-generated method stub
			switch(v.getId()){
			case R.id.btnStart:
				getFrontPicture();
				compose();
				break;
			}
		}
		
	};
	
}

為了完整和方便參考,把佈局檔案也貼一下,如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffffff"
    tools:context=".MainActivity" >

    <LinearLayout 
        android:id="@+id/views1"
        android:layout_width="match_parent"
        android:layout_height="150dip"
        android:orientation="horizontal" >
        
         <ImageView 
            android:id="@+id/pic_bg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1.0" />
         
        <ImageView 
            android:id="@+id/pic"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1.0" />
    </LinearLayout>
    
    <LinearLayout 
        android:id="@+id/views2"
        android:layout_below="@+id/views1"
        android:layout_width="match_parent"
        android:layout_height="150dip"
        android:orientation="horizontal" >
        
        
        <ImageView 
            android:id="@+id/frame"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1.0" />
        
        <ImageView 
            android:id="@+id/mask"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1.0" />
        
    </LinearLayout>

    <Button 
        android:id="@+id/btnStart"
        android:layout_below="@+id/views2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start" />
    
    <ImageView 
        android:id="@+id/showResult"
        android:layout_below="@+id/btnStart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    
</RelativeLayout>



相關推薦

Android 圖片合成新增效果 不規則 透明度漸變效果實現

先貼一張效果圖,這是一張手機截圖: 左上方的風景圖:背景圖片 右上方的人物圖:前景圖片 左邊心型透明圖:相框圖片 右邊心型黑色圖:蒙板圖片 功能:把前景圖應用蒙板,新增相框效果,合成到後景圖上面: 結果就是下面的那張圖片了。 還有一種是透明度漸變的,效果圖如下:

Android Studio增加/浮層特效

寫在前面的話:每一個例項的程式碼都會附上相應的程式碼片或者圖片,保證程式碼完整展示在部落格中。最重要的是保證例程的完整性!!!方便自己也方便他人~歡迎大家交流討論~ 接下來要在自定義相機上新增取景框,即中間掏空旁邊半透明的浮層/蒙板。我一開始搜尋的是“蒙板”,

為網頁新增效果和彈出層js

   有的時候我們需要實現彈出一個層然後下面的層被一層蒙板蒙起來使使用者不能點選裡面的按鈕效果,這一效果具體實現的程式碼如下:這是一個測試效果用的html,可以直接拷貝到html檔案中執行。 <html> <head> <!DOCTYPE ht

Android系統編譯新增OpenCV庫和模型配置檔案

一、新增 libopencv_java3.so庫至/system/lib64/ 在Android原始碼目錄的hardware/libgesture/目錄下建立libopencvhw資料夾,並將libo

Android圖片壓縮按等比例壓縮並且質量壓縮

/** * 圖片按比例大小壓縮方法 * * @param srcPath (根據路徑獲取圖片並壓縮) * @return */ public static File getimage(String src

android 怎麼給listview新增一個固定表頭以及顯示像table的效果

定義一個樣式一條線     <style name="vertical_layout">         <item name="android:layout_width">1dp</item>         <item name

Android 繪圖基礎Bitmap(點陣圖)與Matrix(矩陣)實現圖片5種操作(平移、旋轉、錯切、縮放、對稱)

Android的Matrix利用數學原理實現圖片平移、旋轉等操作詳解   很慶幸自己的線性代數學的還可以,理解Matrix的矩陣變換完全沒有問題。Matrix矩陣實現圖片的平移旋轉等操作涉及到線性代數問題,感興趣它的具體實現的話可以參考一下上面的部落格,非常詳

android 圖片剪下在小米手機上為方形在華為上為圓形解決辦法

在android呼叫系統方法對圖片進行裁剪時,華為手機顯示的圖形會變成圓形,將aspectX和aspectY的值改為不是1;1就好了 if (android.os.Build.MODEL.contai

Android熱修復Andfix和Hotfix,兩種方案的比較與實現

Andfix和hotfix是兩種android熱修復框架。 android的熱修復技術我看的最早的應該是QQ空間團隊的解決方案,後來真正需要了,才仔細調查,現在的方案中,阿里有兩種Dexposed和Andfix框架,由於前一種不支援5.0以上android系統

簡單的程式碼實現上滑導航欄顏色和透明度漸變效果

在開發中經常會給控制器的導航控制器隱藏起來,達到全視窗展示效果但是檢視在上滑過程中又要導航欄顯示出來,而且顯示出來的是透明度漸變效果,這個其實實現起來並不複雜,首先在導航控制器位置新增一個顏色為透明色的背景檢視,在背景檢視上新增某種顏色的子檢視,子檢視的alph

利用canvas製作圖片(可縮放和平移)++文字

前言:   公司一個售前問我能不能用H5做一個手機拍照,給相片新增相框和新增文字上傳到伺服器的功能,我當時一琢磨覺得可行,就利用空餘時間做了一個demo,去掉了拍照和上傳,如果以後有機會,會給補上,當然對於開發過webApp的朋友來做到這個很簡單。下面來看程式碼 1,思路  首先我們需要準備

iOS開發實現導航欄透明度漸變效果

最近做專案實現新的需求,初始狀態導航欄透明,隨著滑動的過程中,改變導航欄的透明度,逐漸顏色加深。 網上找到了兩種解決方案。 第一種,通過研究導航欄的結構圖,找出影響背景顏色的控制元件,對其進行控制改變。 NavigationBar背後有一張型別_

Android效果實現

Layout結構: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:orientatio

Android圖片新增陰影效果的兩種方式

給圖片新增陰影效果,這是很常見的需求。第一種方法是自定義drawable,使用layer-list定義兩個圖片,程式碼如下: show_view.xml: <?xml version="1.0" encoding="utf-8"?> <

Android小例子使用反射機制來讀取圖片制作一個圖片瀏覽器

onclick lac protected blank pri tar lec 存儲 current 效果圖:                                 工程文件夾:   該例子可供於新手參考練習,如果有哪裏不對的地方,望指正>-< 《

Android項目實戰(四)ViewPager切換動畫(3.0版本以上有效果

技術 code info utf-8 play draw pos support addview 原文:Android項目實戰(四):ViewPager切換動畫(3.0版本以上有效果)學習內容來自“慕課網” 一般APP進去之後都會有幾張圖片來導航,

jquery實現圖片無縫滾動,版遮蔽效果

1、無縫連線:通過對li設定屬性float:left;消除標籤之間的間隔 2、通過對ul整體進行偏移設定,使圖片整體滾動, 3、設定圖片切換時機, 4、蒙版遮罩移入時機的選擇 程式碼片. <!DOCTYPE html> <html> <head>

Android 新手引導半透明效果實現

效果圖: 其中的文字和我知道啦是ui切得兩張透明圖片 自定義View: package com.cymobi.library.view.widget; import android.app.Activity; import android.content.Conte

HTML載入中效果...

<!DOCTYPE html> <html lang="zh-CN"> <head>     <meta charset="GBK">     <title>蒙板</title&

android圖片特效處理之光暈效果

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!