android在jni中对SurfaceView显示一张图片
来源:互联网 发布:android程序员出路 编辑:程序博客网 时间:2024/05/21 07:51
大致流程是,在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 stubjni = new Jni(); mHolder = this.getHolder(); mHolder.addCallback(this); bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.rongrong); width = bitmap.getWidth(); height = bitmap.getHeight();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int arg1, int width, int height) {// TODO Auto-generated method stub}@Overridepublic 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); }@Overridepublic 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 4void _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 := videojniLOCAL_SRC_FILES := videojni.c LOCAL_LDLIBS += -llog# for loggingLOCAL_LDLIBS += -llog# for native windowsLOCAL_LDLIBS += -landroidinclude $(BUILD_SHARED_LIBRARY)
尊重原创,欢迎转载,转载请注明: http://blog.csdn.net/qq377366355/article/details/61519802
新手一枚,欢迎朋友指导、交流。谢谢!邮箱:zxjjiaren@qq.com
0 0
- android在jni中对SurfaceView显示一张图片
- [Android] 在Jni中对SurfaceView渲染一张图片
- 【Android】在SurfaceView上显示透明图片
- Android中SurfaceView的使用详解及如何在jni(hal层)直接显示
- 在SurfaceView上拖动一张小图片
- android从网络中获得一张图片,并显示在屏幕上
- android从网络中获得一张图片,并显示在屏幕上
- 在Github的README.md中显示一张图片
- 在Github的README.md中显示一张图片
- Android中从网上下载一张图片显示进度并显示下载好的图片
- 如何在用户区显示一张图片
- 如何在对话框上显示一张图片
- html先显示一张图片2秒后自动隐藏,用在游戏显示logo中
- iOS中如何显示一张图片
- Qt-Quick中设置组件风格、显示一张图片、在一行显示多张图片的方法、绘制图片方法...
- Qt中通过控件在Label标签中显示一张静态图片
- android在RelativeLayout中添加两个SurfaceView预览视频,运行程序后发现有一个surfaceview没有显示的解决办法.
- Android之---ImagView显示图片(将一张图片按原图大小合理显示在imageView上,避免OOM)
- 抽象类和接口区别
- eclipse 使用maven 构建 springboot+mybatis
- 自定义类型转换器的步骤
- 11-jQuery插件
- Android app 启动优化
- android在jni中对SurfaceView显示一张图片
- Android进阶之路
- JQueryEasyUI 组件 布局 Tabs组件(选项卡)
- NavigationView如此风骚的控件
- 数据结构—树与二叉树篇III
- Eclipse中Outline里各种图标的含义
- shadowsocks:此实现不是 Windows 平台 FIPS 验证的加密算法的一部分 解决办法
- 开篇
- elasticsearch 学习笔记