2022年3月20日 星期日

Android Studio - 相機拍照程式(Camera Take Photo Program)(七十)

Android Studio - 相機拍照程式(Camera Take Photo Program)(七十):

上次已經編寫了一個非常簡單的相機程式(Simple Camera Program),當然相機除了預覽(Preview)外,還可以做出不同的功能,拍照是其中不可缺少的功能,拍照後還可以作後期的處理,如測距、人面檢測、文字辨測或 QR 掃描等等,所以是很實用程式,需要研究怎樣編寫相機拍照程式(Camera Take Photo Program)。

Android Studio - 相機拍照程式(Camera Take Photo Program)(七十):
  • 操作系統:Windows 7 64-bit 版本
  • 開發環境:Android Studio 4.0.1 版本
  • 原程式:C:\Development\Development_Android\Android_Project\DIY-Android-091-11b Camera Takephoto
  • 程式:C:\Development\Development_Android\Android_Project\DIY-Android-091-11b Camera Takephoto
  • 測試環境:Vivo(維沃)X5Max Android 4.4.4(KitKat)版本

簡單相機程式(Simple Camera Program)編程步驟:
  • 設定 Camera 許可權限後 - AndroidManifest.xml
  • 設定 SurfaceView 參數 - init_View()
  • 啟動 SurfaceView Callback - mSurfaceHolder.addCallback(this);
  • 打開 Camera - Camera.open()
  • 設置 Camera 參數 - setParameters()
  • StartPreview Camera 顯示 - setPreviewDisplay(surfaceHolder) → startPreview()
  • 設置 Button Takephoto 參數
  • 截取 Camera 圖像 - takePhotoViaCamera()
  • 儲存相片 - SaveImage()

AndroidManifest.xml 獲取 Camera 許可權:

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

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

 

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


activity_camera_takephoto.xml:

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout

    xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent">

 

    <SurfaceView

        android:id="@+id/activity_camera_surface"

        android:layout_width="match_parent"

        android:layout_height="match_parent" />

 

    <Button

        android:id="@+id/btn_camera_photo"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_marginTop="200dp"

        android:text="Take Photo"

        app:layout_constraintEnd_toEndOf="parent"

        app:layout_constraintStart_toStartOf="parent"

        app:layout_constraintTop_toTopOf="parent" />

 

</androidx.constraintlayout.widget.ConstraintLayout>


CameraTakePhoto.java:

package bugworkshop.blogspot.com.camera;

 

import androidx.annotation.NonNull;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

 

// Camera

import android.hardware.Camera;

 

// SurfaceView

import android.view.SurfaceHolder;

import android.view.SurfaceView;

import android.view.View;

import android.widget.Button;

 

// Takephoto

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import java.io.ByteArrayOutputStream;

import android.graphics.Matrix;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

 

public class CameraTakePhoto extends AppCompatActivity implements SurfaceHolder.Callback{

 

    private Button mbtn_camera_photo;

 

    // Camera

    private Camera mCamera;

 

    // SurfaceView

    private SurfaceView mSurfaceView;

    private SurfaceHolder mSurfaceHolder;

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_camera_takephoto);

 

        mbtn_camera_photo = (Button)findViewById(R.id.btn_camera_photo);

 

        mbtn_camera_photo.setOnClickListener(new View.OnClickListener()

        {

            @Override

            public void onClick(View v) {

                takePhotoViaCamera();

            }

        });

 

        init_View();

    }

 

    public void init_View() {

        mSurfaceView = (SurfaceView)findViewById(R.id.activity_camera_surface);

        mSurfaceHolder = mSurfaceView.getHolder();

        mSurfaceHolder.addCallback(this);

        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    }

 

    @Override

    public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {

        mCamera = Camera.open();

        if (mCamera != null) {

            Camera.Parameters p = mCamera.getParameters();

            p.setPreviewSize(640, 480);

            p.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);

            mCamera.setParameters(p);

        }

 

        try {

            mCamera.setPreviewDisplay(surfaceHolder);

            mCamera.startPreview();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

 

    @Override

    public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

 

    @Override

    public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {

    }

 

    // Take Photo

    public void takePhotoViaCamera() {

        if (mCamera != null) {

            mCamera.takePicture(new Camera.ShutterCallback() {

                @Override

                public void onShutter() {

                }

            }, new Camera.PictureCallback() {

                @Override

                public void onPictureTaken(byte[] data, Camera camera) {

                }

            }, new Camera.PictureCallback() {

                @Override

                public void onPictureTaken(final byte[] data, Camera camera) {

                    saveImage(data);

                    mCamera.startPreview();

                }

            });

        }

    }

 

    public void saveImage(byte[] data) {

        BitmapFactory.Options options = new BitmapFactory.Options();

        options.inSampleSize = 6;

        options.inDither = false;

        options.inPurgeable = true;

        options.inInputShareable = true;

        options.inTempStorage = new byte[32 * 1024];

        options.inPreferredConfig = Bitmap.Config.RGB_565;

        Bitmap bMap = BitmapFactory.decodeByteArray(data, 0, data.length, options);

 

        int orientation;

        if (bMap.getHeight() < bMap.getWidth()) {

            orientation = 90;

        } else {

            orientation = 0;

        }

 

        Bitmap bMapRotate;

        if (orientation != 0) {

            Matrix matrix = new Matrix();

            matrix.postRotate(orientation);

            bMapRotate = Bitmap.createBitmap(bMap, 0, 0, bMap.getWidth(), bMap.getHeight(), matrix, true);

        } else {

            bMapRotate = Bitmap.createScaledBitmap(bMap, bMap.getWidth(), bMap.getHeight(), true);

        }

        FileOutputStream out;

        try {

            out = new FileOutputStream("/sdcard/PictPreview.png");

            ByteArrayOutputStream stream = new ByteArrayOutputStream();

            bMapRotate.compress(Bitmap.CompressFormat.PNG, 100, stream);

            out.write(stream.toByteArray());

            out.flush();

            if (bMapRotate != null) {

                bMapRotate.recycle();

                bMapRotate = null;

            }

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}


2022年 3月 19日(Sat)天氣報告
氣溫:45.0°F / 7.0°C @ 07:00
風速:每小時 18公里
降雨機會:37%
相對濕度:百分之 94%
天氣:多雲

沒有留言:

張貼留言