簡體   English   中英

Android:在Android Camera Preview上疊加

[英]Android: Overlay on Android Camera Preview

我正在使用Camera API並調用相機。

我想在相機預覽的頂部顯示標題(用於品牌)。 標頭是jpeg圖片。

可能嗎? 任何幫助表示贊賞。

提前致謝。

我的代碼如下。

public class CameraActivity extends Activity {
    @Override
    protected void onPause() {

        super.onPause();
    }

    private static final int CAMERA_PIC_REQUEST = 2500;
    private Bitmap image2;
    private Bitmap bm;
    public static String imagepath;
    public static int x=1;
    private RdmsDbAdapter dbHelper;
    @Override



    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.header);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        //caling new incident
        if(IncidentFormActivity.incident_id == null || IncidentFormActivity.isDisable==true){
            //DBAdapter instance created and connection opened. 
            dbHelper = new RdmsDbAdapter(CameraActivity.this);
            dbHelper.open();

            //setting up flags
            NewIncidentHelper nih = new NewIncidentHelper();
            nih.setUpNewIncident();

            //setting up incident_id
            String Date= IncidentIdGenerator.getDate();
            String Time = IncidentIdGenerator.getTime();

            IncidentFormActivity.incident_id = IncidentIdGenerator.now("ddMMyyyyHHmmss");
            dbHelper.executeSQL("insert into incident values ('" + IncidentFormActivity.incident_id
                    + "', ' ', ' ', ' ', ' ', '"+Date+"', '0','0','0','0','0','0','0','0','0','"+Time+"')");
            dbHelper.close();
        }

        //calling camera
        Intent cameraIntent = new Intent(
                android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);


    }
    public String getPath(Uri uri) {
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(uri, projection, null, null, null);
        int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }

    //back key on phone pressed
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
        case KeyEvent.KEYCODE_BACK:
            Intent i= new Intent(CameraActivity.this, IncidentFormActivity.class);
            startActivity(i);
            this.finish();

            break;

        default:
            break;
        }
        return super.onKeyDown(keyCode, event);
    }

    //handle response came from camera when the picture is taken.
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == CAMERA_PIC_REQUEST && resultCode == RESULT_OK) {
                final ImageView img = new ImageView(this);
                img.setLayoutParams(new LayoutParams(100, 100));
                image2 = (Bitmap) data.getExtras().get("data");
                img.setImageBitmap(image2);
                String incident_ID = IncidentFormActivity.incident_id;
                //l2.addView(img);
                    imagepath="/sdcard/RDMS/"+incident_ID+ x + ".png";
                File file = new File(imagepath);
                try {
                     bm = Bitmap.createScaledBitmap( image2,400, 300, true);
                    file.createNewFile();
                    FileOutputStream ostream = new FileOutputStream(file);
                    bm.compress(CompressFormat.PNG, 90, ostream);
                    ostream.close(); 
                    //Initialising db class and inserting values
                    dbHelper = new RdmsDbAdapter(CameraActivity.this);
                    dbHelper.open();
                    dbHelper.executeSQL("insert into files values ('"+imagepath+"', '"+IncidentFormActivity.incident_id+"')");
                    dbHelper.close();

                } catch (Exception e) {
                    e.printStackTrace();
                    Toast.makeText(getApplicationContext(),"yourfirst  error message is "
                                            + e.toString(), 1000).show();
                }
                x++;
                final AlertDialog.Builder alert = new AlertDialog.Builder(
                        CameraActivity.this);

                alert.setTitle(getString(R.string.anotherimage));
                alert.setCancelable(false);
                //alert.setMessage("Play or Delete the Video selected");
                //alert.setIcon(R.drawable.vid_red);
                alert.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        Intent sendingpage = new Intent(CameraActivity.this, CameraActivity.class);
                          startActivity(sendingpage);

                    }
                });
                alert.setNegativeButton(getString(R.string.no),
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                Intent callback = new Intent (CameraActivity.this, IncidentFormActivity.class);
                                startActivity(callback);
                            }
                        });

                alert.show();


            }
            if(resultCode==RESULT_CANCELED)
            {

                AlertDialog.Builder builder = new AlertDialog.Builder(CameraActivity.this);

                builder.setMessage(getString(R.string.areuexit)).setCancelable(
                        false).setPositiveButton(getString(R.string.yes),
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                Intent i= new Intent(CameraActivity.this, IncidentFormActivity.class);
                                startActivity(i);
                                CameraActivity.this.finish();
                            }
                        }).setNegativeButton(getString(R.string.no),
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                dialog.cancel();
                                Intent i= new Intent(CameraActivity.this, CameraActivity.class);                            startActivity(i);
                                CameraActivity.this.finish();
                            }
                        });

                builder.show();



            }
        }
    }

您可以使用SurfaceView並創建一個CustomView,它將打開相機,並可以相應地在xml中調整其大小。 下面是一個偽代碼。

創建一個擴展SurfaceView的類並在其中打開相機

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);
    }
}

現在,您必須像這樣在XML中包含使用SurfaceView創建的視圖

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>

現在,您可以在將使用ImageView打開相機的任何Acitivty中使用main.xml。 謝謝....

您將必須處理整個相機預覽並自己拍照。 samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview 您可以在預覽區域上擁有自己的布局,然后將圖形添加到其中。

樣本鏈接

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

您可以像這樣在FrameLayout的幫助下完成此操作:

<?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>

相機項目將為您提供幫助。

您的XML看起來像這樣:

 <?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>

對於Java代碼,您應該在您的活動中擴展SurfaceHolder.Callback,然后將相機像這樣連接到曲面視圖,它的完整代碼請謹慎使用位圖和畫布,這是棘手的部分:

 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();
      }
  }

}

我想現在我也應該給您完整的XML部分。 所以這里是:

  <?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>

共享按鈕目前不起作用,但是會保存整個框架布局(單擊捕獲時)。 希望對您有所幫助。

一種解決方法是將活動XML文件與另一個包含標題圖像的XML文件重疊。 為此:

  1. 在布局文件夾中創建一個新的布局文件。 例如: overlay.xml
  2. 在其中插入一個ImageView ,類似:

     <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. 然后在Activity java文件(即MotionDetector.java文件)中,創建一個新方法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. 最后,從onCreate()調用addView()方法添加圖像:

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

然后最終結果將是在SurfaceView上方覆蓋圖像。 視標頭圖像的質量而定,標頭的渲染質量應看起來像是原始的。 希望能幫助到你。

恐怕您必須自己實現相機預覽屏幕。 從理論上講,可以通過修改其布局或通過創建覆蓋窗口將覆蓋添加到其他應用程序。 我認為第一種方法是無法實現的,第二種方法可以實現,但這是一種破解和易於出錯的方法。

實現您自己的相機活動並不是一項艱巨的任務,但是卻充滿了挑戰。 我建議您看一下默認的相機應用程序。 這是其源代碼: https : //github.com/android/platform_packages_apps_camera

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM