어플리케이션 제작 중에 SurfaceView에 CameraPreview를 이용하여 카메라를 제어하는 프로그래밍 중

실시간으로 SurfaceView를 캡쳐해야하는 코드가 필요해 처리하는 과정 등을 정리하여 포스팅합니다.

SurfaceView는 일반적인 함수로 캡쳐하면 검은 화면만 출력되기 때문에...

여러가지 찾아본 후 적용되는 코드로 설명하곘습니다.

CameraPreview로 SurfaceView에 카메라 화면을 출력할 때, 실시간으로 사진파일이 필요할 때 사용합니다.


[CameraPreview.java]


public class CameraPreview extends ViewGroup implements SurfaceHolder.Callback {

... 중략 ...

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

... 중략 ...

mCamera.setPreviewDisplay(mHolder);

mCamera.setPreviewCallback(new Camera.PreviewCallback(){

@Override

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

// 현재 SurfaceView를 JPEG Format으로 변경

Camera.Parameters parameters = camera.getParameters();

int w = parameters.getPreviewSize().width;

int h = parameters.getPreviewSize().height;

int format = parameters.getPreviewFormat();

YuvImage image = new YuvImage(data, format, w, h, null);

ByteArrayOutputStream out = new ByteArrayOutputStream();

Rect area = new Rect(0, 0, w, h);

image.compressToJpeg(area, 100, out);

Bitmap bm = BitmapFactory.decodeByteArray(out.toByteArray(), 0, out.size());

byte[] currentData = out.toByteArray();         

                   

... 중략 ...

}

}

}


기본 코드입니다.

CameraView class에서 SurfaceHolder.Callback을 implements하고

surfaceChanged() 에서 mCamera.setPreviewCallback을 호출합니다.

onPreviewFrame 메소드는 CameraPreview에서 실시간으로 호출되는 함수입니다.

위 코드는 현재 SurfaceView 화면을 캡쳐해서 JPEG Format으로 만들어주는 코드입니다.


여기서 JPEG 파일을 PNG 파일로 바꾸는 방법입니다.


... 위 코드로 부터 계속 ...

int orientation = calculatePreviewOrientation(mCameraInfo, mDisplayOrientation);

Matrix matrix = new Matrix();

matrix.postRotate(orientation);


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

options.inSampleSize = 1 // 이미지 사이즈 리스케일(2의 지수 승으로 해야 처리속도 빠름; 1,2,4,8,16...; 필요시)

options.inPreferredConfig = Bitmap.Config.ARGB_8888;

// RGB_565 : 16bit Bitmap, ARGB_8888 : 32bit Bitmap, 4444는 저품질이라 추천안함


Bitmap bitmap = BitmapFactory.decodeByteArray(currentData, 0, currentData.length, options);

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

// bitmap src, start x, start y, width, height, 회전, Flag


 // Bitmap 이미지를 surfaceView 좌표로 변환

bitmap = GetBinaryBitmap(bitmap); // bitmap 이진화 처리


//bitmap을 byte array로 변환

 ByteArrayOutputStream stream = new ByteArrayOutputStream();

bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); // 100 수치 변경해서 품질(Quality) 변경

currentData = stream.toByteArray();


// 이후 해당 Byte Array로 파일 저장 및 처리...

... 중략 ....

}

}

}


조금 복잡할 수도 있는 코드입니다.

한줄씩 주석 포함해서 해석하면서 코드 작성하시면 쉽게 처리 가능할 것 같습니다.


PNG(Bitmap으로) 파일 저장하는 방법은 Google에 많이 있고 또 예제코드가 있기 때문에 생략하겠습니다.


이상 CameraPreview에서 카메라 화면을 SurfaceView에 출력하고 그 화면을 캡쳐하는 방법에 대해 알아보았습니다.

질문 사항은 댓글로 남겨주세요!!


* 참고 글 : 

SurfaceView CameraPreview 연동

Bitmap 이진화 처리



안드로이드 프로그래밍에서 특수키 제어하는 방법입니다.

특수키란 키보드로 입력하는 키 외에 뒤로가기, 홈버튼, 볼륨버튼.. 등을 말합니다.

먼저 실행 될 activity에서 우클릭 - Generate를 눌러줍니다.



생성자, getter, setter...등 목록이 많이 있습니다.

이 중에 Override Methods를 선택합니다.



OnKeyDown이라고 검색해봅시다.(창이 뜬 상태에서 그냥 치면 검색됩니다.)

없는 경우 이미 메소드를 생성한 경우입니다.



OK버튼을 누르면 아래와 같은 코드가 생깁니다.

@Override라는 문구가 싫으신 분은 Insert @Override 체크버튼을 해제하시면 됩니다.



자 이제 이 메소드에서 특수키 이벤트를 구현하시면 됩니다.

다음은 특수키 목록입니다.


KEYCODE_BACK : 뒤로가기 버튼

KEYCODE_VOLUME_DOWN : 볼륨 ↓ 버튼

KEYCODE_VOLUME_UP : 볼륨 ↑ 버튼

KEYCODE_HOME : 홈 버튼


이외에 키보드에서 입력할 수 있는 모든 키는 코드로 정의되어있습니다.

이번시간에는 특수키 제어만 해보겠습니다.


다음과 같이 코드를 작성합니다.


public boolean onKeyDown(int keyCode, KeyEvent event) {

switch(keyCode){

case KeyEvent.KEYCODE_BACK :

// 여기에 뒤로가기 버튼을 눌렀을 때 행동 입력

break;

case KeyEvent.KEYCODE_VOLUME_DOWN :

// 여기에 볼륨 ↓ 버튼을 눌렀을 때 행동 입력

break;

case KeyEvent.KEYCODE_VOLUME_UP

// 여기에 볼륨 ↑ 버튼을 눌렀을 때 행동 입력

break;

case KeyEvent.KEYCODE_HOME

// 여기에 홈 버튼을 눌렀을 때 행동 입력

break;

}

return super.onKeyDown(keyCode, event);

}


필요한 키 코드만 복사해서 붙여넣어 사용하면됩니다.

단순히 키 입력을 막고싶다 하시는 분은


case KeyEvent.KEYCODE_BACK :

return;


라고 입력하시면 됩니다.



* 수정(8/24)

HOME키 이벤트는 위 코드로 제어할 시 제대로 작동이 안됩니다.

따라서 다음과 같이 처리합니다.

우클릭 - Generate - Override Methods 선택 후 onUserLeaveHint 검색하고 생성합니다.



휴대폰의 홈 키 또는 작업탭 키를 눌렀을 때 작동하는 것을 확인했습니다.



저는 Log로 작성했지만 홈 키 또는 작업탭 키를 눌렀을 때 작동 할 코드를 Log부분에 작성하시면 됩니다.




* 참고 : KeyEvent는 해당 코드를 입력한 Activity(화면)에서만 발생합니다.


* 참고 (더 많은 키 코드를 확인하고싶은 분은  아래 링크로 가서 확인하세요)

https://developer.android.com/reference/android/view/KeyEvent



오타 및 질문사항은 댓글로 달아주세요!!







API를 사용하다보면 보통 해외에서 만든 소스가 대부분입니다.

따라서 한글을 지원하기도 하고 안하기도 하는데

한글을 지원하더라도 유니코드로 문자열이 처리가 되면 난감합니다.

그래서 이번엔 유니코드를 한글로 변환하는 프로그램을 작성해봤습니다.


- 소스코드


public string uni_to_kr(string uni)

{

     string line;

     uni = uni.ToUpper(); // 문자열을 모두 대문자로 변환

     // 파일 읽기

     System.IO.StreamReader file = new System.IO.StreamReader(@"d:\unicode.txt"); 

     while ((line = file.ReadLine()) != null) // 파일 한 줄 단위로 읽기

     {

          if (line.Contains(uni)) // 입력 한 유니코드가 포함 된 줄이면

          {

               file.Close(); // 파일 닫기

               return line.Split('\t')[1].ToString(); // 한글 문자열 반환

          }

     }

     return null;

}


unicode.txt



다음 유니코드가 저장 되어있는 파일을 읽어서 코드를 찾은 후 한글을 반환하는

아주 간단한 소스코드입니다.


질문 사항은 댓글로 달아주세요!




'C#' 카테고리의 다른 글

C# 기초다지기 - 문자열  (2) 2018.11.07
C# 기초다지기 - 배열  (1) 2018.11.06
C# 기초다지기 - 상수  (0) 2018.11.06
C# 기초다지기 - 캡슐화  (0) 2018.11.05
C# 기초다지기 - 프로그램 구조  (0) 2018.11.05
C# 기초다지기 - 변수  (0) 2018.11.05
C# DB연동  (1) 2018.08.29
[C#] Visual Studio 2017 C# OpenCV 라이브러리 설치  (0) 2018.08.18

to Top