정상에서 IT를 외치다

[Android, Camera] 2. 카메라 프리뷰를 이용한 화면 캡처 및 배경 이미지 적용 본문

안드로이드

[Android, Camera] 2. 카메라 프리뷰를 이용한 화면 캡처 및 배경 이미지 적용

Black-Jin 2018. 8. 22. 15:28
반응형

안녕하세요. 블랙진입니다.


Capture the camera preview with image in android


Camera api 를 사용하여 화면을 캡처하고 캡처한 화면에 배경 이미지를  적용하는 방법에 대해 포스팅 해보겠습니다.


현 포스팅은 이전 포스팅의 연장입니다. ~!



저번 포스팅에는 카메라 프리뷰를 안드로이드 기기에 맞게 띄우는 법에 대해 살펴보았습니다.


이번에는 프리뷰 화면을 캡처하는 법에 대해 포스팅 해보겠습니다.




1. 캡처 기능 추가



_activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<FrameLayout
android:id="@+id/cameraPreview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>

<LinearLayout
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">

<Button
android:id="@+id/btnCapture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="캡처" />

</LinearLayout>


</RelativeLayout>

화면 하단에 캡처 버튼을 추가해 줍니다.




_MainAcitivty.kt

btnCapture.setOnClickListener {
myCameraPreview?.takePicture()
}

캡처 버튼에 takePicture() 함수를 적용해 줍니다.




_MyCameraPreview.java

/**
* 이미지 캡처
*/
public void takePicture(){

mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
}

/**
* 이미지 저장을 위한 콜백 함수
*/
private Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback() {
public void onShutter() {

}
};

private Camera.PictureCallback rawCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {

}
};


private Camera.PictureCallback jpegCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {

//이미지의 너비와 높이 결정
int w = camera.getParameters().getPictureSize().width;
int h = camera.getParameters().getPictureSize().height;
int orientation = calculatePreviewOrientation(mCameraInfo, mDisplayOrientation);

//Log.d("MyTag","이미지 캡처 시 -> orientation : " + orientation);

//byte array 를 bitmap 으로 변환
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeByteArray( data, 0, data.length, options);

//이미지를 디바이스 방향으로 회전
Matrix matrix = new Matrix();

/**
* 셀카 모드에는 저장 시 좌우 반전을 해줘야 한다.
*/
if(mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
//Log.d("MyTag","180도 추가 회전 후 좌우반전을 해줍니다.");
//orientation += 180;
matrix.setScale(-1,1);
}

matrix.postRotate(orientation);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);

//bitmap 을 byte array 로 변환
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] currentData = stream.toByteArray();

//파일로 저장
new MyCameraPreview.SaveImageTask().execute(currentData);

}
};

위와 같이 takePicture 와 콜백 함수를 추가해 줍니다.


jpegCallback 함수를 통해 비트맵 이미지를 바이트 변환하여 JPEG 이미지로 정하게 됩니다. 


그 하단에 이어서 SaveImageTask 클래스를 추가해 줍니다.


/**
* 이미지 저장을 위한 콜백 클레스
*/
private class SaveImageTask extends AsyncTask<byte[], Void, Void> {

@Override
protected Void doInBackground(byte[]... data) {
FileOutputStream outStream = null;

try {

File path = new File (Environment.getExternalStorageDirectory().getAbsolutePath() + "/camtest");
if (!path.exists()) {
path.mkdirs();
}

String fileName = String.format("%d.jpg", System.currentTimeMillis());
File outputFile = new File(path, fileName);

outStream = new FileOutputStream(outputFile);
outStream.write(data[0]);
outStream.flush();
outStream.close();

Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length + " to "
+ outputFile.getAbsolutePath());


mCamera.startPreview();


// 갤러리에 반영
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(Uri.fromFile(outputFile));
getContext().sendBroadcast(mediaScanIntent);


try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
Log.d(TAG, "Camera preview started.");
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}


} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

return null;
}

}

위 클래스는 AsyncTask 로 동작합니다. 


Environment.getExternalStorageDirectory().getAbsolutePath() + "/camtest"

위는 갤러리에 저장될 파일 경로 입니다. camtest 라는 폴더가 생성되어 그 안에 사진이 차곡 차곡 저장됩니다.

저장 폴더의 이름을 변경하고 싶으시면 camtest 명을 변경하시면 됩니다.


 String fileName = String.format("%d.jpg", System.currentTimeMillis());

위는 camtest 폴더에 저장되는 파일명입니다. 파일 타입은 jpg 이고 파일 명은 중복되면 안되기 때문에 시스템 시간으로 설정하였습니다.


이렇게 하면 매 사진을 찍을 때마다 시스템 시간이 다르기 때문에 파일명이 겹칠 일이 없습니다.




아래는 MyCameraPreview.java 전체 코드 입니다.



짠! 이걸로 캡처 버튼을 누르시면 camTest 폴더에 이미지가 차곡차곡 저장되는 것을 확인하실 수 있을 겁니다.~!~!


다음 포스터는 캡처된 이미지에 배경을 넣는 방법을 포스팅 해보겠습니다.


< 참고 사이트 >


구글 문서

카메라 캡처

카메라 방향 설정


반응형
Comments