Androidでカメラを操作する

携帯電話でカメラを操作することは、常に私にとって興味深いことです。 すべての仕組み...そして、Android'omを搭載した携帯電話を手に入れました。 私はそれを理解しようとして失敗しませんでした。 結果は次のとおりです。



写真を撮ることができる小さなプログラムを考えてください。



すべての操作は、 Cameraクラスを使用して実行されます。

変数を取得する必要があります

Camera camera;
      
      





彼女を初期化する

 camera = Camera.open();
      
      





カメラでの作業が終了したら、次のことを行う必要があります

 camera.release();
      
      





そうしないと、カメラはロックされたままになり、他のアプリケーションからアクセスできなくなります。



カメラなどの通常のアプリケーションでは、初期化はonResumeで行い、リリースはonPauseで行うのが最適です



カメラを使用する際の前提条件は、プレビューウィンドウ(プレビュー)を作成することです。 このウィンドウはSurfaceクラスのオブジェクトである必要があり、 SurfaceViewは画面での表示に適しています。

発表します

 SurfaceView preview;
      
      





プレビューを設定するには、パラメーターがSurfaceHolderクラスのオブジェクトであるsetPreviewDisplayメソッドを呼び出す必要があります。

 SurfaceHolder surfaceHolder; surfaceHolder = preview.getHolder(); camera.setPreviewDisplay(surfaceHolder);
      
      





プレビュー表示を有効にするには、

 camera.startPreview();
      
      





これが行われない場合、カメラは写真を撮ることができません。



実際に、写真を撮るには、メソッドを呼び出す必要があります

 void takePicture(Camera.ShutterCalback shutter, Camera.PictureCallback raw, Camera.PictureCallback postview, Camera.PictureCallback jpg);
      
      





パラメーターを使用して(ところで、それらのいずれかがnullになる可能性があります)、さまざまなイベントのハンドラーが設定されます。



takePicture呼び出しは、ボタンのonClickハンドラーに直接配置できます。この場合、クリックするとすぐに撮影が行われますが、予備のオートフォーカスを使用することもできます。

この場合、メソッドを実装する必要があるCamera.AutoFocusCallbackハンドラーが設定されます

 public void onAutoFocus(boolean paramBoolean, Camera paramCamera);
      
      





次に、ハンドラーでcamera.autoFocus()ボタンを呼び出した後、ハンドラーが1回呼び出されます。このハンドラーでは、フォーカスの成功と写真撮影の必要性について既に決定しています。



SurfaceHolderSurfaceHolderで動作するように設定できます。

surfaceHolder.addCallback();







この場合、メソッドを実装する必要があります

 public void surfaceCreated(SurfaceHolder holder); public void surfaceChanged(SurfaceHolder holder, int format, int width, int height); public void surfaceDestroyed(SurfaceHolder holder);
      
      





それらを使用して、アプリケーションは、変更された場合または削除された場合にSurfaceが正常に作成されたことを通知されます。



プレビューのサイズは、プログラムの実行中に変更できます。

 LayoutParams lp = preview.getLayoutParams(); lp.width =  ; lp.height =  ; preview.setLayoutParams(lp);
      
      





カメラアプリケーションの場合、画面の場所をすぐに設定するのが最も便利です

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);





それ以外の場合、たとえばsurfaceCreatedで画面の場所を確認し、たとえばcamera.setDisplayOrientation(0)



を使用してプレビューを回転する必要があります。

画面を回転させるのに時間がかかるため、これはあまり便利ではありません。 この時点で、onPauseとonResumeが呼び出され、Surfaceが再作成されます。



Camera.PreviewCallbackハンドラーを宣言することもできます。これを介してメソッドを実装します

 void onPreviewFrame(byte[] paramArrayOfByte, Camera paramCamera);
      
      





プレビューに表示される各フレームを受信して​​処理できます。



そして最後の重要なポイント。 ほとんどの場合、SurfaceViewのアスペクト比はカメラのプレビューのアスペクト比と異なることが判明しています。 したがって、画面上の画像の歪みを回避するために、表示されるプレビューウィンドウのサイズを調整する必要があります。



私はほとんど忘れていました。 マニフェストに許可を追加する必要があります

 <uses-permission android:name="android.permission.CAMERA" />
      
      







MainScreen.java

 package test.camera; import android.app.Activity; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.os.Bundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.ViewGroup.LayoutParams; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.view.View; import android.hardware.Camera; import android.hardware.Camera.Size; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; public class MainScreen extends Activity implements SurfaceHolder.Callback, View.OnClickListener, Camera.PictureCallback, Camera.PreviewCallback, Camera.AutoFocusCallback { private Camera camera; private SurfaceHolder surfaceHolder; private SurfaceView preview; private Button shotBtn; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //  ,       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); //  ,     getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); //    requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main); //  SurfaceView   SurfaceView01 preview = (SurfaceView) findViewById(R.id.SurfaceView01); surfaceHolder = preview.getHolder(); surfaceHolder.addCallback(this); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); //    Button01 shotBtn = (Button) findViewById(R.id.Button01); shotBtn.setText("Shot"); shotBtn.setOnClickListener(this); } @Override protected void onResume() { super.onResume(); camera = Camera.open(); } @Override protected void onPause() { super.onPause(); if (camera != null) { camera.setPreviewCallback(null); camera.stopPreview(); camera.release(); camera = null; } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceCreated(SurfaceHolder holder) { try { camera.setPreviewDisplay(holder); camera.setPreviewCallback(this); } catch (IOException e) { e.printStackTrace(); } Size previewSize = camera.getParameters().getPreviewSize(); float aspect = (float) previewSize.width / previewSize.height; int previewSurfaceWidth = preview.getWidth(); int previewSurfaceHeight = preview.getHeight(); LayoutParams lp = preview.getLayoutParams(); //     preview,     if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) { //   camera.setDisplayOrientation(90); lp.height = previewSurfaceHeight; lp.width = (int) (previewSurfaceHeight / aspect); ; } else { //  camera.setDisplayOrientation(0); lp.width = previewSurfaceWidth; lp.height = (int) (previewSurfaceWidth / aspect); } preview.setLayoutParams(lp); camera.startPreview(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { } @Override public void onClick(View v) { if (v == shotBtn) { //      //     //camera.takePicture(null, null, null, this); camera.autoFocus(this); } } @Override public void onPictureTaken(byte[] paramArrayOfByte, Camera paramCamera) { //   jpg   /sdcard/CameraExample/ //   - System.currentTimeMillis() try { File saveDir = new File("/sdcard/CameraExample/"); if (!saveDir.exists()) { saveDir.mkdirs(); } FileOutputStream os = new FileOutputStream(String.format("/sdcard/CameraExample/%d.jpg", System.currentTimeMillis())); os.write(paramArrayOfByte); os.close(); } catch (Exception e) { } //  ,   ,   .    paramCamera.startPreview(); } @Override public void onAutoFocus(boolean paramBoolean, Camera paramCamera) { if (paramBoolean) { //   ,   paramCamera.takePicture(null, null, null, this); } } @Override public void onPreviewFrame(byte[] paramArrayOfByte, Camera paramCamera) { //    ,   preview } }
      
      







main.xml

 <?xml version="1.0" encoding="utf-8"?> <FrameLayout android:id="@+id/FrameLayout01" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <SurfaceView android:id="@+id/SurfaceView01" android:layout_width="wrap_content" android:layout_height="wrap_content"> </SurfaceView> <Button android:text="@+id/Button01" android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content"> </Button> </FrameLayout>
      
      







AndroidManifest.xml

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="test.camera" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true"> <activity android:name=".MainScreen" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> </manifest>
      
      







プログラムは、電話LG Optimus One P500でデバッグおよびテストされました。



執筆時には、次の情報源が使用されました。



  1. developer.android.com/reference/android/hardware/Camera.html
  2. ショーンヴァンエブリィ。 Pro Android Media:スマートフォンとタブレット向けのグラフィックス、音楽、ビデオ、リッチメディアアプリの開発。 Apress 2009。
  3. developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.html




リンクからプロジェクトをダウンロードできます: ここで 再読み込みzalil.ru/30377379



All Articles