开发者

How do I put graphics on top of my camera preview in Android?

开发者 https://www.devze.com 2023-01-16 03:06 出处:网络
I see a couple of threads on this topic, but none of them seem to answer the question, so, I\'m giving it another go...

I see a couple of threads on this topic, but none of them seem to answer the question, so, I'm giving it another go...

Very simple idea... I want to some portion of the screen to preview (and shoot) the camera and the other portions of the screen to add my own graphical elements (buttons, colorful frame around the camera preview, etc).

The example that comes with Android fills the screen. The obvious solution (that doesn't seem to be working) is to use my own SurfaceView (rather than the one they do in the example) and have it sitting in my XML. The code (beneath) doesn't crash and reports that it's firing up the camera... it just never renders on the screen.

I have no idea what I'm doing incorrectly. My guess is that it has something to do with the display thread never having the urge to redraw anything after it renders the initial screen, but I even tried adding a button and initiating the camera to render on the surface view upon button click, but that has not provoked it any further. (most of this code is pulled directly out of the Android sample code, so, I'm sure it's correct. I'm just doing something wrong in how I pull my View in after the fact, I think).

Any and all help greatly appreciated.

public class TakePhoto extends Activity implements SurfaceHolder.Callback{
    /** Called when the activity is first created. */
    SurfaceHolder mHolder;
    Camera mCamera;


@Override
protected void onCreate(Bundle savedInstanceState) {            
    super.onCreate(savedInstanceState);


    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
    WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(R.layout.take_photo);        

    try{
        SurfaceView sv = (SurfaceView) findViewById(R.id.camera_surface);
        mHolder = sv.getHolder();
        mHolder.addCallback(this);     
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
        toast("added callback");
    }catch(Exception e){
        toast("push: " + e);
    }       
}


public void surfaceCreated(SurfaceHolder holder) {

    mCamera = Camera.open();
    try {

       mCamera.setPreviewDisplay(mHolder);
    } catch (IOException exception) {
        mCamera.release();
        mCamera = null;
        toast("error:" + exception);
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    mCamera.stopPreview();
    mCamera.release();
    mCamera = null;
}


private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.05;
    double targetRatio = (double) w / h;
    if (sizes == null) return null;

    Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    int targetHeight = h;


    for (Size size : sizes) {
        double ratio = (double) size.width / size.height;
        if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
        if (Math.abs(size.height - targetHeight) < minDiff) {
            optimalSize = size;
            minDiff = Math.abs(size.height - targetHeight);
        }
    }


    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}

public void surfaceChanged(SurfaceHolder 开发者_如何学运维holder, int format, int w, int h) {

    Camera.Parameters parameters = mCamera.getParameters();

    List<Size> sizes = parameters.getSupportedPreviewSizes();
    Size optimalSize = getOptimalPreviewSize(sizes, w, h);        

    parameters.setPreviewSize(optimalSize.width, optimalSize.height);        

    mCamera.setParameters(parameters);
    mCamera.startPreview();
}

private void toast(String str){
    Context context = getApplicationContext();       
    int duration = Toast.LENGTH_SHORT;
    Toast toast = Toast.makeText(context, str, duration);
    toast.show();

}

}


Just use use FrameLayout as a parent to your SurfaceView and add all other elements there as well. The way I have a center "target" on a surface view:

<FrameLayout android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:layout_weight="2"
  android:padding="5dip"  
  >
  <com.commonlib.controls.CameraPreview
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:layout_weight="1"
  android:layout_gravity="center"
  android:id="@+id/surface_camera"
  />
  <ImageView android:id="@+id/target"
    android:layout_gravity="center"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/target"
    >
    </ImageView>
</FrameLayout>

Check my question here for CameraPreview class.


You have no class taking the camera preview callback and delivering the camera frames to the surface layer..

see: http://nhenze.net/?p=154

download the eclipse project and take a look at the source..

And remember you can overlay the surfaceview and that is how you will get your buttons, etc rather than attempt putting 2d on surfaceview, etc..

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号