Android canvas draw line on camera

ⅰ亾dé卋堺 提交于 2020-01-16 00:38:15

问题


I'm working with augmented reality app and I want to draw a line that connects two movable objects on top of the camera. However I get this exception

Process: test.job.reality.augument.job.com.augumentrealitytest, PID: 15056
    java.lang.IllegalArgumentException
    at android.view.Surface.nativeLockCanvas(Native Method)
    at android.view.Surface.lockCanvas(Surface.java:266)
    at custom.MyCameraView$MyThread.run(MyCameraView.java:447)

Here's my code as you can see I start my thread in surfaceCreted method. I'm thinking that I can't lockCanvas because it's a;ready locked by camera, am I right? However I to draw line is it possible (I'm using beyondAR augumented reality library)

public class MyCameraView extends SurfaceView implements SurfaceHolder.Callback, Camera.PictureCallback {
private MyThread thread;

public MyCameraView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

@SuppressWarnings("deprecation")
private void init(Context context) {
    mIsPreviewing = false;
    mHolder = getHolder();
    mHolder.addCallback(this);

    configureCamera();

    if (Build.VERSION.SDK_INT <= 10) {// Android 2.3.x or lower
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    thread=new MyThread(getHolder(),this);
    getHolder().addCallback(this);
    setFocusable(true);
}

 @Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);


}

public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, acquire the camera and tell it where
    // to draw.

    thread.startrun(true);
    thread.start();
    try {

        if (mCamera == null) {
            init(getContext());
            if (mCamera == null) {
                return;
            }
        }

        mCamera.setPreviewDisplay(holder);
    } catch (IOException exception) {
        if (mCamera != null) {
            mCamera.release();
        }
        mCamera = null;
        Logger.e(TAG, "CameraView -- ERROR en SurfaceCreated", exception);
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    releaseCamera();

    thread.startrun(false);
    thread.stop();
}

public class MyThread extends Thread{

    private SurfaceHolder msurfaceHolder;
    private MyCameraView mSurfaceView;
    private boolean mrun =false;

    public MyThread(SurfaceHolder holder, MyCameraView mSurfaceView) {

        this.msurfaceHolder = holder;
        this.mSurfaceView=mSurfaceView;
    }

    public void startrun(boolean run) {

        mrun=run;
    }

    @SuppressLint("WrongCall")
    @Override
    public void run() {

        super.run();
        Canvas canvas;
        while (mrun) {
            canvas=null;
            try {
                canvas = msurfaceHolder.lockCanvas();
                synchronized (msurfaceHolder) {
                    mSurfaceView.onDraw(canvas);
                }
            } finally {
                if (canvas != null) {
                    msurfaceHolder.unlockCanvasAndPost(canvas);
                }
            }
        }
    }
}

回答1:


When a surface is used to display camera preview, you cannot draw on it anymore. You could, in principle, open a separate transparent canvas on top of the preview surface, and draw on that canvas. It may be much easier to switch to OpenGL preview (using SurfaceTexture); then you can use the same OpenGL context for your drawings (but they must be expressed in OpenGL, too). You can find a simple demo project at GitHub to begin with.

But even in this case, there is another problem with your task: even if your CV is very fast, there is no synchornization between your augmentation and the camera frame that goes straight from the sensors to the screen. In the case of OpenGL, there are some simple things that can be done in 0 time (e.g. simple convolution on the received texture). But anything more interesting requires something different.

We usually hide the live preview from the user, get the frames in the onPreviewFrame() callback, process them and draw the frame and whatever additional lines or objects manually. This introduces some delay, but if your algorithms are really efficient, this delay may be negligible.

Again, OpenGL is usually of great help here.




回答2:


Don't lockCanvas and stop thread call & just put the below code in on Draw method. I hope it will work.

protected void onDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    super.onDraw(canvas);

    Paint paint = new Paint();

    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();

    int screenWidth = metrics.widthPixels;
    int screenHeight = metrics.heightPixels;

    screenHeight = (int) (metrics.heightPixels * 0.6290);
    paint.setAntiAlias(true);
    paint.setStrokeWidth(1);
    paint.setStyle(Paint.Style.STROKE);

    paint.setColor(Color.argb(255, 255, 255, 255));

    canvas.drawLine((screenWidth / 4), 0,
            (screenWidth / 4), screenHeight + 500, paint);


    if(screenWidth == 1280 && screenHeight == 473)  // this condition for 10" tab only
    canvas.drawLine((screenWidth / 2f), 0,
                (screenWidth / 2f), screenHeight + 500, paint);

    else
    canvas.drawLine((screenWidth / 2.20f), 0,
            (screenWidth / 2.20f), screenHeight + 500, paint);

    canvas.drawLine(0, (screenHeight / 2.15f) * 2, screenWidth,
            (screenHeight / 2.15f) * 2, paint);

    canvas.drawLine(0, (screenHeight / 2.15f) , screenWidth,
            (screenHeight / 2.15f), paint);
}


来源:https://stackoverflow.com/questions/35341021/android-canvas-draw-line-on-camera

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!