Android Bitmap图片的处理

【一】

转自:http://blog.csdn.net/zimo2013/article/details/16848939

比较好的参考:http://blog.csdn.net/zimo2013/article/details/16849477

Bitmap是Android系统中的图像处理的最重要类之一。用它可以获取图像文件信息,进行图像剪切、旋转、缩放等操作,并可以指定格式保存图像文件。本文从应用的角度,着重介绍怎么用Bitmap来实现这些功能。

每一个图片从服务器/SDCard中拉取到客户端之前都必须经过剪裁、缩放(剪裁)这两个过程,如果服务器没有处理图片的话。

一、Bitmap的生成

1.1 BitmapFactory decode出Bitmap

    Bitmap实现在android.graphics包中。但是Bitmap类的构造函数是私有的,外面并不能实例化,只能是通过JNI实例化。这必然是 某个辅助类提供了创建Bitmap的接口,而这个类的实现通过JNI接口来实例化Bitmap的,这个类就是BitmapFactory。

Android图像处理之Bitmap类

图一、BitmapFactory主要方法及Options选项

 

利用BitmapFactory可以从一个指定文件中,利用decodeFile()解出Bitmap;也可以定义的图片资源中,利用decodeResource()解出Bitmap。

 

1.2 decode时的选项

在使用方法decodeFile()/decodeResource()时,都可以指定一个BitmapFacotry.Options

利用Options的下列属性,可以指定decode的选项:

  • inPreferredConfig 指定decode到内存中,手机中所采用的编码,可选值定义在Bitmap.Config中。缺省值是ARGB_8888。
  • inJustDecodeBounds 如果设置为true,并不会把图像的数据完全解码,亦即decodeXyz()返回值为null,但是Options的outAbc中解出了图像的基本信息。
  • inSampleSize 设置decode时的缩放比例。

 

利用Options的这些值就可以高效的得到一幅缩略图。

Android图像处理之Bitmap类

图二、BitmapFactory.decodeFile()

 

先设置inJustDecodeBounds= true,调用decodeFile()得到图像的基本信息[Step#2~4];

利用图像的宽度(或者高度,或综合)以及目标的宽度,得到inSampleSize值,再设置inJustDecodeBounds= false,调用decodeFile()得到完整的图像数据[Step#5~8]。

先获取比例,再读入数据,如果欲读入大比例缩小的图,将显著的节约内容资源。有时候还会读入大量的缩略图,这效果就更明显了。

 

二、利用Bitmap和Matrix实现图像变换

    Bitmap可以和Matrix结合实现图像的剪切、旋转、缩放等操作。

Android图像处理之Bitmap类

图三、Bitmap方法

 

用源Bitmap通过变换生成新的Bitmap的方法:

[java]  view plain copy
  1. public static Bitmap createBitmap(Bitmap source, int x, int y, intwidth, int height, Matrix m, boolean filter)
  2. public static Bitmap createBitmap(Bitmap source, int x, int y, intwidth, int height)
  3. public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)

第一个方法是最终的实现,后两种只是对第一种方法的封装。

第二个方法可以从源Bitmap中指定区域(x,y, width, height)中挖出一块来实现剪切;第三个方法可以把源Bitmap缩放为dstWidth x dstHeight的Bitmap。

 

设置Matrix的Rotate(通过setRotate())或者Scale(通过setScale()),传入第一个方法,可实现旋转或缩放。

Android图像处理之Bitmap类

图四、Bitmap实现旋转

 

三、保存图像文件

    经过图像变换之后的Bitmap里的数据可以保存到图像压缩文件里(JPG/PNG)。

Android图像处理之Bitmap类

图五、保存Bitmap数据到文件

 

这个操作过程中,Bitmap.compress()方法的参数format可设置JPEG或PNG格式;quality可选择压缩质量;fOut是输出流(OutputStream),这里的FileOutputStream是OutputStream的一个子类。

总结一下,本文介绍Bitmap的使用方法——用Bitmap实现图像文件的读取和写入,并用Bitmap实现图像的剪切、旋转和缩放变换。



【二】

从网络上加载图片,除了图片缓存(LruCache)外,还需要解决图片内存大小和图片几何大小问题(前提是服务器端没有显示图片大小),解决从网络或sdcard上加载大图片有可能造成内存OOM的问题和图片可能产生的拉伸变形问题,图片从网络服务器上拉取到手机或从手机相机获取图片存入手机等,首先都应该对图片进行采样,减少高宽的像素来达到节省内存,之后再对采样后的图片进行裁剪方式生成缩略图或采用缩放方式生成缩略图(根据项目需求二则采用其一即可)。

下面是我写的采样图片、压缩图片、裁剪图片的3个函数,以后项目中可以直接复制使用:

1. 采样图片函数:

	/**
	 * 采样图片,减少图片占用内存。
	 * 算法:采样率设为x,则要求 srcHeight / x > dstHeight,且 srcWidth / x > dstWidth;
	 * @param srcBitmap
	 * @param dstWidth
	 * @param dstHeight
	 * @return
	 */
	public static Bitmap sampleBitmap(String pathName, int dstWidth, int dstHeight) {
		int inSampleSize = 1;
		
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(pathName, options);
		int srcHeight = options.outHeight;
		int srcWidth = options.outWidth;
		
		if (srcHeight > dstHeight || srcWidth > dstWidth) {
			
			// 计算出实际宽高和目标宽高的比率
	        final int heightRatio = Math.round((float) srcHeight / (float) dstHeight);
	        final int widthRatio = Math.round((float) srcWidth / (float) dstWidth);
	        
	        // 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高  
	        // 一定都会大于等于目标的宽和高。  
	        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
		}

		options.inSampleSize = inSampleSize;
		options.inJustDecodeBounds = false;
		return BitmapFactory.decodeFile(pathName, options);
	}


2. 缩放图片和裁剪图片生成缩略图的函数:

	/**
	 * 缩放图片方式生成缩略图:必须调整目标宽、高来保持原始图片的宽高比,否则图片会被拉伸,
	 * 压缩算法是:比较(原始图片高宽比例)和(目标图片高宽比例)的大小,如果前者大于后者,则
	 * 说明需要减小目标图片的宽度以适应原始高宽比例;反之,减小目标图片的高度。
	 * 
	 * 【思想是:要想达到原始图片的比例,目标图片只能减小高度或宽度的大小来适应,不能增加
	 * 图片大小】
	 * (1) srcHeight / srcWidth > dstHeight / dstWidth:只能减小dstWidth;
	 * (2) srcHeight / srcWidth < dstHeight / dstWidth: 只能减小dstHeight;
	 * 
	 * @param srcBitmap
	 * @param dstWidht 必须小于srcBitmap图片的宽度
	 * @param dstHeight 必须小于srcBitmap图片的高度
	 * @return
	 */
	public static Bitmap createScaledBitmap(Bitmap srcBitmap, int dstWidth, int dstHeight) {
		Bitmap retBitmap = null;
		int srcWidth = srcBitmap.getWidth();
		int srcHeight = srcBitmap.getHeight();

		if (srcWidth > dstWidth && srcHeight > dstHeight) {
			int srcScaled = srcHeight / srcWidth; // 原始图片高宽比例
			int dstScaled = dstHeight / dstWidth; // 目标图片高宽比例
			if (srcScaled > dstScaled) {
				dstWidth = dstHeight / srcScaled; // dstHeight不变
			} else {
				dstHeight = dstWidth * srcScaled; // dstWidth不变
			}
			retBitmap = Bitmap.createScaledBitmap(srcBitmap, dstWidth, dstHeight, true);
			
			if (!srcBitmap.isRecycled()) {
				srcBitmap.recycle();
			}
			return retBitmap;
		}
		
		return srcBitmap;
	}
	
	/**
	 * 剪切图片方式生成缩略图
	 * @author Habby
	 * @param srcBitmap
	 * @param dstWidth 必须小于srcBitmap图片的宽度
	 * @param dstHeight 必须小于srcBitmap图片的高度
	 * @return
	 */
	public static Bitmap createCenterCropBitmap(Bitmap srcBitmap, int dstWidth, int dstHeight) {
		Bitmap retBitmap = null;
		int srcWidth = srcBitmap.getWidth();
		int srcHeight = srcBitmap.getHeight();

		if (srcWidth > dstWidth && srcHeight > dstHeight) {
			int x = (srcWidth - dstWidth) / 2;
			int y = (srcHeight - dstHeight) / 2;
			retBitmap = Bitmap.createBitmap(srcBitmap, x, y, dstWidth, dstHeight);
			if (!srcBitmap.isRecycled()) {
				srcBitmap.recycle();
			}
			return retBitmap;
		}
		
		return srcBitmap;
	}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 要在 Android 上合成多个 Bitmap 图片,可以使用 Canvas 类和 Bitmap 类。下面是一个简单的示例: 1. 创建一个空的 Bitmap 对象,作为最终合成的图片: ```java Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(result); ``` 2. 将需要合成的 Bitmap 依次绘制到空的 Bitmap 上: ```java canvas.drawBitmap(bitmap1, x1, y1, null); canvas.drawBitmap(bitmap2, x2, y2, null); canvas.drawBitmap(bitmap3, x3, y3, null); ``` 3. 最后,可以保存合成后的 Bitmap图片文件或者显示在 ImageView 中: ```java imageView.setImageBitmap(result); ``` 完整的代码示例: ```java public Bitmap mergeBitmaps(Bitmap bitmap1, Bitmap bitmap2, Bitmap bitmap3) { int width = bitmap1.getWidth(); int height = bitmap1.getHeight() + bitmap2.getHeight() + bitmap3.getHeight(); Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(result); canvas.drawBitmap(bitmap1, 0, 0, null); canvas.drawBitmap(bitmap2, 0, bitmap1.getHeight(), null); canvas.drawBitmap(bitmap3, 0, bitmap1.getHeight() + bitmap2.getHeight(), null); return result; } ``` 以上代码将三个 Bitmap 垂直合成为一个 Bitmap,第一个 Bitmap 在最上面,第二个在中间,第三个在最下面。可以根据实际需求修改代码。 ### 回答2: Android中合成bitmap图片可以使用Canvas和Paint类来实现。步骤如下: 1. 创建一个新的Bitmap对象,用于存储合成后的图片。 2. 创建一个Canvas对象,并将新的Bitmap对象与Canvas关联起来。 3. 创建一个Paint对象,并设置相关的合成属性,如颜色、透明度、画笔风格等。 4. 使用Canvas的drawBitmap()方法将多个Bitmap对象绘制到新的Bitmap上,实现图片的合成效果。 5. 最后,可以将合成后的Bitmap保存到本地文件或者显示在界面上。 以下是一个简单的示例代码: ```java // 创建合成后的Bitmap对象 Bitmap resultBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); // 创建Canvas对象,并与新的Bitmap关联 Canvas canvas = new Canvas(resultBitmap); // 创建Paint对象 Paint paint = new Paint(); // 设置合成属性 paint.setColor(Color.RED); paint.setAlpha(128); paint.setStyle(Paint.Style.FILL); // 绘制bitmap1 canvas.drawBitmap(bitmap1, matrix1, paint); // 绘制bitmap2 canvas.drawBitmap(bitmap2, matrix2, paint); // 绘制bitmap3 canvas.drawBitmap(bitmap3, matrix3, paint); // 可以依次绘制更多的bitmap ... // 保存合成后的Bitmap到本地文件 resultBitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); ``` 以上代码中,width和height表示合成后的Bitmap的宽度和高度,bitmap1、bitmap2、bitmap3等表示待合成的原始Bitmap对象,matrix1、matrix2、matrix3等表示对相应的Bitmap进行变换的Matrix对象。 通过以上步骤,就可以实现Android中的Bitmap图片合成。 ### 回答3: Android中的Bitmap是一个表示图像的类,可以用来显示图片、进行图像处理等操作。要实现Bitmap图片合成,可以通过以下步骤: 1. 创建一个新的Bitmap对象,用于存储合成后的图片。可以使用Bitmap的createBitmap()方法,指定宽度、高度和颜色格式创建一个空白的Bitmap对象。 2. 获取要合成的原始图片。可以使用BitmapFactory的decodeResource()方法,从资源文件中加载图片,并通过BitmapFactory.Options对象设置图片的缩放比例、色彩模式等参数。 3. 将原始图片绘制到新的Bitmap对象上。可以使用Canvas的drawBitmap()方法,在新的Bitmap上绘制原始图片。可以设置合成图片的位置、大小等属性。 4. 如果需要合成多张图片,重复步骤2和步骤3,将其他图片依次绘制到新的Bitmap对象上。 5. 最后,可以将合成后的Bitmap对象进行保存或显示。可以使用Bitmap的compress()方法将Bitmap对象保存到指定的输出流中,或使用ImageView等控件的setImageBitmap()方法显示合成后的图片。 需要注意的是,图片合成可能会消耗较大的内存和处理时间,特别是在合成大尺寸图片或大量图片时。为了避免内存溢出和性能问题,可以适当进行图片的压缩、缩放或分块处理,或使用异步处理方式进行合成。此外,可以通过Bitmap的回收和复用来优化内存使用。 总之,通过创建新的Bitmap对象,获取原始图片,绘制到新的Bitmap上,就可以实现Android中的图片合成功能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值