[Android] 给图像添加相框、圆形圆角显示图片、图像合成知识
? ? 前一篇文章講述了Android觸屏setOnTouchListener實現(xiàn)突破縮放、移動、繪制和添加水印,繼續(xù)我的"隨手拍"項目完成給圖片添加相框、圓形圓角顯示圖片和圖像合成的功能介紹.希望文章對大家有所幫助.
一. 打開圖片和顯示assets文件中圖片
? ? 首先,對XML中activity_main.xml進行布局,通過使用RelativeLayout相對布局完成(XML代碼后面附).然后,在Mainctivity.java中public class MainActivity extends Activity函數(shù)添加代碼如下,添加點擊按鈕監(jiān)聽事件:
//控件 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() {@Overridepublic 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 { //載入圖片尺寸大小沒載入圖片本身 trueBitmapFactory.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; } } //圖像真正解碼 falsebmpFactoryOptions.inJustDecodeBounds = false; bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageFileUri), null, bmpFactoryOptions); imageShow.setImageBitmap(bmp);}catch(FileNotFoundException e) { e.printStackTrace(); } } //end if }
? ? 上面點擊"打開"按鈕能實現(xiàn)打開圖片,而在講述為圖片添加邊框時,它其實就是通過兩張或多張圖片的合成實現(xiàn)的.
? ? 在jacpy.may《Android圖片處理總結(jié)》文檔中建議圖片不要放在drawable目錄下,因為屏幕分辨率會影響圖片的大小.最好放在assets目錄里,它代表應(yīng)用無法直接訪問的原生資源(通常加載PNG透明圖實現(xiàn)邊框合成),只能以流的方式讀取并且小于1M.
? ? 讀取assets文件夾中圖片的方法如下,首先手動添加PNG圖片至assets目錄,然后在omCreate函數(shù)中添加如下代碼:
//顯示assets中圖片 showImageBn = (Button)findViewById(R.id.button2); showImageBn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) { Bitmap bitmap = getImageFromAssets("image01.png");imageShow.setImageBitmap(bitmap); } }); ? ?再通過自定義函數(shù)getImageFromAssets實現(xiàn)獲取圖片"image01.png":
//獲取assets中資源并轉(zhuǎn)換為Bitmap private Bitmap getImageFromAssets(String fileName) {//Android中使用assets目錄存放資源,它代表應(yīng)用無法直接訪問的原生資源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代碼如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/container"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.example.touchimagetest.MainActivity"tools:ignore="MergeRootFrame" ><!-- 底部添加按鈕 --><RelativeLayoutandroid:id="@+id/MyLayout_bottom"android:orientation="horizontal" android:layout_width="fill_parent"android:layout_height="50dp"android:layout_alignParentBottom="true"android:gravity="center"><LinearLayout android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"android:layout_alignParentBottom="true" ><Buttonandroid:id="@+id/button1"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_weight="1"android:text="打開" /><Buttonandroid:id="@+id/button2"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_weight="1"android:text="顯示" /><Buttonandroid:id="@+id/button3"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_weight="1"android:text="邊框" /><Buttonandroid:id="@+id/button4"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_weight="1"android:text="桃心" /><Buttonandroid:id="@+id/button5"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_weight="1"android:text="圓形" /></LinearLayout></RelativeLayout><!-- 頂部顯示圖片 --><RelativeLayoutandroid:id="@+id/Content_Layout" android:orientation="horizontal"android:layout_above="@id/MyLayout_bottom"android:layout_width="fill_parent" android:layout_height="wrap_content"android:layout_alignParentTop="true"android:background="#000000"android:gravity="center"><ImageViewandroid:id="@+id/imageView1"android:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_gravity="center_horizontal" /></RelativeLayout> </RelativeLayout>
二. 添加相框與圖片合成
? ? 然后開始完成圖片合成的工作,這里我采用兩種方法完成.繼續(xù)在onCreate函數(shù)中添加代碼: //模式1合成圖片 showImageBn1 = (Button)findViewById(R.id.button3); showImageBn1.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Bitmap bitmap = getImageFromAssets("image01.png");addFrameToImage(bitmap);} });? ?通過自定義函數(shù)addFrameToImage實現(xiàn)加載圖片合成.首先創(chuàng)建一個空的可變?yōu)閳D對象,它的大小和配置與打開的圖像相同,隨后構(gòu)建一個Canvas對象和一個Paint對象,在畫布上繪制第一個位圖對象,它成為了合成操作的目標.? ? 現(xiàn)在設(shè)置Paint對象上的過渡模式,通過傳入一個定義操作模式的常量,實例化一個新的PorterDuffXfermode對象.然后在Canvas對象上繪制第二個位圖對象,并將ImageView設(shè)置為新的位圖對象.代碼如下: //圖片合成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多媒體開發(fā)高級編程》,但是它圖片十四合成效果不是很好: //模式2合成圖片 showImageBn2 = (Button)findViewById(R.id.button4); showImageBn2.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Bitmap bitmap = getImageFromAssets("image07.png");//第二種合成方法imageShow.setImageBitmap(addFrameToImageTwo(bitmap));} });? ? 然后通過自定義函數(shù)實現(xiàn): //圖片合成 private Bitmap addFrameToImageTwo(Bitmap frameBitmap) //bmp原圖 frameBitmap資源圖片(邊框) {//bmp原圖 創(chuàng)建新位圖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附圖是方法一,但是它的合成效果不是很優(yōu)秀,而第三張圖是第二種方法,但是它的響應(yīng)時間稍微要長些.
? ? ??? ? ?? ? ?在第一種方法通過PoterDuffXfermode類作為過渡模式,該類因Thomas Porter和Tom Duff而得名,他們于1984年在ACM SIGGRAPH計算機圖形學(xué)發(fā)表“Compositing digital images(合成數(shù)字圖像)”的文章,它介紹了彼此重疊繪制圖像的不同規(guī)則.這些規(guī)則定義了哪些圖像的哪些部分將出現(xiàn)在結(jié)果輸出中.
? ? 在Android的PorterDuff.Mode類中列舉了Porter和Duff及其他更多人制定的規(guī)則.
? ? android.graphics.PorterDuff.Mode.SRC:此規(guī)則意味著只繪制源圖像,當(dāng)前它正是應(yīng)用此規(guī)則的Paint對象.
? ? android.graphics.PorterDuff.Mode.DST:此規(guī)則意味著只顯示目標圖像,在已有畫布上的初始圖像.
? ? 如下圖所示,定義Mode值如下:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? 其中,有4個規(guī)則定義了當(dāng)一幅圖像放置在另一幅圖像上時如何合成這兩幅圖像,它是我們經(jīng)常使用的值:
? ? android.graphics.PorterDuff.Mode.LIGHTEN:獲得每個位置上兩幅圖像中最亮的像素并顯示.
? ? android.graphics.PorterDuff.Mode.DARKEN:獲得每個位置上兩幅圖像中最暗的像素并顯示.
? ? android.graphics.PorterDuff.Mode.MULTIPLY:將每個位置的兩個像素相乘,除以255,使用該值創(chuàng)建一個新的像素進行顯示.結(jié)果顏色=頂部顏色*底部顏色/255.
? ? android.graphics.PorterDuff.Mode.SCREEN:反轉(zhuǎn)每個顏色,執(zhí)行相同操作.結(jié)果顏色=255-(((255-頂部顏色)*(255-底部顏色))/255)
三. 圓形和圓角矩形顯示圖片
? ?最后講述如何實現(xiàn)圓形和圓角矩形顯示圖片,在onCreate函數(shù)中添加如下代碼://圓角合成圖片 roundImageBn = (Button)findViewById(R.id.button5); roundImageBn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {imageShow.setImageBitmap(getRoundedCornerBitmap(bmp) );} });???然后通過自定義函數(shù)getRoundedCornerBitmap實現(xiàn)圓形: //生成圓角圖片 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(); //設(shè)置圓形半徑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; }? ?同樣,如果把該函數(shù)里面內(nèi)容替換即可實現(xiàn)圓形矩形顯示圖片: 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; //轉(zhuǎn)角設(shè)置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); }? ?運行結(jié)果如下圖所示:
? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ?? ? ? 總結(jié):
? ? 該文章主要講述如何給圖像增加相框,圓角顯示圖像和圖像合成的介紹.里面主要通過源碼并有詳細的過程,為什么要寫這篇文章?因為在圖像處理中我認為這種添加邊框、改變邊框、圖片合成都屬于同一種類型的變化和渲染.該圖像處理軟件還沒有整合,推薦大家看下面資料中兩本書.
??? 最后希望文章對大家有所幫助,如果有不足或錯誤的地方請見諒!不論如何,我覺得這篇文章自己寫得不錯,自己先給自己一個贊吧!加油\(^o^)/~
??? 下載地址:http://download.csdn.net/detail/eastmount/8102845
??? 源碼基本格式如下圖所示:
(By:Eastmount 2014-10-31 夜3點?http://blog.csdn.net/eastmount)
參考資料與推薦博文: 1.最該感謝的是兩本書的作者《Android多媒體開發(fā)高級編程》和《Android圖片處理總結(jié) 著:jacpy.may》,網(wǎng)上很多資料都是它們.
2.android圖像處理系列之六--給圖片添加邊框(下)-圖片疊加?
作者-SJF0115 他是轉(zhuǎn)載了該書的一些文章,也非常不錯.
3.Android 圖片合成:添加蒙板效果 不規(guī)則相框 透明度漸變效果的實現(xiàn)
作者-HappyDelano 非常不錯的文章,講述了4張圖實現(xiàn)桃心顯示的效果.
4.Android圖片合成?作者-johnlxj 講述了圖片合成的實現(xiàn)過程.
5.Android 完美實現(xiàn)圖片圓角和圓形(對實現(xiàn)進行分析)
作者-鴻洋_ 該作者很多android文章都非常不錯
6.android 畫圖之setXfermode?作者-lipeng88213 推薦起鏈接的Android圖片倒影
7.Android ImageView點擊選中后添加邊框?作者-黑米粥 該方法在切換圖片中實用
8.android 輕松實現(xiàn)在線即時聊天【圖片、語音、表情、文字】?作者-anonymousblogs
總結(jié)
以上是生活随笔為你收集整理的[Android] 给图像添加相框、圆形圆角显示图片、图像合成知识的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Android] 触屏setOnTou
- 下一篇: [Android] 通过Menu实现图片