Android: Overlay on Android Camera Preview

后端 未结 6 560
后悔当初
后悔当初 2020-11-27 13:32

I\'m using Camera API and invoking the camera.

I want to display a header (for branding) on the top of the camera preview. The header is a jpeg image.

Is

相关标签:
6条回答
  • 2020-11-27 13:47

    look your XML would be like this:

     <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent" >
    
    <android.view.SurfaceView
     android:id="@+id/surface"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent" />
    
    <ImageView
    android:id = "@+id/header"
    android:layout_width = "wrap_content"
    android:layout_height = "wrap_content" />
    
    </FrameLayout>
    

    and for the java code you should extend SurfaceHolder.Callback in your activity and then attach the camera to the surface view like this,its my full code please be careful with bitmaps and canvas that is the tricky part :

     public class MainActivity extends Activity implements SurfaceHolder.Callback 
    {
      private Camera camera = null;
      private SurfaceView cameraSurfaceView = null;
      private SurfaceHolder cameraSurfaceHolder = null;
      private boolean previewing = false;
      RelativeLayout relativeLayout;
    
    
    
    
    
      private Button btnCapture = null;
      private Button btnsave = null;
      private Button btnshare = null;
      private boolean isSaved=false;
      private boolean isCaptured=false;
    
      @Override
      protected void onCreate(Bundle savedInstanceState) 
      {
        super.onCreate(savedInstanceState);
    
        getWindow().setFormat(PixelFormat.TRANSLUCENT);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(
                             WindowManager.LayoutParams.FLAG_FULLSCREEN,
                             WindowManager.LayoutParams.FLAG_FULLSCREEN);
    
        setContentView(R.layout.activity_main);
    
        relativeLayout=(RelativeLayout) findViewById(R.id.containerImg);
        relativeLayout.setDrawingCacheEnabled(true);
        cameraSurfaceView = (SurfaceView)
                                           findViewById(R.id.surfaceView1);
      //  cameraSurfaceView.setLayoutParams(new FrameLayout.LayoutParams(640, 480));
        cameraSurfaceHolder = cameraSurfaceView.getHolder();
        cameraSurfaceHolder.addCallback(this);
    //    cameraSurfaceHolder.setType(SurfaceHolder.
      //                                               SURFACE_TYPE_PUSH_BUFFERS);
    
    
    
    
        btnCapture = (Button)findViewById(R.id.capturebtn);
        btnCapture.setOnClickListener(new OnClickListener() 
        {   
          @Override
          public void onClick(View v) 
          {
             camera.takePicture(cameraShutterCallback, 
                                           cameraPictureCallbackRaw,
                                           cameraPictureCallbackJpeg);
             isCaptured=true;
          }
        });
        btnsave = (Button)findViewById(R.id.savebtn);
        btnsave.setOnClickListener(new OnClickListener() {
    
            @Override
            public void onClick(View v) {
                 FrameLayout frm = (FrameLayout)findViewById(R.id.frameLayout1);
                    frm.setDrawingCacheEnabled(true);
                    frm.buildDrawingCache();
                    Bitmap bitmap = frm.getDrawingCache();
                    try {
                        File rootFile=new File(Environment.getExternalStorageDirectory().toString()+"/MYCAMERAOVERLAY");
                        rootFile.mkdirs();
                        Random generator = new Random();
                        int n = 10000;
                        n = generator.nextInt(n);
                        String fname = "Image-"+ n +".png";
    
                        File resultingfile = new File(rootFile, fname);
    
                        if (resultingfile.exists ()) resultingfile.delete (); 
                        try {
                               FileOutputStream Fout = new FileOutputStream(resultingfile);
                               bitmap.compress(CompressFormat.PNG, 100, Fout);
                               Fout.flush();
                               Fout.close();
    
                        } catch (FileNotFoundException e) {
                            Log.d("In Saving File", e + "");
                    }
                    } catch(IOException e){
                        Log.d("In Saving File", e + "");
                    }
                    isSaved=true;
                }
            });
        btnshare = (Button)findViewById(R.id.sharebtn);
        btnshare.setOnClickListener(new OnClickListener() {
    
            @Override
            public void onClick(View v) {
                if((isSaved)&&(isCaptured)){
                    // TODO sharing what ever we saved 
                    // take the path
    
    
                }
    
            }
        });
       } 
    
    
      ShutterCallback cameraShutterCallback = new ShutterCallback() 
      {  
        @Override
        public void onShutter() 
        {
          // TODO Auto-generated method stub   
        }
      };
    
      PictureCallback cameraPictureCallbackRaw = new PictureCallback() 
      {  
        @Override
        public void onPictureTaken(byte[] data, Camera camera) 
        {
          // TODO Auto-generated method stub   
        }
      };
    
      PictureCallback cameraPictureCallbackJpeg = new PictureCallback() 
      {  
        @Override
        public void onPictureTaken(byte[] data, Camera camera) 
        {
          // TODO Auto-generated method stub   
          Bitmap cameraBitmap = BitmapFactory.decodeByteArray
                                                                      (data, 0, data.length);
    
       int   wid = cameraBitmap.getWidth();
         int  hgt = cameraBitmap.getHeight();
    
        //  Toast.makeText(getApplicationContext(), wid+""+hgt, Toast.LENGTH_SHORT).show();
          Bitmap newImage = Bitmap.createBitmap
                                            (wid, hgt, Bitmap.Config.ARGB_8888);
    
          Canvas canvas = new Canvas(newImage);
    
          canvas.drawBitmap(cameraBitmap, 0f, 0f, null);
    
          camera.startPreview();
    
          newImage.recycle();
          newImage = null;
    
          Intent intent = new Intent();
          intent.setAction(Intent.ACTION_VIEW);
    
          startActivity(intent);
    
        }
      };
    
      @Override
      public void surfaceChanged(SurfaceHolder holder, 
                                           int format, int width, int height) 
      {
        // TODO Auto-generated method stub
    
        if(previewing)
        {
          camera.stopPreview();
          previewing = false;
        }
        try 
        {
          Camera.Parameters parameters = camera.getParameters();
          parameters.setPreviewSize(640, 480);
          parameters.setPictureSize(640, 480);
          if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
              camera.setDisplayOrientation(-90);
    
          }
    
         // parameters.setRotation(90);
          camera.setParameters(parameters);
    
          camera.setPreviewDisplay(cameraSurfaceHolder);
          camera.startPreview();
          previewing = true;
        } 
        catch (IOException e) 
        {
          // TODO Auto-generated catch block
          e.printStackTrace();  
        }
      }
    
      @Override
      public void surfaceCreated(SurfaceHolder holder) 
      {
        // TODO Auto-generated method stub
        try
        {
          camera = Camera.open();
        }
        catch(RuntimeException e)
        {
          Toast.makeText(getApplicationContext(), "Device camera  is not working properly, please try after sometime.", Toast.LENGTH_LONG).show();
        }
      }
    
      @Override
      public void surfaceDestroyed(SurfaceHolder holder) 
      {
        // TODO Auto-generated method stub
          try{
    
    
        camera.stopPreview();
        camera.release();
        camera = null;
        previewing = false;
          }catch(Exception e){
              e.printStackTrace();
          }
      }
    

    }

    and i think now i should give you the full XML part too. so here it is:

      <?xml version="1.0" encoding="utf-8"?>
     <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:android1="http://schemas.android.com/apk/res/android"
    android:id="@+id/containerImg"
    android:layout_width="fill_parent"
    android:layout_height="match_parent"
    android1:layout_gravity="bottom"
    android:orientation="vertical"
    android1:gravity="bottom" >
    
        <FrameLayout
        android:id="@+id/frameLayout1"
        android1:layout_width="wrap_content"
        android1:layout_height="wrap_content"
        android:gravity="center|top"
         >
    
     <SurfaceView
         android1:id="@+id/surfaceView1"
         android1:layout_width="100dip"
         android1:layout_height="150dip"
         android1:layout_gravity="center_horizontal" />
    
    <ImageView
    android1:id="@+id/imageView1"
    android1:layout_width="fill_parent"
    android1:layout_height="fill_parent"
    android:contentDescription="@string/app_dress_desc"
    android:gravity="center|bottom"
    android1:scaleType="center"
    android1:src="@drawable/dress" />
    
    </FrameLayout>
    
    
    <GridLayout
        android1:id="@+id/gridLayout1"
        android1:layout_width="match_parent"
        android1:layout_height="wrap_content"
        android1:layout_alignParentBottom="true"
        android1:layout_alignParentLeft="true"
        android1:columnCount="1"
        android1:gravity="center|bottom"
        android1:orientation="vertical" >
    
        <ImageButton
            android1:id="@+id/capturebtn"
            android1:layout_width="60dp"
            android1:layout_height="wrap_content"
            android1:layout_gravity="left"
            android1:src="@drawable/camera"
            android:contentDescription="@string/app_icon_camera_desc" />
    
        <ImageButton
            android1:id="@+id/savebtn"
            android1:layout_width="60dp"
            android1:layout_height="wrap_content"
            android1:layout_column="0"
            android1:layout_gravity="center_horizontal|top"
            android1:layout_row="0"
            android1:src="@drawable/save"
            android:contentDescription="@string/app_icon_save_desc" />
    
        <ImageButton
            android1:id="@+id/sharebtn"
            android1:layout_width="60dp"
            android1:layout_height="wrap_content"
            android1:layout_column="0"
            android1:layout_gravity="right|top"
            android1:layout_row="0"
            android1:src="@drawable/share"
            android:contentDescription="@string/app_icon_share_desc" />
    </GridLayout>
    

    share button doesn't work at this point but it saves the whole frame layout on capture clicked. hope it will be helpful.

    0 讨论(0)
  • 2020-11-27 13:48

    You can do that with the help of FrameLayout like this:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent" >
    
      <android.view.SurfaceView
      android:id="@+id/surface"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent" />
    
    <ImageView
        android:id = "@+id/header"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content" />
    
    </FrameLayout>
    

    This camera project will help you.

    0 讨论(0)
  • 2020-11-27 14:05

    You can use SurfaceView and create a CustomView that will open the camera and you can adjust its size in the xml accordingly. Below is a pseudo code.

    Create a class that extends SurfaceView and open camera inside that

    CapturePreview.java

    public class CapturePreview extends SurfaceView implements SurfaceHolder.Callback{
    
        public static Bitmap mBitmap;
        SurfaceHolder holder;
        static Camera mCamera;
    
        public CapturePreview(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            holder = getHolder();
            holder.addCallback(this);
            holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
    
            Camera.Parameters parameters = mCamera.getParameters();
            parameters.getSupportedPreviewSizes();
            mCamera.setParameters(parameters);
            mCamera.startPreview();
        }
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
    
            try {
                mCamera = Camera.open();
                mCamera.setPreviewDisplay(holder);
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            mCamera.stopPreview();
            mCamera.release();
        }
        /***
         * 
         *  Take a picture and and convert it from bytes[] to Bitmap.
         *  
         */
        public static void takeAPicture(){  
    
            Camera.PictureCallback mPictureCallback = new PictureCallback() {
                @Override
                public void onPictureTaken(byte[] data, Camera camera) {
    
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
                }
            };
            mCamera.takePicture(null, null, mPictureCallback);
        }
    }
    

    Now you have to include the view that you created using SurfaceView in your xml like this

    main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent">
    
      <FrameLayout 
      android:id="@+id/mySurfaceView"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content">
    
      <com.cam.CapturePreview 
      android:layout_width="fill_parent"
      android:layout_height="wrap_content">
      </com.cam.CapturePreview>
    
      </FrameLayout>
    
      <LinearLayout 
      android:layout_below="@id/mySurfaceView" 
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:layout_centerInParent="true"
      android:gravity="center">
    
      <ImageView android:id="@+id/myImageView" 
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/icon"/>
      </LinearLayout>  
    
    </RelativeLayout>
    

    Now you can use this main.xml in any Acitivty that will open a camera with a ImageView. Thanks....

    0 讨论(0)
  • 2020-11-27 14:06

    You will have to handle the whole camera preview and taking picture yourself. Take a look at the Samples at samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview. You can have your own layout over the preview area and add your graphic to it.

    Sample link

    https://developer.android.com/training/camera/cameradirect#java

    0 讨论(0)
  • 2020-11-27 14:10

    I'm afraid you have to implement camera preview screen yourself. In theory an overlay can be added to other application by modifying its layout or by creating an overlay window. The first way is impossible to implement and the second way can be implemented I think but it's kind of a hack and a error prone method.

    Implementing you own camera activity is not a very difficult task but it's rather challenging. I would recommend you to take a look at the default Camera application. Here's its source code: https://github.com/android/platform_packages_apps_camera.

    0 讨论(0)
  • 2020-11-27 14:10

    A workaround alternative is to overlay the Activity XML file with another XML file which contains the header image. To do so:

    1. Create a new Layout file inside the layout folder. For eg: overlay.xml
    2. Insert an ImageView inside it, something like:

      <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>
      
    3. Then inside the Activity java file, ie MotionDetector.java file , create a new method addView() :

         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);
      
         }
      
    4. Finally invoke the addView() method from onCreate() to add the image:

      protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.header);
      addView();
      

    Then end result would be an image overlay above the SurfaceView. Subject to the quality of the header image, the rendered quality of the header shall seem original. Hope it helps.

    0 讨论(0)
提交回复
热议问题