首先自定义一个显示控件,继承自View类:
package com.example.virreal;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ImageFormat;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import java.io.ByteArrayOutputStream;
public class DisPlay extends View {
private Bitmap bitmap = null;
private byte[] data;
public DisPlay(Context context) {
super(context);
}
public DisPlay(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public DisPlay(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public DisPlay(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
if(getBitmap() == null) {
paint.setTextSize(getHeight()/10);
canvas.drawText("没有图像数据",getLeft(),getTop() + getHeight()/10,paint);
} else {
canvas.drawBitmap(getBitmap(),0,0,paint);
}
}
private Bitmap YuvYoBitmap(byte[] data, int width, int height,int format) { //将预览的YUV数据格式转换为BitMap
YuvImage yuvImage = new YuvImage(data, format, width, height, null);
ByteArrayOutputStream os = new ByteArrayOutputStream(data.length);
if(yuvImage.compressToJpeg(new Rect(0,0, width, height),100,os)){
byte[] tmp = os.toByteArray();
bitmap = BitmapFactory.decodeByteArray(tmp, 0, tmp.length);
}
return bitmap;
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public byte[] getData() {
return data;
}
public void setData(byte[] data, int width, int height,int format) {//在Camera.PreViewCallback中调用此方法即可
this.data = data;
setBitmap(YuvYoBitmap(data, width, height, format));
}
}
其实可以看到,核心代码就是将YUV转换为Bitmap
private Bitmap YuvYoBitmap(byte[] data, int width, int height,int format) { //将预览的YUV数据格式转换为BitMap
YuvImage yuvImage = new YuvImage(data, format, width, height, null);
ByteArrayOutputStream os = new ByteArrayOutputStream(data.length);
if(yuvImage.compressToJpeg(new Rect(0,0, width, height),100,os)){
byte[] tmp = os.toByteArray();
bitmap = BitmapFactory.decodeByteArray(tmp, 0, tmp.length);
}
return bitmap;
}
这样一来,只需发送预览数据即可
Camera.PreviewCallback precallback = new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
try {
BufferedOutputStream os = new BufferedOutputStream(socket.getOutputStream());
os.write(data);
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
/* disPlay.setData(data, msize.width, msize.height, ImageFormat.NV21);
disPlay.invalidate();*/ //这两句可做自己预览用,不过我感觉自己看还是用Surface比较好。
}
};
接收并显示数据
try {
BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
int len = in.read();
byte[] tmp = new byte[len];
in.read(tmp,0,len);
disPlay.setData(data, width, height,format);
disPlay.invalidate();
} catch (IOException e) {
e.printStackTrace();
}
到这里就完成了。
想写一个调用JNI层的,大佬们有没有关于Android JNI的参考书或者网站推荐啊啊啊啊啊…