Java 如何在相机预览中显示水印
我正在制作一个运动检测器应用程序,我想在相机预览上显示一个水印图像。 我试过这个方法,但对我不起作用。请在代码中解释,如何在没有任何问题的情况下显示运动检测部分的水印 MotionDetection.javaJava 如何在相机预览中显示水印,java,android,android-layout,android-camera,surfaceview,Java,Android,Android Layout,Android Camera,Surfaceview,我正在制作一个运动检测器应用程序,我想在相机预览上显示一个水印图像。 我试过这个方法,但对我不起作用。请在代码中解释,如何在没有任何问题的情况下显示运动检测部分的水印 MotionDetection.java public class MotionDetectionActivity extends SensorsActivity { private static final String TAG = "MotionDetectionActivity"; private static Surf
public class MotionDetectionActivity extends SensorsActivity {
private static final String TAG = "MotionDetectionActivity";
private static SurfaceView preview = null;
private static SurfaceHolder previewHolder = null;
private static Camera camera = null;
private static boolean inPreview = false;
private static long mReferenceTime = 0;
private static IMotionDetection detector = null;
private static volatile AtomicBoolean processing = new AtomicBoolean(false);
/**
* {@inheritDoc}
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
preview = (SurfaceView) findViewById(R.id.preview);
previewHolder = preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
if (Preferences.USE_RGB) {
detector = new RgbMotionDetection();
} else if (Preferences.USE_LUMA) {
detector = new LumaMotionDetection();
} else {
// Using State based (aggregate map)
detector = new AggregateLumaMotionDetection();
}
}
/**
* {@inheritDoc}
*/
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
/**
* {@inheritDoc}
*/
@Override
public void onPause() {
super.onPause();
camera.setPreviewCallback(null);
if (inPreview) camera.stopPreview();
inPreview = false;
camera.release();
camera = null;
}
/**
* {@inheritDoc}
*/
@Override
public void onResume() {
super.onResume();
camera = Camera.open();
}
private PreviewCallback previewCallback = new PreviewCallback() {
/**
* {@inheritDoc}
*/
@Override
public void onPreviewFrame(byte[] data, Camera cam) {
if (data == null) return;
Camera.Size size = cam.getParameters().getPreviewSize();
if (size == null) return;
if (!GlobalData.isPhoneInMotion()) {
DetectionThread thread = new DetectionThread(data, size.width, size.height);
thread.start();
}
}
};
private SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
/**
* {@inheritDoc}
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera.setPreviewDisplay(previewHolder);
camera.setPreviewCallback(previewCallback);
} catch (Throwable t) {
Log.e("PreviewDemo-surfaceCallback", "Exception in setPreviewDisplay()", t);
}
}
/**
* {@inheritDoc}
*/
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = getBestPreviewSize(width, height, parameters);
if (size != null) {
parameters.setPreviewSize(size.width, size.height);
Log.d(TAG, "Using width=" + size.width + " height=" + size.height);
}
camera.setParameters(parameters);
camera.startPreview();
inPreview = true;
}
/**
* {@inheritDoc}
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// Ignore
}
};
private static Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) {
Camera.Size result = null;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width <= width && size.height <= height) {
if (result == null) {
result = size;
} else {
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea) result = size;
}
}
}
return result;
}
private static final class DetectionThread extends Thread {
private byte[] data;
private int width;
private int height;
public DetectionThread(byte[] data, int width, int height) {
this.data = data;
this.width = width;
this.height = height;
}
/**
* {@inheritDoc}
*/
@Override
public void run() {
if (!processing.compareAndSet(false, true)) return;
// Log.d(TAG, "BEGIN PROCESSING...");
try {
// Previous frame
int[] pre = null;
if (Preferences.SAVE_PREVIOUS) pre = detector.getPrevious();
// Current frame (with changes)
// long bConversion = System.currentTimeMillis();
int[] img = null;
if (Preferences.USE_RGB) {
img = ImageProcessing.decodeYUV420SPtoRGB(data, width, height);
} else {
img = ImageProcessing.decodeYUV420SPtoLuma(data, width, height);
}
// long aConversion = System.currentTimeMillis();
// Log.d(TAG, "Converstion="+(aConversion-bConversion));
// Current frame (without changes)
int[] org = null;
if (Preferences.SAVE_ORIGINAL && img != null) org = img.clone();
if (img != null && detector.detect(img, width, height)) {
// The delay is necessary to avoid taking a picture while in
// the
// middle of taking another. This problem can causes some
// phones
// to reboot.
long now = System.currentTimeMillis();
if (now > (mReferenceTime + Preferences.PICTURE_DELAY)) {
mReferenceTime = now;
Bitmap previous = null;
if (Preferences.SAVE_PREVIOUS && pre != null) {
if (Preferences.USE_RGB) previous = ImageProcessing.rgbToBitmap(pre, width, height);
else previous = ImageProcessing.lumaToGreyscale(pre, width, height);
}
Bitmap original = null;
if (Preferences.SAVE_ORIGINAL && org != null) {
if (Preferences.USE_RGB) original = ImageProcessing.rgbToBitmap(org, width, height);
else original = ImageProcessing.lumaToGreyscale(org, width, height);
}
Bitmap bitmap = null;
if (Preferences.SAVE_CHANGES) {
if (Preferences.USE_RGB) bitmap = ImageProcessing.rgbToBitmap(img, width, height);
else bitmap = ImageProcessing.lumaToGreyscale(img, width, height);
}
Log.i(TAG, "Saving.. previous=" + previous + " original=" + original + " bitmap=" + bitmap);
Looper.prepare();
new SavePhotoTask().execute(previous, original, bitmap);
} else {
Log.i(TAG, "Not taking picture because not enough time has passed since the creation of the Surface");
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
processing.set(false);
}
// Log.d(TAG, "END PROCESSING...");
processing.set(false);
}
};
private static final class SavePhotoTask extends AsyncTask<Bitmap, Integer, Integer> {
/**
* {@inheritDoc}
*/
@Override
protected Integer doInBackground(Bitmap... data) {
for (int i = 0; i < data.length; i++) {
Bitmap bitmap = data[i];
String name = String.valueOf(System.currentTimeMillis());
if (bitmap != null) save(name, bitmap);
}
return 1;
}
private void save(String name, Bitmap bitmap) {
File photo = new File(Environment.getExternalStorageDirectory(), name + ".jpg");
if (photo.exists()) photo.delete();
try {
FileOutputStream fos = new FileOutputStream(photo.getPath());
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
} catch (java.io.IOException e) {
Log.e("PictureDemo", "Exception in photoCallback", e);
}
}
}
}
公共类MotionDetectionActivity扩展了SensorsActivity{
私有静态最终字符串标记=“MotionDetectionActivity”;
私有静态SurfaceView预览=null;
私有静态SurfaceHolder previewHolder=null;
专用静态摄像机=空;
私有静态布尔inPreview=false;
私有静态长mrreferencetime=0;
专用静态检测检测器=空;
私有静态volatile AtomicBoolean处理=新的AtomicBoolean(false);
/**
*{@inheritardoc}
*/
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
预览=(SurfaceView)findViewById(R.id.preview);
previewHolder=preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE类型推送缓冲区);
如果(首选项。使用_RGB){
检测器=新的RgbMotionDetection();
}else if(首选项。使用\u LUMA){
检测器=新LumaMotionDetection();
}否则{
//使用基于状态的(聚合映射)
检测器=新的AggregateLumaMotionDetection();
}
}
/**
*{@inheritardoc}
*/
@凌驾
公共无效OnConfiguration已更改(配置newConfig){
super.onConfigurationChanged(newConfig);
}
/**
*{@inheritardoc}
*/
@凌驾
公共无效暂停(){
super.onPause();
camera.setPreviewCallback(空);
if(inPreview)camera.stopPreview();
inPreview=false;
相机。释放();
摄像机=零;
}
/**
*{@inheritardoc}
*/
@凌驾
恢复时公开作废(){
super.onResume();
camera=camera.open();
}
private PreviewCallback PreviewCallback=新建PreviewCallback(){
/**
*{@inheritardoc}
*/
@凌驾
预览帧上的公共无效(字节[]数据,摄像头){
if(data==null)返回;
Camera.Size Size=cam.getParameters().getPreviewSize();
if(size==null)返回;
如果(!GlobalData.isPhoneInMotion()){
DetectionThread线程=新的DetectionThread(数据、大小.宽度、大小.高度);
thread.start();
}
}
};
private SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback(){
/**
*{@inheritardoc}
*/
@凌驾
已创建的公共空白表面(表面持有人){
试一试{
照相机。设置预览显示(预览文件夹);
camera.setPreviewCallback(previewCallback);
}捕获(可丢弃的t){
Log.e(“PreviewDemo surfaceCallback”,“setPreviewDisplay()中的异常”,t);
}
}
/**
*{@inheritardoc}
*/
@凌驾
公共空白表面更改(表面文件夹持有者、整型格式、整型宽度、整型高度){
Camera.Parameters=Camera.getParameters();
Camera.Size Size=getBestPreviewSize(宽度、高度、参数);
如果(大小!=null){
parameters.setPreviewSize(size.width、size.height);
Log.d(标记“Using width=“+size.width+”height=“+size.height”);
}
设置参数(参数);
camera.startPreview();
inPreview=true;
}
/**
*{@inheritardoc}
*/
@凌驾
公共空间表面覆盖(表面覆盖物持有人){
//忽略
}
};
专用静态相机。大小getBestPreviewSize(整数宽度、整数高度、相机。参数){
Camera.Size结果=null;
对于(Camera.Size:parameters.getSupportedPreviewSizes()){
if(size.width(mrreferencetime+Preferences.PICTURE\u延迟)){
mrreferencetime=now;
位图previous=null;
if(Preferences.SAVE_PREVIOUS&&pre!=null){
if(Preferences.usergb)previous=ImageProcessing.rgbToBitmap(pre、width、height);
else previous=图像处理。亮度灰度(预处理、宽度、高度);
}
位图原始=空;
if(Preferences.SAVE_ORIGINAL&&org!=null){
if(Preferences.USE_RGB)original=ImageProcessing.rgbToBitmap(组织、宽度、高度);
else original=ImageProcessing.lumaToGreyscale(组织、宽度、高度);
}
位图=空;
如果(首选项。保存更改){
if(Preferences.USE_RGB)bitmap=ImageProcessing.rgbToBitmap(img,width,height);
else bitmap=ImageProcessing.lumaToGreyscale(img、宽度、高度);
}
Log.i(标记“Saving..previous=“+previous+”original=“+original+”bitmap=“+bitmap”);
Looper.prepare();
新建SavePhotoTask().execute(上一个、原始、位图);
}否则{
Log.i(标记“由于创建曲面后没有足够的时间,所以没有拍照”);
}
}
}捕获(例外e){
e、 printStackTrace();
}最后{
处理。设置(假);
}
//Log.d(标记“结束处理…”);
处理。设置(假);
}
};
私有静态最终类SavePhotoTask扩展了AsyncTask{
/**
*{@inheritardoc}
*/
@凌驾
受保护的整数doInBackground(位图…数据){
对于(int i=0;i<?xml version="1.0" encoding="utf-8"?>
<SurfaceView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</SurfaceView>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:id="@+id/imageView1"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/android" />
</RelativeLayout>
private void addView()
{
controlInflater = LayoutInflater.from(getBaseContext());
View viewControl = controlInflater.inflate(R.layout.overlay, null);
LayoutParams layoutParamsControl = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
this.addContentView(viewControl, layoutParamsControl);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
preview = (SurfaceView) findViewById(R.id.preview);
previewHolder = preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
addView();