大致流程是,在java获得Bitmap 的相素值,再通过getSurface()拿到Surface,一起传到jni,在jni就可以直接用了。
遇到一个坑就是在荣耀7.0手机上,图片大了不行运行,目前还没找到原因,如有朋友知道可以给我留言。谢谢!
public class SurfaceActivity extends Activity{
private MSurfaceView yuvsurfaceview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_view);
yuvsurfaceview = (MSurfaceView) findViewById(R.id.tSurfaceView);
}
}
这是surfaceview
public class MSurfaceView extends SurfaceView implements SurfaceHolder.Callback{
private SurfaceHolder mHolder;
private Jni jni;
private Bitmap bitmap;
private int width, height;
public MSurfaceView(Context context) {
this(context, null, 0);
// TODO Auto-generated constructor stub
}
public MSurfaceView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// TODO Auto-generated constructor stub
}
public MSurfaceView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
jni = new Jni();
mHolder = this.getHolder();
mHolder.addCallback(this);
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.rongrong);
width = bitmap.getWidth();
height = bitmap.getHeight();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int arg1, int width, int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
//把surfce传到Jni画图
int[] pixels = new int[width * height];
System.out.println("Width : " + width + ", height : " + height);
//把位图的数据拷贝到pixels[]中
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
//初始化
jni.setSurface(holder.getSurface(), pixels, width, height);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
public Surface getSurface() {
SurfaceHolder holder = getHolder();
if (holder != null) {
return holder.getSurface();
}
return null;
}
}
调用jni的一个类
public class Jni {
static {
System.loadLibrary("videojni");
}
public native void setSurface(Surface surface, int[] bit, int w, int h);
}
jni c 的实现
#include
#include
#include "logcat.h"
#include
#include
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define RGB_SIZE 4
void _UtilsIntToBtye(unsigned char *btyeArray,int *intArray, int len);
JNIEXPORT void JNICALL Java_com_example_jni_Jni_setSurface
(JNIEnv *env, jclass jazz, jobject jsurface,jintArray pixels, jint videoWidth, jint videoHeight){
jsize length =(*env)->GetArrayLength(env,pixels);
unsigned char btyeArr[length * 4];
LOGD("pixels length = %d",length);
int* arrayPointer =(*env)->GetIntArrayElements(env,pixels,NULL);
_UtilsIntToBtye(btyeArr , arrayPointer, length);
ANativeWindow *mANativeWindow;
mANativeWindow = ANativeWindow_fromSurface(env, jsurface);
LOGD("--setSurface--form c-----1-----");
// 需要先设定图像的尺寸和格式
ANativeWindow_setBuffersGeometry(mANativeWindow, videoWidth, videoHeight, WINDOW_FORMAT_RGBA_8888);
ANativeWindow_Buffer nwBuffer;
if (0 != ANativeWindow_lock(mANativeWindow, &nwBuffer, NULL)) {
LOGD("ANativeWindow_lock() error");
return;
}
LOGD("--setSurface--form c-----2-----width = %d height = %d",nwBuffer.width,nwBuffer.height);
//这里*4是因为,buffer是8位的,arrayPointer是32位,长度肯定是按8位来算
if (nwBuffer.width >= nwBuffer.stride) {
memcpy(nwBuffer.bits, btyeArr, length*4);
// memcpy(nwBuffer.bits, arrayPointer, length*4);
LOGI("---nwBuffer.width >= nwBuffer.stride---");
} else {
/*
fixed花屏问题:
输出stride和width的日志发现,如果正常显示则stride==width,
通过注释可以看出应该是内存对齐问题导致的, 调整代码:
*/
int i;
LOGI("------bits = %d",nwBuffer.bits);
LOGI("------stride = %d",nwBuffer.stride);
for (i = 0; i < videoHeight; i++) {
memcpy(nwBuffer.bits + nwBuffer.stride * i*RGB_SIZE,
btyeArr + videoWidth * i*RGB_SIZE, videoWidth*RGB_SIZE);
}
}
if (0 != ANativeWindow_unlockAndPost(mANativeWindow)) {
LOGD("ANativeWindow_unlockAndPost error");
return;
}
ANativeWindow_release(mANativeWindow);
}
void _UtilsIntToBtye(unsigned char *btyeArray,int *intArray, int len){
int i;
LOGD("pixels length = %d",len);
for(i = 0; i < len; i++){
//red
btyeArray[i * 4] = (unsigned char)(intArray[i] >> 16) & 0xff;
//green
btyeArray[i * 4 + 1] = (unsigned char)(intArray[i] >> 8) & 0xff;
//blue
btyeArray[i * 4 + 2] = (unsigned char)intArray[i] & 0xff;
// btyeArray[i * 4 + 3] = 0x1;
//LOGD("pixels length = %d",len);
}
LOGD("pixels ............. length = %d",len);
}
LOCAL_PATH := $(call my-dir , common/src ,common)
include $(CLEAR_VARS)
LOCAL_MODULE := videojni
LOCAL_SRC_FILES := videojni.c
LOCAL_LDLIBS += -llog
# for logging
LOCAL_LDLIBS += -llog
# for native windows
LOCAL_LDLIBS += -landroid
include $(BUILD_SHARED_LIBRARY)
尊重原创,欢迎转载,转载请注明: http://blog.csdn.net/qq377366355/article/details/61519802
新手一枚,欢迎朋友指导、交流。谢谢!邮箱:[email protected]