如何在 Android 中的相机捕获图像上设置实时帧

Posted

技术标签:

【中文标题】如何在 Android 中的相机捕获图像上设置实时帧【英文标题】:How to set Live Frame on Camera Capturing Image in Android 【发布时间】:2016-07-26 10:48:13 【问题描述】:

我必须像上图那样在相机上设置实时帧。但是我的setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);getWidth();getHeight();Camera.PictureCallback等已被弃用。有人知道实现上述的代码吗?

我用过

public class CameraOverview1 extends Activity implements SurfaceHolder.Callback
private Camera camera = null;
private SurfaceView cameraSurfaceView = null;
private SurfaceHolder cameraSurfaceHolder = null;
private boolean previewing = false;
private Display display = null;
private static int wid = 0, hgt = 0;
private LayoutInflater layoutInflater = null;
private View cameraViewControl = null;
private LayoutParams layoutParamsControl = null;
private Button btnCapture = null;
@Override
protected void onCreate(Bundle savedInstanceState) 

// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

display = getWindowManager().getDefaultDisplay(); 
wid = display.getWidth();
hgt = display.getHeight();

getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

setContentView(R.layout.cameraoverlay1);

cameraSurfaceView = (SurfaceView)findViewById(R.id.cameraSurfaceView);
cameraSurfaceHolder = cameraSurfaceView.getHolder();
cameraSurfaceHolder.addCallback(this);
cameraSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

layoutInflater = LayoutInflater.from(getBaseContext());
layoutParamsControl = new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT);

cameraViewControl = layoutInflater.inflate(R.layout.cambutton, null);     
this.addContentView(cameraViewControl, layoutParamsControl);
btnCapture = (Button)findViewById(R.id.btnCapture);
btnCapture.setOnClickListener(new OnClickListener() 
   
    @Override
    public void onClick(View v) 
    
        // TODO Auto-generated method stub
        camera.takePicture(cameraShutterCallback, 
                cameraPictureCallbackRaw,
                cameraPictureCallbackJpeg);
    
);
 
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);

    wid = cameraBitmap.getWidth();
    hgt = cameraBitmap.getHeight();

    Bitmap newImage = Bitmap.createBitmap(wid, hgt, Bitmap.Config.ARGB_8888);

    Canvas canvas = new Canvas(newImage);

    canvas.drawBitmap(cameraBitmap, 0f, 0f, null);

    Drawable drawable = getResources().getDrawable
            (R.drawable.frame1);
    drawable.setBounds(0, 0, wid, hgt);
    drawable.draw(canvas);

    File storagePath = new File(Environment.
            getExternalStorageDirectory() + "/MyCameraApp/"); 
    storagePath.mkdirs(); 

    File myImage = new File(storagePath,
            Long.toString(System.currentTimeMillis()) + ".jpg");

    try
    
        FileOutputStream out = new FileOutputStream(myImage);
        newImage.compress(Bitmap.CompressFormat.JPEG, 80, out);


        out.flush();
        out.close();
    
    catch(FileNotFoundException e)
    
        Log.d("In Saving File", e + "");    
    
    catch(IOException e)
    
        Log.d("In Saving File", e + "");
    

    camera.startPreview();

    drawable = null;

    newImage.recycle();
    newImage = null;

    cameraBitmap.recycle();
    cameraBitmap = null;

;
@Override
public void surfaceChanged(SurfaceHolder holder, 
    int format, int width, int height)

// TODO Auto-generated method stub

if(previewing)

    camera.stopPreview();
    previewing = false;

if (camera != null)
    try 
    
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
camera.stopPreview();
camera.release();
camera = null;
previewing = false;

实际上,几乎所有内容都已弃用。有什么想法吗?

【问题讨论】:

你是说FPS还是总帧数? 我正在构建一个像囤积相框这样的应用程序。看上图。 所以你需要双预览前后摄像头?.. 猜猜看。你知道代码(或任何网站链接)吗? 【参考方案1】:

基于此示例android-Camera2Basic

我已经应用了一些更改,结果如下:

Camera2BasicFragmentFront.java

Source

Camera2BasicFragment.java

Source

AutoFitTextureView.java

Source

fragment_camera2_basic.xml(确保替换 com.YourPackage.AutoFitTextureView)

<?xml version="1.0" encoding="utf-8"?><!--
 Copyright 2014 The Android Open Source Project
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
     http://www.apache.org/licenses/LICENSE-2.0
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_>

    <com.YourPackage.AutoFitTextureView
        android:id="@+id/texture"
        android:layout_
        android:layout_
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true" />

</RelativeLayout>

activity_main.xml

<RelativeLayout android:layout_
    android:layout_
    xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_
    android:layout_ >
</FrameLayout>
<FrameLayout
android:id="@+id/containerFront"
android:layout_
android:layout_ />
</RelativeLayout>

比在 MainActivity.java 中:

public class MainActivity extends AppCompatActivity
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (null == savedInstanceState) 
            getFragmentManager().beginTransaction()
                    .replace(R.id.container, Camera2BasicFragment.newInstance())
                    .commit();
            getFragmentManager().beginTransaction()
                    .replace(R.id.containerFront, Camera2BasicFragmentFront.newInstance())
                    .commit();
        
    

并将此权限用于Manifest.xml

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

这就是享受!

附言 Java 类还包含保存照片的方法!

【讨论】:

你能给我完整的源代码吗?我只是一个初学者

以上是关于如何在 Android 中的相机捕获图像上设置实时帧的主要内容,如果未能解决你的问题,请参考以下文章

从android中的画廊和相机中捕获图像

检测实时android相机预览的颜色代码

为啥使用相机意图捕获的图像会在 Android 上的某些设备上旋转?

如何使用相机设置捕获的图像以适合固定高度和宽度的 Imageview

Android自动裁剪相机捕获的图像

如何在android中使用相机捕获自定义图像大小?