android在jni中对SurfaceView显示一张图片

大致流程是,在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 <jni.h>
#include <stdlib.h>
#include "logcat.h"
#include <android/native_window_jni.h>
#include <android/log.h>
#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);
}


android.mk

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

新手一枚,欢迎朋友指导、交流。谢谢!邮箱:zxjjiaren@qq.com



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值