求解自定义相机短时间拍多张照片导致OOM如何解决

格子林ll 2015-01-19 08:27:42
加精
我现在在做一款自定义相机,需要有一个快速拍照的功能,就是用户可以短时间内一直点那个拍照按钮,不需要等之前那张照片处理完,由于底层相机的原因,我没张图片都需要做旋转,有些需要做剪裁,所以目前我都得转成Bitmap来处理
现在的一个方案是这样的:
用户点击一下拍照,我就开一个线程,这个线程只是用来实现文件流保存图片的,不会导致OOM,同时每次开启一个线程我就把这个线程放到List容器中,线程执行结束后移除,当list容器中线程个数为0时就是用户这短时间里面要的图片都用文件流的形式保存完了
这时候我会开启另一个线程,会优先处理最后一张图片来给用户提前预览,然后紧接着用for循环对之前未处理的图片进行一张张的处理,每张图片我最后都有recycle和值为null回收
但是现在还是会一直出现OOM的情况,好多方法都试过了,目前真的束手无策,目前自身技术也还处于刚起步,希望各位大神指点一下思路或者解决的方案,我不知道byte[]数组是否可以直接进行旋转剪裁的操作而不需要读成Bitmap,是否需要到底层实现?
真心求指点,已经卡了好久了,跪谢!!
...全文
1129 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
Trent1985 2015-02-09
  • 打赏
  • 举报
回复
引用 20 楼 mrDiordna 的回复:
[quote=引用 19 楼 Trent1985 的回复:] [quote=引用 12 楼 mrDiordna 的回复:] [quote=引用 9 楼 u013405006 的回复:] http://blog.csdn.net/taotao110120119/article/details/7450561这边文章里面我觉得对你可能是有用的,而且做法比较简单,你内存泄露其实主要就是没能够及时的释放内存导致的,那为什么没能够释放内存呢?这边文章里面有提到。
在每次使用完bitmap之后都有recycle和置为null,但是依旧存在OOM的问题,因为我是开线程来操作的,就可能是多条线程同时出现decode的情况,而且我查到一篇博文有说recycle不是立马回收,不知真假[/quote] 这个问题可能有几个原因: 1,你保存bitmap的方法有问题,如果你使用的是BitmaFactory.createBitmap这种方式,来生成图像,保存,那么,很有可能出现挂掉的情况,最好使用流操作; 2,你保存过程中,是否显示图像,如果显示,那么每次都把ImageView先设置为空,比如setImageResource(0),然后在显示图像; 3,如果实线程冲突了,那么你记录个boolean变量,当线程执行时,变量为true,该线程执行完毕后,为false,先一个线程开启时 做个判断即可。[/quote] 1.createBitmap是必须使用的吧,因为我要对图片做旋转剪裁还有缩放,就必须先从流里面加载一个图片,然后再将这个Bitamp作为source来create出最终的bitmap 分享下我的解决方法便于往后需要的人参考: 1.在AndroidManifest中申请largeHeap=true,向系统申请应用所能拿到的最大空间,对于图片处理软件来说这个操作应该是利大于弊的 2.使用线程池进行操作,往高一点可以动态根据手机的不同内存来开启不同数量的线程 3.可以考虑往JNI方面走,但是不知道使用算法后图片处理效率是否会变慢,有试过使用算法合并两张图片,时间大概要十来秒,这方面之前还没深入研究过,所以还得尝试一下 希望有更好解决方法的朋友一起交流,这个应该是android系统经常会遇到的问题,帮助别人也是帮助自己,万分感谢![/quote] jni层可以 引用 CC写的图像合并算法,肯定不会那么慢你!我现在专业做jni+C图像处理的
格子林ll 2015-02-09
  • 打赏
  • 举报
回复
引用 19 楼 Trent1985 的回复:
[quote=引用 12 楼 mrDiordna 的回复:] [quote=引用 9 楼 u013405006 的回复:] http://blog.csdn.net/taotao110120119/article/details/7450561这边文章里面我觉得对你可能是有用的,而且做法比较简单,你内存泄露其实主要就是没能够及时的释放内存导致的,那为什么没能够释放内存呢?这边文章里面有提到。
在每次使用完bitmap之后都有recycle和置为null,但是依旧存在OOM的问题,因为我是开线程来操作的,就可能是多条线程同时出现decode的情况,而且我查到一篇博文有说recycle不是立马回收,不知真假[/quote] 这个问题可能有几个原因: 1,你保存bitmap的方法有问题,如果你使用的是BitmaFactory.createBitmap这种方式,来生成图像,保存,那么,很有可能出现挂掉的情况,最好使用流操作; 2,你保存过程中,是否显示图像,如果显示,那么每次都把ImageView先设置为空,比如setImageResource(0),然后在显示图像; 3,如果实线程冲突了,那么你记录个boolean变量,当线程执行时,变量为true,该线程执行完毕后,为false,先一个线程开启时 做个判断即可。[/quote] 1.createBitmap是必须使用的吧,因为我要对图片做旋转剪裁还有缩放,就必须先从流里面加载一个图片,然后再将这个Bitamp作为source来create出最终的bitmap 分享下我的解决方法便于往后需要的人参考: 1.在AndroidManifest中申请largeHeap=true,向系统申请应用所能拿到的最大空间,对于图片处理软件来说这个操作应该是利大于弊的 2.使用线程池进行操作,往高一点可以动态根据手机的不同内存来开启不同数量的线程 3.可以考虑往JNI方面走,但是不知道使用算法后图片处理效率是否会变慢,有试过使用算法合并两张图片,时间大概要十来秒,这方面之前还没深入研究过,所以还得尝试一下 希望有更好解决方法的朋友一起交流,这个应该是android系统经常会遇到的问题,帮助别人也是帮助自己,万分感谢!
Trent1985 2015-02-02
  • 打赏
  • 举报
回复
引用 12 楼 mrDiordna 的回复:
[quote=引用 9 楼 u013405006 的回复:] http://blog.csdn.net/taotao110120119/article/details/7450561这边文章里面我觉得对你可能是有用的,而且做法比较简单,你内存泄露其实主要就是没能够及时的释放内存导致的,那为什么没能够释放内存呢?这边文章里面有提到。
在每次使用完bitmap之后都有recycle和置为null,但是依旧存在OOM的问题,因为我是开线程来操作的,就可能是多条线程同时出现decode的情况,而且我查到一篇博文有说recycle不是立马回收,不知真假[/quote] 这个问题可能有几个原因: 1,你保存bitmap的方法有问题,如果你使用的是BitmaFactory.createBitmap这种方式,来生成图像,保存,那么,很有可能出现挂掉的情况,最好使用流操作; 2,你保存过程中,是否显示图像,如果显示,那么每次都把ImageView先设置为空,比如setImageResource(0),然后在显示图像; 3,如果实线程冲突了,那么你记录个boolean变量,当线程执行时,变量为true,该线程执行完毕后,为false,先一个线程开启时 做个判断即可。
laoer_2002 2015-02-02
  • 打赏
  • 举报
回复
支持楼主
zyr987503101 2015-01-27
  • 打赏
  • 举报
回复
画虎烂 2015-01-22
  • 打赏
  • 举报
回复
关注中,支持下楼主
xusir98 2015-01-22
  • 打赏
  • 举报
回复
格子林ll 2015-01-21
  • 打赏
  • 举报
回复
引用 9 楼 u013405006 的回复:
http://blog.csdn.net/taotao110120119/article/details/7450561这边文章里面我觉得对你可能是有用的,而且做法比较简单,你内存泄露其实主要就是没能够及时的释放内存导致的,那为什么没能够释放内存呢?这边文章里面有提到。
在每次使用完bitmap之后都有recycle和置为null,但是依旧存在OOM的问题,因为我是开线程来操作的,就可能是多条线程同时出现decode的情况,而且我查到一篇博文有说recycle不是立马回收,不知真假
格子林ll 2015-01-21
  • 打赏
  • 举报
回复
引用 10 楼 u012137924 的回复:
我之前做相关项目的时候,也是出现OOM,后来解决了。个人觉得你的问题跟我的有点类似,你自己也觉得是同时decode的时候造成的OOM吧,所以,我才说用一个数组来存一张照片,然后后面按照你的思路走,不过,这样的话,貌似有点奢侈,多了应该也会OOM,汗,这个问题还真不好解决。 加油吧,你行的!要是解决了,给个解决的思路或方案。呵呵。
因为目前在实习让做自定义相机项目,这个问题卡了两天了,有推荐直接对byte[]数组进行操作的,这个目前来说如果有算法应该是最佳的感觉,算法也肯定是有的,就是不知道去哪找,有点心烦
山鹰1985 2015-01-21
  • 打赏
  • 举报
回复
我之前做相关项目的时候,也是出现OOM,后来解决了。个人觉得你的问题跟我的有点类似,你自己也觉得是同时decode的时候造成的OOM吧,所以,我才说用一个数组来存一张照片,然后后面按照你的思路走,不过,这样的话,貌似有点奢侈,多了应该也会OOM,汗,这个问题还真不好解决。 加油吧,你行的!要是解决了,给个解决的思路或方案。呵呵。
索吻的贼 2015-01-21
  • 打赏
  • 举报
回复
http://blog.csdn.net/taotao110120119/article/details/7450561这边文章里面我觉得对你可能是有用的,而且做法比较简单,你内存泄露其实主要就是没能够及时的释放内存导致的,那为什么没能够释放内存呢?这边文章里面有提到。
格子林ll 2015-01-21
  • 打赏
  • 举报
回复
引用 7 楼 u012137924 的回复:
你的OOM是不是出现在Byte[]里面,你有没有试过新开一个线程就new 一个Byte[],或者用更大的数组来存储,然后把这些数组存到一个指定的地方,处理完最近一张照片的同时异步处理这些照片,同时处理的话等待时间太长了,而且容易出错。
不可能是byte数组OOM的,因为android给bitmap分配的空间是8MB左右,一张清晰的照片基本应该是2M甚至更大,所以同时decode的时候会造成内存溢出,目前估计办法只能用算法甚至往JNI方面靠拢了
windfury_plus 2015-01-20
  • 打赏
  • 举报
回复
android预览的效果默认支持为NV21和yv12,具体的你可以下面方法试着查看真机支持的格式 如果支持的话可以用parameters.setPreviewFormat(ImageFormat.YV12);之类的设置格式了。

List<Integer> pvFmts = parameters.getSupportedPreviewFormats();//Camera.Parameters parameters
if (pvFmts == null || !pvFmts.contains(ImageFormat.NV21))//例如
{
					Log.v(TAG, "手机不支持ImageFormat.NV21");
}
关于nv21 http://blog.csdn.net/vblittleboy/article/details/10945143 参考过的一篇,了解uv的排列 旋转的思路大概是: 先对Y进行排列,再对UV进行排列,不同的编码格式的差异在于UV。 我项目中用的是YV12的转换算法。排列是U在前V在后,而I420是V在前U在后,所占位子一样。 NV21除了Y是一样的,UV是排列在一起的。 就这么多资料了。靠你自己了
山鹰1985 2015-01-20
  • 打赏
  • 举报
回复
为什么不想想用摄像模式来截图?你的解决方法太复杂了。
山鹰1985 2015-01-20
  • 打赏
  • 举报
回复
你的OOM是不是出现在Byte[]里面,你有没有试过新开一个线程就new 一个Byte[],或者用更大的数组来存储,然后把这些数组存到一个指定的地方,处理完最近一张照片的同时异步处理这些照片,同时处理的话等待时间太长了,而且容易出错。
windfury_plus 2015-01-20
  • 打赏
  • 举报
回复
引用 5 楼 mrDiordna 的回复:
[quote=引用 4 楼 u012137924 的回复:] 为什么不想想用摄像模式来截图?你的解决方法太复杂了。
因为有摄影模式和拍照模式,而且系统处理的方式应该也不是用摄影模式吧,感觉这是种规避的方法[/quote] 摄像模式的清晰度和拍照模式还是有很大差别吧,还有一些小功能也缺失……如果可以弄成一样,能否介绍下方法。
格子林ll 2015-01-20
  • 打赏
  • 举报
回复
引用 4 楼 u012137924 的回复:
为什么不想想用摄像模式来截图?你的解决方法太复杂了。
因为有摄影模式和拍照模式,而且系统处理的方式应该也不是用摄影模式吧,感觉这是种规避的方法
格子林ll 2015-01-19
  • 打赏
  • 举报
回复
引用 1 楼 inquisitive_plus 的回复:
我做过的是操作Camera类的 mCamera.setPreviewCallback方法的 Camera.PreviewCallback回调接口的 onPreviewFrame方法 其中有个参数是byte[] data,就是每帧图像的byte数组,对其进行旋转 如果知道设置过每帧动画的数据类型,例如设置了 parameters.setPreviewFormat(ImageFormat.YV12);//Camera.Parameters parameters 因为下面的旋转算法是对yv12,如果是图像是nv21算法有些类似,但需要修改下(原因是图像数据排列方式不同)。你可以百度一下 下面贴一下yv12的旋转算法(逆时针旋转90度)

/**
	 * 旋转数据
	 * 
	 * @param dst
	 *            目标数据
	 * @param src
	 *            源数据
	 * @param srcWidth
	 *            源数据宽
	 * @param height
	 *            源数据高
	 */
	private void YV12RotateNegative90(byte[] dst, byte[] src, int srcWidth,
			int height)
	{
		int t = 0;
		int i, j;

		int wh = srcWidth * height;

		for (i = srcWidth - 1; i >= 0; i--)
		{
			for (j = height - 1; j >= 0; j--)
			{
				dst[t++] = src[j * srcWidth + i];
			}
		}

		for (i = srcWidth / 2 - 1; i >= 0; i--)
		{
			for (j = height / 2 - 1; j >= 0; j--)
			{
				dst[t++] = src[wh + j * srcWidth / 2 + i];
			}
		}

		for (i = srcWidth / 2 - 1; i >= 0; i--)
		{
			for (j = height / 2 - 1; j >= 0; j--)
			{
				dst[t++] = src[wh * 5 / 4 + j * srcWidth / 2 + i];
			}
		}
	}

能否求告知一下如何知道图片是yv21还是nv21,还有我旋转的角度不是固定的,这个算法是否有出处,希望大神再指点详细些
windfury_plus 2015-01-19
  • 打赏
  • 举报
回复
我做过的是操作Camera类的 mCamera.setPreviewCallback方法的 Camera.PreviewCallback回调接口的 onPreviewFrame方法 其中有个参数是byte[] data,就是每帧图像的byte数组,对其进行旋转 如果知道设置过每帧动画的数据类型,例如设置了 parameters.setPreviewFormat(ImageFormat.YV12);//Camera.Parameters parameters 因为下面的旋转算法是对yv12,如果是图像是nv21算法有些类似,但需要修改下(原因是图像数据排列方式不同)。你可以百度一下 下面贴一下yv12的旋转算法(逆时针旋转90度)

/**
	 * 旋转数据
	 * 
	 * @param dst
	 *            目标数据
	 * @param src
	 *            源数据
	 * @param srcWidth
	 *            源数据宽
	 * @param height
	 *            源数据高
	 */
	private void YV12RotateNegative90(byte[] dst, byte[] src, int srcWidth,
			int height)
	{
		int t = 0;
		int i, j;

		int wh = srcWidth * height;

		for (i = srcWidth - 1; i >= 0; i--)
		{
			for (j = height - 1; j >= 0; j--)
			{
				dst[t++] = src[j * srcWidth + i];
			}
		}

		for (i = srcWidth / 2 - 1; i >= 0; i--)
		{
			for (j = height / 2 - 1; j >= 0; j--)
			{
				dst[t++] = src[wh + j * srcWidth / 2 + i];
			}
		}

		for (i = srcWidth / 2 - 1; i >= 0; i--)
		{
			for (j = height / 2 - 1; j >= 0; j--)
			{
				dst[t++] = src[wh * 5 / 4 + j * srcWidth / 2 + i];
			}
		}
	}

80,351

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧