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

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

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

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

//控件
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
}

   
上面点击"打开"button能实现打开图片,而在讲述为图片加入边框时,它事实上就是通过两张或多张图片的合成实现的.

在jacpy.may《Android图片处理总结》文档中建议图片不要放在drawable文件夹下,由于屏幕分辨率会影响图片的大小.最好放在assets文件夹里,它代表应用无法直接訪问的原生资源(通常载入PNG透明图实现边框合成),仅仅能以流的方式读取而且小于1M.

读取assets文件夹中图片的方法例如以下,首先手动加入PNG图片至assets文件夹,然后在omCreate函数中加入例如以下代码:

//显示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":

//获取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代码例如以下:

<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" >
    <!-- 底部加入按钮 -->
    <RelativeLayout
        android: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" >
			<Button
				 android:id="@+id/button1"
				 android:layout_width="wrap_content"
				 android:layout_height="match_parent"
				 android:layout_weight="1"
				 android:text="打开" />
			<Button
				 android:id="@+id/button2"
				 android:layout_width="wrap_content"
				 android:layout_height="match_parent"
				 android:layout_weight="1"
				 android:text="显示" />
			<Button
				 android:id="@+id/button3"
				 android:layout_width="wrap_content"
				 android:layout_height="match_parent"
				 android:layout_weight="1"
				 android:text="边框" />
			<Button
				 android:id="@+id/button4"
				 android:layout_width="wrap_content"
				 android:layout_height="match_parent"
				 android:layout_weight="1"
				 android:text="桃心" />
			<Button
				 android:id="@+id/button5"
				 android:layout_width="wrap_content"
				 android:layout_height="match_parent"
				 android:layout_weight="1"
				 android:text="圆形" />
	    </LinearLayout>
	</RelativeLayout>
    <!-- 顶部显示图片 -->
    <RelativeLayout
        android: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">
        <ImageView
	        android:id="@+id/imageView1"
	        android:layout_width="fill_parent"
	        android:layout_height="fill_parent"
	        android:layout_gravity="center_horizontal" />
    </RelativeLayout>
</RelativeLayout>

二. 加入相框与图片合成

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

//模式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
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多媒体开发高级编程》,可是它图片十四合成效果不是非常好:

//模式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));
	}
});

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

//图片合成
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:获得每一个位置上两幅图像中最暗的像素并显示.

android.graphics.PorterDuff.Mode.MULTIPLY:将每一个位置的两个像素相乘,除以255,使用该值创建一个新的像素进行显示.结果颜色=顶部颜色*底部颜色/255.

android.graphics.PorterDuff.Mode.SCREEN:反转每一个颜色,运行同样操作.结果颜色=255-(((255-顶部颜色)*(255-底部颜色))/255)

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

   最后讲述怎样实现圆形和圆角矩形显示图片,在onCreate函数中加入例如以下代码:

//圆角合成图片
roundImageBn = (Button)findViewById(R.id.button5);
roundImageBn.setOnClickListener(new OnClickListener() {
	@Override
	public void onClick(View v) {
		imageShow.setImageBitmap(getRoundedCornerBitmap(bmp) );
	}
});

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

//生成圆角图片
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;
}

   相同,假设把该函数里面内容替换就可以实现圆形矩形显示图片:

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^)/~

下载地址:http://download.csdn.net/detail/eastmount/8102845

源代码基本格式例如以下图所看到的:

(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 轻松实如今线即时聊天【图片、语音、表情、文字】 作者-anonymousblogs

时间: 2024-10-29 19:05:40

[Android] 给图像加入相框、圆形圆角显示图片、图像合成知识的相关文章

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

    前一篇文章讲述了Android触屏setOnTouchListener实现突破缩放.移动.绘制和添加水印,继续我的"随手拍"项目完成给图片添加相框.圆形圆角显示图片和图像合成的功能介绍.希望文章对大家有所帮助. 一. 打开图片和显示assets文件中图片 首先,对XML中activity_main.xml进行布局,通过使用RelativeLayout相对布局完成(XML代码后面附).然后,在Mainctivity.java中public class MainActivity e

(转)使用OpenGL显示图像(七)Android OpenGLES2.0——纹理贴图之显示图片

转:http://blog.csdn.net/junzia/article/details/52842816 前面几篇博客,我们将了Android中利用OpenGL ES 2.0绘制各种形体,并在上一篇博客中专门讲了GLSL语言.但是我们看到的基于OpenGL开发的应用和游戏,可不仅仅是那些规则形体和一些简单的色彩构成,而是各种不规则的形体构成了现实世界或者卡通世界的人和事物,他们都是外面穿着漂亮“衣服”的.本篇博客就是来讲解这些“衣服”的基础的.这些衣服就是纹理贴图. 什么是纹理贴图 一般说来

Android L下用XXRadius设置圆角背景图片不能显示

设置控件的background的例子: <Button android:id="@+id/btn1" android:layout_width="100dp" android:layout_height="50dp" android:text="btn1" android:background="@drawable/btn1"/> <?xml version="1.0"

Android自定义ImageView实现图片圆形 ,椭圆和矩形圆角显示

Android中的ImageView只能显示矩形的图片,为了用户体验更多,Android实现圆角矩形,圆形或者椭圆等图形,一般通过自定义ImageView来实现,首先获取到图片的Bitmap,然后通过Paint和onDraw()进行圆形图片显示. 效果图: 代码: 1 activity_image.xml 2 <?xml version="1.0" encoding="utf-8"?> 3 <LinearLayoutxmlns:android=&q

Android 圆形/圆角图片的方法

Android 圆形/圆角图片的方法 目前网上有很多圆角图片的实例,Github上也有一些成熟的项目.之前做项目,为了稳定高效都是选用Github上的项目直接用.但这种结束也是Android开发必备技能 ,所以今天就来简单研究一下该技术,分享给大家. 预备知识: Xfermode介绍: 下面是Android ApiDemo里的"Xfermodes"实例,效果图. Xfermode有三个子类,结构如下: view sourceprint? 1.public class 2.Xfermod

Android dialog圆角显示及解决出现的黑色棱角

最近在开发一个天气预报的app,看到一个比较不错友情提示,如下:                怎么样,看起来比原始的dialog好看吧.好了,做法也许有很多,我介绍下我的做法吧, 首先,我第一个想到的就是重写dialog.自定义一个layout布局,引用shape.xml实现圆角. 在此之前,我要说明一下:在我们新建的布局文件,只要不是最外层我们引用shape就不会遇到下面这个问题,看图:           仔细看就是四个角,发现出现四个黑棱角,这个肯定使我们不想要的结果,我在配置文件中怎么

android dialog圆角显示及解决出现的黑色棱角.(友情提示)

http://blog.csdn.net/jj120522/article/details/7871289 最近在开发一个天气预报的app,看到一个比较不错友情提示,如下:                怎么样,看起来比原始的dialog好看吧.好了,做法也许有很多,我介绍下我的做法吧, 首先,我第一个想到的就是重写dialog.自定义一个layout布局,引用shape.xml实现圆角. 在此之前,我要说明一下:在我们新建的布局文件,只要不是最外层我们引用shape就不会遇到下面这个问题,看图

Android ImageView 图片圆角显示(转载)

转载自:http://www.w2bc.com/Article/3623 android中的ImageView只能显示矩形的图片,这样一来不能满足我们其他的需求,比如要显示圆形的图片,这个时候,我们就需要自定义ImageView了,其原理就是首先获取到图片的Bitmap,然后进行裁剪圆形的bitmap,然后在onDraw()进行绘制圆形图片输出. 自定义的圆形的ImageView类的实现代码如下: package com.rainwii.entity; //包名 import android.c

android 手把手教你绘制圆形头像

自从腾讯QQ中的圆形头像,火了起来后,现在我们在一些应用中都能看到圆形头像的身影,在个人主页或者个人资料面板中使用圆形头像,会使整个布局变得更加优雅 现在我们来进行第一步,创建一个继承ImageView的抽象类MakeRoundImage.让他重写onDraw方法,并且声明一个画笔 import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import androi