在项目开发中涉及到比较多的图片处理,如摄像头预览图片的旋转,送入人脸识别sdk的图片数据,上传到后台识别记录的抓拍图片等等,以前常用的方式都是直接使用matrix来处理或者重复创建多个bitmap,这样会造成大量的资源浪费,并且效率低下,通过查找一些资料,发现了可以使用renderscript来处理,这样的方式会更快,因此在此记录下。
不知道renderscript是什么的同学可以看下这篇文章:Android高效计算——RenderScript
优点:
1、速度更快(对比matrix的方式速度2-5倍);
2、cpu和内存降低(使用同一份缓存);
缺点:
1、可能存在适配问题。
2、实现复杂。
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.support.v8.renderscript.*;
import android.util.Log;
public class ScriptUtils {
private static final String TAG = "ScriptUtil";
private static RenderScript mRs;
private static Allocation mInAllocation;
private static Allocation mOutAllocation;
private static ScriptC_rotatemirror mRotateRotateMirrorScript;
private static ScriptC_rotate mRotateRotateScript;
public static void getRotateBitmap(Context context, Bitmap bitmap,Bitmap outBitmap,
boolean isFrontCamera) {
if(isFrontCamera){
getRotateAndMirrorBitmap(context, bitmap,outBitmap);
return;
}
getRotateBitmap(context, bitmap,outBitmap);
}
public static void getRotateBitmap(Context context, Bitmap bitmap,Bitmap outBitmap){
if(bitmap == null || bitmap.isRecycled() || outBitmap == null || outBitmap.isRecycled()){
Log.w(TAG, "getRotateBitmap bitmap is empty!");
}
initRsIfNeed(context,bitmap,outBitmap);
mInAllocation.copyFrom(bitmap);
mRotateRotateScript.bind_gPixels(mInAllocation);
mRotateRotateScript.set_gIn(mOutAllocation);
mRotateRotateScript.set_gOut(mOutAllocation);
mRotateRotateScript.set_gScript(mRotateRotateScript);
mRotateRotateScript.invoke_filter();
mOutAllocation.copyTo(outBitmap);
}
public static void getRotateAndMirrorBitmap(Context context, Bitmap bitmap,Bitmap outBitmap){
if(bitmap == null || bitmap.isRecycled() || outBitmap == null || outBitmap.isRecycled()){
Log.w(TAG, "getRotateAndMirrorBitmap bitmap is empty!");
}
initRsIfNeed(context,bitmap,outBitmap);
mInAllocation.copyFrom(bitmap);
mRotateRotateMirrorScript.bind_gPixels(mInAllocation);
mRotateRotateMirrorScript.set_gIn(mOutAllocation);
mRotateRotateMirrorScript.set_gOut(mOutAllocation);
mRotateRotateMirrorScript.set_gScript(mRotateRotateMirrorScript);
mRotateRotateMirrorScript.invoke_filter();
mOutAllocation.copyTo(outBitmap);
}
private static void initRsIfNeed(Context context,Bitmap inBitmap,Bitmap outBitmap){
if(mRs == null){
mRs = RenderScript.create(context);
}
int width = inBitmap.getWidth();
int height = inBitmap.getHeight();
if(mInAllocation == null || (mInAllocation.getType().getX() != width || mInAllocation.getType().getY() != height) ){
if(mInAllocation != null){
mInAllocation.destroy();
}
mInAllocation = Allocation.createFromBitmap(mRs, inBitmap,
Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
}
width = outBitmap.getWidth();
height = outBitmap.getHeight();
if(mOutAllocation == null || (mOutAllocation.getType().getX() != width || mOutAllocation.getType().getY() != height) ){
if(mOutAllocation != null){
mOutAllocation.destroy();
}
mOutAllocation = Allocation.createFromBitmap(mRs, outBitmap,
Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
}
if(mRotateRotateMirrorScript == null){
mRotateRotateMirrorScript = new ScriptC_rotatemirror(mRs,context.getResources(),R.raw.rotatemirror);
}
if(mRotateRotateScript == null){
mRotateRotateScript = new ScriptC_rotate(mRs,context.getResources(),R.raw.rotate);
}
}
}
#pragma version(1)
#pragma rs java_package_name(com.jwz.bitmap.utils)
rs_allocation gIn;
rs_allocation gOut;
rs_script gScript;
static int mImageWidth;
static int mImageHeight;
const uchar4 *gPixels;
void init() {
}
void root(const uchar4 *v_in, uchar4 *v_out, const void *usrData, uint32_t x, uint32_t y) {
*v_out = gPixels[y + (mImageWidth-1-x)*mImageHeight];
return;
}
void filter() {
mImageWidth = rsAllocationGetDimX(gOut);
mImageHeight = rsAllocationGetDimY(gOut);
/*
rsDebug("In image size is ", rsAllocationGetDimX(gIn), rsAllocationGetDimY(gIn));
rsDebug("Out image size is ", rsAllocationGetDimX(gOut), rsAllocationGetDimY(gOut));
*/
rsForEach(gScript, gIn, gOut);
}
#pragma version(1)
#pragma rs java_package_name(com.jwz.bitmap.utils)
rs_allocation gIn;
rs_allocation gOut;
rs_script gScript;
static int mImageWidth;
static int mImageHeight;
const uchar4 *gPixels;
void init() {
}
void root(const uchar4 *v_in, uchar4 *v_out, const void *usrData, uint32_t x, uint32_t y) {
*v_out = gPixels[(mImageHeight-y -1) + (mImageWidth-1-x)*mImageHeight];
return;
}
void filter() {
mImageWidth = rsAllocationGetDimX(gOut);
mImageHeight = rsAllocationGetDimY(gOut);
//rsDebug("In image size is ", rsAllocationGetDimX(gIn), rsAllocationGetDimY(gIn));
//rsDebug("Out image size is ", rsAllocationGetDimX(gOut), rsAllocationGetDimY(gOut));
rsForEach(gScript, gIn, gOut);
}
#pragma version(1)
#pragma rs java_package_name(com.jwz.bitmap.utils)
rs_allocation gIn;
rs_allocation gOut;
rs_script gScript;
static int mImageWidth;
static int mImageHeight;
const uchar4 *gPixels;
void init() {
}
void root(const uchar4 *v_in, uchar4 *v_out, const void *usrData, uint32_t x, uint32_t y) {
*v_out = gPixels[(mImageWidth - x - 1) + (y-1)*mImageWidth];
return;
}
void filter() {
mImageWidth = rsAllocationGetDimX(gOut);
mImageHeight = rsAllocationGetDimY(gOut);
//rsDebug("In image size is ", rsAllocationGetDimX(gIn), rsAllocationGetDimY(gIn));
//rsDebug("Out image size is ", rsAllocationGetDimX(gOut), rsAllocationGetDimY(gOut));
rsForEach(gScript, gIn, gOut);
}
这些方法在实际的开发过程中还是很好用的,在人脸识别的应用中,往往几毫秒、十几毫秒的时间都是非常珍贵的,所以在开发过程中,我们尽可能多去使用这些性能较高的方式来完成我们的应用程序。