`

(转)Android多媒体学习四:实现图像的编辑和合成

 
阅读更多
import java.io.FileNotFoundException;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
/**
 * 在Android中我们可以对图像进行编辑处理等操作
 * 包括放大缩小,旋转,偏移,裁剪,以及更改亮度,饱和度等
 * 
 * 1、首先,从SDCard中选择图片,采用Android自带的Callery应用获得
 * Gallery是Android自带的图片和视频管理应用
 * 使用Intent来启动Gallery应用,需要指定两个参数,一个是Action,另一个是多媒体存放的URI
 * Action是一个通用的Action叫ACTION_PICK,来告诉Gallery,我们想检索数据。
 * 第二个是Data,是一个URI,这里当然是MediaStore.Images.Media.EXTERNAL_CONTENT_URI
 * 当在Gallery中选择了一个图片的时候,返回的Intent中的Data域就是所选图片对应的URI
 * 
 * @author Administrator
 *
 */
public class PhotoProcess extends Activity{
	public static final int FIRST_PIC = 0;
	public static final int SECOND_PIC = 1;
	public static final int MAX_WIDTH = 240;
	public static final int MAX_HEIGHT = 180;
	private Button btnSelect,btnSelect2;
	private ImageView srcImageView, dstImageView;
	
	private Bitmap srcBitmap, dstBitmap;
	private Uri imageUri;
	
	
	public void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		this.setContentView(R.layout.process);
		
		this.btnSelect = (Button)this.findViewById(R.id.btn_select);
		btnSelect.setOnClickListener(clickListener);
		this.btnSelect2 = (Button)this.findViewById(R.id.btn_select2);
		btnSelect2.setOnClickListener(clickListener2);
		srcImageView = (ImageView)this.findViewById(R.id.img_src);
		dstImageView = (ImageView)this.findViewById(R.id.img_dst);
	}
	
	private View.OnClickListener clickListener = new View.OnClickListener() {
		
		@Override
		public void onClick(View arg0) {
			// 启动Gallery应用
			Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
			startActivityForResult(intent, FIRST_PIC);
		}
	};
	private View.OnClickListener clickListener2 = new View.OnClickListener() {
		
		@Override
		public void onClick(View arg0) {
			// 启动Gallery应用
			Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
			startActivityForResult(intent, SECOND_PIC);
			
		}
	};	
	
	public boolean onCreateOptionsMenu(Menu menu){
		//super.onCreateOptionsMenu(menu);
		//MenuInflater menuInflater = new MenuInflater(this);
		//menuInflater.inflate(R.layout.image, menu)
		menu.add(Menu.NONE,1,Menu.NONE,"复制");
		menu.add(Menu.NONE,2,Menu.NONE,"变换");
		menu.add(Menu.NONE,3,Menu.NONE,"亮度");
		menu.add(Menu.NONE,4,Menu.NONE,"合成");
		return super.onCreateOptionsMenu(menu);
	}
	
	public boolean onOptionsItemSelected(MenuItem item){
		int id = item.getItemId();
		switch(id){
		case 1:
			//复制一个图像
			if(srcBitmap != null){
				dstBitmap = getDstImage(null);//这里没有变换
				dstImageView.setImageBitmap(dstBitmap);
			}
			break;
		case 2:
			//对复制后的图像进行变换
			if(srcBitmap != null){
				dstBitmap = transferImage();
				dstImageView.setImageBitmap(dstBitmap);
			}
			break;
		case 3:
			//改变图像的色彩
			if(srcBitmap != null){
				dstBitmap = ajustImage();
				dstImageView.setImageBitmap(dstBitmap);
			}
			break;
		case 4:
			if(srcBitmap != null && dstBitmap != null){
				dstBitmap = compositeImages();
				dstImageView.setImageBitmap(dstBitmap);
			}
			break;
		}
		return true;
	}
	
	/**
	 * 为了创建一个图像的副本,我们可以在创建一个新的空的Bitmap,然后在这个Bitmap上绘制一个Bitmap
	 * 这个空的Bitmap应该和已存在的Bitmap具有相同的尺寸和颜色深度
	 * 
	 * 然后我们需要一个Canvas对象,一个Canvas简单说,就是一个画布,存放Bitmap,在构造时,就可以传入Bitmap对象
	 * 同时,Canvas中定义了很多便捷的画图方法,方便我们绘制各种图形
	 * 接下来,如果我们需要处理颜色和对比度,我们需要一个Paint对象,通过Paint我们可以设置画笔的各种特性。
	 * 
	 * 最后,我们调用Canvas的drawBitmap就可以将原Bitmap绘制在dstBitmap上了
	 * 
	 */
	private Bitmap getDstImage(Matrix matrix){
		
		Bitmap bmp = null;
		//下面这个Bitmap中创建的函数就可以创建一个空的Bitmap
		//返回的是一个可以改变的Bitmap对象,这样我们后面就可以对其进行变换和颜色调整等操作了
		bmp = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
		//创建Canvas对象,
		Canvas canvas = new Canvas(bmp); 
		//创建Paint对象,这里先不用
		Paint paint = new Paint();
		//在Canvas上绘制一个已经存在的Bitmap。这样,dstBitmap就和srcBitmap一摸一样了
		
		if(matrix != null){
			//如果matrix存在,则采用变换
			canvas.drawBitmap(dstBitmap, matrix, paint);
		}else{
			canvas.drawBitmap(srcBitmap, 0, 0, paint);
		}
		
		
		return bmp;

	}
	
	
	/**
	 * 重载getDstImage函数,传入定制的Paint对象
	 * @param matrix
	 * @param paint
	 * @return
	 */
	private Bitmap getDstImage(Matrix matrix, Paint paint){
		
		Bitmap bmp = null;
		//下面这个Bitmap中创建的函数就可以创建一个空的Bitmap
		//返回的是一个可以改变的Bitmap对象,这样我们后面就可以对其进行变换和颜色调整等操作了
		bmp = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
		//创建Canvas对象,
		Canvas canvas = new Canvas(bmp); 
		
		//在Canvas上绘制一个已经存在的Bitmap。这样,dstBitmap就和srcBitmap一摸一样了
		
		if(matrix != null){
			//如果matrix存在,则采用变换
			canvas.drawBitmap(dstBitmap, matrix, paint);
		}else{
			canvas.drawBitmap(srcBitmap, 0, 0, paint);
		}
		
		
		return bmp;

	}	
	
	/**
	 * 为了放大缩小、旋转图像,我们要使用Matrix类。Matrix类是一个三维矩阵。
	 * 在Android屏幕中,图像的每个像素对应都是一个坐标,一个坐标由x/y/z组成
	 * ------------------------
	 * cosX -sinX translateX
	 * sinX cosX  translateY
	 * 0	0	  scale
	 * ------------------------
	 * 第一行的值,影响着x坐标。比如 1 0 0 =>x = 1*x + 0*y + 0*z
	 * 第二行的值,影响着y坐标。比如0 1 0 => y = 0*x + 1*y + 0*z
	 * 第三行的值,影响着z坐标。比如 0 0 1 => z = 0*x + 0*y + 1*z
	 * 
	 * 我们自己计算一个矩阵然后通过Matrax.setValues设置。
	 * 这样,在调用canvas的drawBitmap方法时,传入matrix
	 * 
	 * Matrix类并不提倡我们使用这种方式来操作变换,Matrix针对不同的变换都相应的有pre,set,post三种方法
	 * 可以使用。
	 * pre是矩阵前乘
	 * set是直接设置
	 * post是矩阵后乘
	 */
	private Bitmap transferImage(){
		Matrix matrix = new Matrix();
		matrix.setValues(new float[]{
			.5f,0,0,//这里只会影响到x轴,所以,图片的长度将是原来的一半
			0,1,0,
			0,0,1
		});
		return this.getDstImage(matrix);
	}
	
	/**
	 * 该方法中我们将对图像的颜色,亮度,对比度等进行设置
	 * 需要用到ColorMatrix类。ColorMatrix类是一个四行五列的矩阵
	 * 每一行影响着[R,G,B,A]中的一个
	 * -------------------------
	 * a1 b1 c1 d1 e1
	 * a2 b2 c2 d2 e2
	 * a3 b3 c3 d3 e3
	 * a4 b4 c4 d4 e4
	 * -------------------------
	 * Rnew => a1*R+b1*G+c1*B+d1*A+e1
	 * Gnew => a2*R+b2*G+c2*B+d2*A+e2
	 * Bnew => a3*R+b3*G+c3*B+d3*A+e3
	 * Gnew => a4*R+b4*G+c4*B+d4*A+e4
	 * 其中R,G,B的值是128,A的值是0
	 * 
	 * 最后将颜色的修改,通过Paint.setColorFilter应用到Paint对象中。
	 * 主要对于ColorMatrix,需要将其包装成ColorMatrixColorFilter对象,再传给Paint对象
	 * 
	 * 同样的,ColorMatrix提供给我们相应的方法,setSaturation()就可以设置一个饱和度
	 */
	private Bitmap ajustImage(){
		ColorMatrix cMatrix = new ColorMatrix();
//		int brightIndex = -25;
//		int doubleColor = 2;
//		cMatrix.set(new float[]{
//				doubleColor,0,0,0,brightIndex, //这里将1改为2则我们让Red的值为原来的两倍
//				0,doubleColor,0,0,brightIndex,//改变最后一列的值,我们可以不改变RGB同道颜色的基础上,改变亮度
//				0,0,doubleColor,0,brightIndex,
//				0,0,0,doubleColor,0
//		});
		//cMatrix.setSaturation(2.0f);//设置饱和度
		cMatrix.setScale(2.0f, 2.0f, 2.0f, 2.0f);//设置颜色同道色彩缩放
		Paint paint = new Paint();
		paint.setColorFilter(new ColorMatrixColorFilter(cMatrix));
		return this.getDstImage(null, paint);
	}
	
	/**
	 * 图像的合成,可以通过在同一个Canvas中绘制两张图片。
	 * 只是在绘制第二章图片的时候,需要给Paint指定一个变幻模式TransferMode。
	 * 在Android中有一个XFermode所有的变幻模式都是这个类的子类
	 * 我们需要用到它的一个子类PorterDuffXfermode,关于这个类,其中用到PorterDuff类
	 * 这个类很简单,就包含一个Enum是Mode,其中定义了一组规则,这组规则就是如何将
	 * 一张图像和另一种图像进行合成
	 * 关于图像合成有四种模式,LIGHTEN,DRAKEN,MULTIPLY,SCREEN
	 */
	private Bitmap compositeImages(){
		
		Bitmap bmp = null;
		//下面这个Bitmap中创建的函数就可以创建一个空的Bitmap
		bmp = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
		Paint paint = new Paint();
		Canvas canvas = new Canvas(bmp);
		//首先绘制第一张图片,很简单,就是和方法中getDstImage一样
		canvas.drawBitmap(srcBitmap, 0, 0, paint);		
		
		//在绘制第二张图片的时候,我们需要指定一个Xfermode
		//这里采用Multiply模式,这个模式是将两张图片的对应的点的像素相乘
		//,再除以255,然后以新的像素来重新绘制显示合成后的图像
		paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
		canvas.drawBitmap(dstBitmap, 0, 0, paint);
		
		return bmp;
	}
	public void onActivityResult(int requestCode, int resultCode, Intent data){
		super.onActivityResult(requestCode, resultCode, data);
		
		Log.v("Result OK Value:", resultCode+"");
		Log.v("RequestCode Value", requestCode+"");
		
		if(resultCode == RESULT_OK){
			imageUri = data.getData();	
			if(requestCode == FIRST_PIC){
				//在Gallery中选中一个图片时,返回来的Intent中的Data就是选择图片的Uri
				srcBitmap = getSrcImage(imageUri);
				srcImageView.setImageBitmap(srcBitmap);				
			}else if(requestCode == SECOND_PIC){
				//这里处理用户选择的第二张图片
				
				dstBitmap = getSrcImage(imageUri);
				dstImageView.setImageBitmap(dstBitmap);
			}
		}
	}
	
	/**
	 * 需要加载的图片可能是大图,我们需要对其进行合适的缩小处理
	 * @param imageUri
	 */
	private Bitmap getSrcImage(Uri imageUri){
		//Display display = this.getWindowManager().getDefaultDisplay();
		try {
			BitmapFactory.Options ops = new BitmapFactory.Options();
			ops.inJustDecodeBounds = true;
			Bitmap bmp = BitmapFactory.decodeStream(this.getContentResolver().openInputStream(imageUri),null,ops);
			int wRatio = (int)Math.ceil(ops.outWidth/(float)MAX_WIDTH);
			int hRatio = (int)Math.ceil(ops.outHeight/(float)MAX_HEIGHT);
			
			if(wRatio > 1 && hRatio > 1){
				if(wRatio > hRatio){
					ops.inSampleSize = wRatio;
				}else{
					ops.inSampleSize = hRatio;
				}
			}
			
			ops.inJustDecodeBounds = false;
			bmp = BitmapFactory.decodeStream(this.getContentResolver().openInputStream(imageUri),null,ops);
			
			return bmp;
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			Log.e(this.getClass().getName(), e.getMessage());
		}
		
		return null;
	}
}

 

 

 

 

 

 

转自chenjie19891104的的博客(http://blog.csdn.net/chenjie19891104/article/category/756236),以

便以后学习和查询!


 

分享到:
评论

相关推荐

    Android多媒体学习之实现图像的编辑和合成

    在Android平台上,多媒体应用开发是不可或缺的一部分,尤其是在图像编辑和合成方面。这涉及到对图片进行裁剪、旋转、滤镜处理、拼接等操作,极大地丰富了用户体验。本篇文章将深入探讨Android中如何实现图像的编辑和...

    《Android多媒体编程从初学到精通》前四章

    通过前四章的学习,开发者可以建立起对Android多媒体编程的基本认识,能够独立实现简单的音频、图像和视频功能。然而,这只是多媒体编程的冰山一角,随着深入学习,开发者将掌握更复杂的技术,如实时视频处理、...

    android 把多张图片合成MP4视频Demo

    本示例代码提供了一种实现方法,通过利用Android自带的多媒体处理库,将静态图片转换为动态的视频流。以下是这个过程涉及的关键知识点: 1. **多媒体框架**:Android系统提供了一个强大的多媒体框架,包括...

    Android多媒体开发高级编程

    本节将深入探讨Android多媒体开发的高级编程技巧,帮助开发者实现更高效、更丰富的多媒体应用。 1. **多媒体框架概述** Android的多媒体框架基于开放移动联盟(OMA)的开放移动 Alliance Digital Media ...

    Android-ImageToVideoAndroid用于将图像轻松转换成视频

    图片转视频的过程主要基于多媒体处理技术,通过逐帧将图片合成到视频流中。在Android系统中,这通常涉及到`MediaCodec`和`MediaMuxer`这两个关键组件。`MediaCodec`用于编码图片数据,`MediaMuxer`则负责将编码后的...

    【eoeAndroid特刊】第15期:Android多媒体.zip

    总结,Android多媒体技术涉及音频、视频、图像以及相机的处理,开发者可以通过系统提供的API和第三方库,实现丰富的多媒体功能。深入理解这些技术,对于打造高质量的Android应用至关重要。在实际项目中,应结合具体...

    android短视频录制编辑

    综上所述,"android短视频录制编辑"项目涵盖了Android多媒体处理的多个核心知识点,从视频录制到后期编辑,涉及到了图像处理、音频处理、UI设计等多个领域,对开发者的技术要求较高。通过深入理解并运用这些技术,...

    Android的多媒体框架OpenCore介绍

    OpenCore作为Android多媒体处理的核心,与其他组件紧密集成。例如,与硬件抽象层(HAL)配合,实现对硬件音视频设备的访问;与SurfaceFlinger协作,完成画面的合成和显示;与Android的多媒体服务(如MediaPlayer服务...

    第15期:Android多媒体.zip

    总结来说,Android多媒体技术涵盖了音频、视频和图像的处理,开发者需要了解和掌握各种API的使用,以及如何针对不同的设备和场景进行优化。通过深入学习和实践,开发者可以创建出功能丰富、性能优秀的多媒体应用。

    android录屏、录音并合成视频保存本地

    综上所述,实现“android录屏、录音并合成视频保存本地”的过程涉及到Android的多媒体框架、权限管理、编码合成等多个方面的知识。通过熟练掌握这些技术,开发者可以构建出功能丰富的应用,满足用户在各种场景下的...

    FFmpegAndroid,android 端基于 FFmpeg 实现音频剪切、拼接、转码、混音、编解码;视频剪切、水印、截图、转码、编解码、转 Gif 动图;音视频合成与分离;音视频解码、同步与播放;FFmpeg 本地推流、H264 与 RTMP 实时推流直播;OpenGL GPUImage ffmpeg:色调、亮度、亮度、亮度.zip

    - 合成:将音频和视频流结合,创建新的多媒体文件。 - 分离:从多媒体文件中提取单独的音频或视频流,便于分别处理。 4. 解码与同步: - 音视频解码:将编码后的音视频数据还原成原始的比特流,以便播放或进一步...

    安卓 图片合成视频(利用javacv)

    在Android平台上,将图片合成为视频是一个常见的需求,特别是在多媒体应用或者动态相册制作中。...这个过程涉及到文件I/O、图像处理和多媒体编码等多个技术领域,对于提升Android应用的多媒体功能非常有帮助。

    行业分类-设备装置-实现多媒体图片的方法和装置.zip

    在IT行业中,多媒体图片的处理是一项至关重要的技术,它涵盖了图像的生成、编辑、传输、存储和显示等多个方面。本文将深入探讨“实现多媒体图片的方法和装置”这一主题,主要基于提供的标题和描述。 首先,我们需要...

    Android的多媒体框架OpenCore介绍(实用1).zip

    OpenCore是Android多媒体框架的核心部分,它是一个综合的多媒体处理库,负责解码、合成、流媒体控制等功能。OpenCore的设计目标是提供一种高效、灵活的解决方案,以支持多种多媒体格式和标准,满足Android设备对...

    ffmpeg视频编辑导出以及合成

    FFmpeg 是一个强大的开源工具集,用于处理音频和视频文件。...无论你是个人用户还是专业开发者,都可以通过学习和掌握 FFmpeg 来提升多媒体处理能力。了解并熟练使用 FFmpeg,能让你在视频编辑和合成领域游刃有余。

    Android--开发--的多媒体框架OpenCore介绍.rar

    尽管OpenCore在现代Android版本中的地位已经被新框架取代,但理解其工作原理对于深入学习Android多媒体处理仍然具有价值。OpenCore的模块化设计和处理流程为后来的多媒体框架提供了很好的参考和基础。 总的来说,...

    多媒体技术和Android开发平台简介.ppt

    【Android多媒体应用编程开发平台】 随着移动设备的普及,Android作为一个开放的移动开发平台,为多媒体应用的创建提供了便利。Android SDK提供了丰富的多媒体功能,支持音频、视频、图像的处理和播放,让开发者...

Global site tag (gtag.js) - Google Analytics