반응형

http://liveupdate.tistory.com/179

반응형

'CS > 타이젠' 카테고리의 다른 글

[타이젠] 외부 application 실행시키기  (0) 2017.08.11
[타이젠] 슬라이드  (0) 2016.12.27
반응형

http://gogorchg.tistory.com/entry/Android-%ED%94%84%EB%A0%88%EC%9E%84-%EC%86%8D%EB%8F%84-%EC%A1%B0%EC%A0%88





쓰레드를 조절할 때, postDelay를 이용해서 프레임 속도를 조절하는데요.

Opengl을 사용할 경우 라이브러리 자체내에서 스레드를 돌리기 때문에

프레임 속도를 조절하기가 힘든 경우가 있었습니다.

그래서 이같은 소스가를 사용하는데요.

private static long targetFrameInterval = 1000L / 30L;  // 프레임 속도 30
private long frame = 30L;

// 스레드 콜백 함수 (무한 반복 하는 함수)
public synchronized void onDrawFrame(GL10 gl) {

// 프레임 처음 시간 설정

long frameStartTime = System.currentTimeMillis();

//.. 뭔가 뿌려주기 위한 소스 등등.

// 프레임 시간을 넘기면 그 시간 만큼 정지

long frameEndTime = System.currentTimeMillis();

long delta = frameEndTime - frameStartTime;

if (targetFrameInterval - delta > frame) {

try {

Thread.sleep(targetFrameInterval - delta);

} catch (InterruptedException e) {}

}
 


 저두 구글링을 통해서 알아낸 겁니다.

알았다기 보단 퍼 온거죠..^^;;; 

사이트를 잊어버려서.. 결국 이렇게 올렸다는..헤헤 

출처: http://gogorchg.tistory.com/entry/Android-%ED%94%84%EB%A0%88%EC%9E%84-%EC%86%8D%EB%8F%84-%EC%A1%B0%EC%A0%88 [항상 초심으로]

반응형

'CS > OpenGL' 카테고리의 다른 글

[OpenGL] 공부순서  (0) 2016.12.26
[OpenGL] FBO 관련 사이트  (0) 2016.12.21
[OpenGL]glReadPixels로 픽셀값을 읽어 glDrawPixels로 그리기  (0) 2016.12.21
[OpenGL] Frambe buffer object(FBO)  (1) 2016.12.20
[OpenGL] 텍스쳐 예제  (0) 2016.12.01
반응형

http://www.slideshare.net/badaindonesia/samsung-indonesia-tizen-native-app

반응형

'CS > 타이젠' 카테고리의 다른 글

[타이젠] 외부 application 실행시키기  (0) 2017.08.11
[타이젠] 좋은 블로그  (0) 2017.01.11
반응형

http://m.blog.naver.com/dnib/220581936320

반응형
반응형

1.

http://wanochoi.com/?p=1019


2.

http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/


3

FBO를 이용한 Render To Texture 구현

http://blog.daum.net/aero2k/53


4.

네이버 3D카페

http://cafe.naver.com/gld3d/181



5.

glPixelRead Example

http://www.lighthouse3d.com/tutorials/opengl-selection-tutorial/



6.

glPixelRead

https://www.khronos.org/opengles/sdk/docs/man3/html/glReadPixels.xhtml




반응형

'CS > OpenGL' 카테고리의 다른 글

[OpenGL] 쓰레드 속도조절  (0) 2017.01.04
[OpenGL] 공부순서  (0) 2016.12.26
[OpenGL]glReadPixels로 픽셀값을 읽어 glDrawPixels로 그리기  (0) 2016.12.21
[OpenGL] Frambe buffer object(FBO)  (1) 2016.12.20
[OpenGL] 텍스쳐 예제  (0) 2016.12.01
반응형

// 배열 동적할당 
 BYTE *oimagedata = (BYTE*)malloc(sW*sH*3); 
 BYTE *nimagedata = (BYTE*)malloc(sW*sH*3); 

 glReadPixels(0, 0, sW, sH, GL_RGB, GL_UNSIGNED_BYTE, oimagedata);


// 이미지 플립
 for(int j = 0 ; j< sH ; j++){
  for(int i = 0; i < sW ; i++){
   nimagedata[j*sW*3 + i*3 + 0] = oimagedata[j*sW*3 + (sW-i)*3 + 0];
   nimagedata[j*sW*3 + i*3 + 1] = oimagedata[j*sW*3 + (sW-i)*3 + 1];
   nimagedata[j*sW*3 + i*3 + 2] = oimagedata[j*sW*3 + (sW-i)*3 + 2];
  }
 }

 glDrawPixels(sW, sH, GL_RGB, GL_UNSIGNED_BYTE, nimagedata);
 
// 배열 해제
 
 free(oimagedata);
 free(nimagedata);



반응형

'CS > OpenGL' 카테고리의 다른 글

[OpenGL] 쓰레드 속도조절  (0) 2017.01.04
[OpenGL] 공부순서  (0) 2016.12.26
[OpenGL] FBO 관련 사이트  (0) 2016.12.21
[OpenGL] Frambe buffer object(FBO)  (1) 2016.12.20
[OpenGL] 텍스쳐 예제  (0) 2016.12.01
반응형

출처 : http://wanochoi.com/?p=1019


Framebuffer는 rendering의 최종 결과가 기록되는 buffer들의 집합이다.
OpenGL context가 생성되면서 기본적으로 하나의 framebuffer를 생성하여 사용하는데,
이러한 default framebuffer를 window-system-provided framebuffer라고 부른다.
반면, 필요 시 임의의 framebuffer를 동적으로 생성하여 사용하는 것이 가능한데,
이렇게 생성된 framebuffer를 application-created framebuffer라고 하며,
일반적으로 framebuffer object (FBO)라고 한다.
FBO는 display 외의 목적으로도 많이 사용된다.
Buffer란 OpenGL이 관리하는 memory 영역을 말한다. (buffer=array=image)
이러한 의미로 보면 FBO는 사실 엄밀히 말해서 buffer는 아니다.
(사실 aggregator의 개념에 더 가깝다.)

FBO는 하나 또는 다수의 buffer들이 attach되어 있는 형태로 존재한다.
(여러 개의 array들에 대한 pointer들을 member로 가지는 구조체(struct)와 같은 개념.)
Default framebuffer에는 color, depth, stencil, accumulation의 용도로 사용되는 buffer들이 attach될 수 있지만, FBO에는 accumulation을 제외한 color, depth, stencil의 용도로 사용되는 buffer들이 attach될 수 있다.
하나의 FBO에는 다수의 attachment point들이 존재하며, 각각의 attachment point마다 하나의 buffer가 attach될 수 있다.
하나의 FBO는 n개(system 마다 다름)의 color attachment points와 각각 한 개씩의 depth attachment point, stencil attachment point를 가진다.
(GL_COLOR_ATTACHMENT0, …, GL_COLOR_ATTACHMENTn, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT)
하나의 FBO에는 최소한 한 개의 color buffer가 attach되어야 한다.
여러 개의 color attachment points를 가지고 있는 이유는 동시에 여러 개의 color buffer에 rendering이 가능하기 때문인데, 이러한 기법을 multiple render targets (MRT)라고 부른다.
Framebuffer attachable buffer는 크게 두 가지 type이 있다.
1. texture object  2. renderbuffer object
Texture object가 render target으로 설정되어 rendering이 수행되는 것을 render-to-texture,
RBO가 render target으로 설정되어 rendering 작업이 수행되는 것을 offscreen rendering이라고 한다.
기본적으로 RBO에 rendering 작업이 완료되었다고 해도 GPU memory 상에만 존재할 뿐 화면에는 보여지지 않기 때문이다.
Texture란 보통의 경우 3D model의 표면을 장식해주는 image의 역할을 수행하지만, 이 외에도 다양한 data를 저장하기 위해 사용될 수 있다.
즉, texture는 GPU에서 사용되는 bulk data를 저장하는 용도로 쓰인다.
(bulk data란 여러 가지 용도로 사용되는 data를 말함.)
Texture는 1D, 2D, 3D 등의 형태로 사용이 가능하며, shader 내에서 값을 읽어서 사용하는 것이 가능하다.
Texture는 GPU memory 상에 독립적으로 동적 할당되어 자유롭게 사용이 가능하지만, RBO는 반드시 FBO에 attach되어 사용되어야 한다.
RBO는 texture와는 달리 반드시 2D 형태로만 사용되어야 하고, 단 한 개의 image 만을 가질 수 있다. (texture에서처럼 mipmaps 사용이 불가능함.)
RBO에 저장된 rendering 결과는 glReadPixels(), glDrawPixels(), glCopyPixels()와 같은 함수들을 이용해서 읽고 쓰는 것이 가능하긴 하지만, shader 내에서는 값을 읽어오는 것이 불가능하므로 texture source 등의 용도로 사용할 수 없다. 만약 shader 내에서 특정 image의 값을 읽어올 필요가 있다면 texture object로 만들어서 사용해야 한다.
만약 shader에서 값을 읽어서 사용하지 않는다면 성능상 texture object 보다는 RBO type을 사용하는 것이 더 좋다.
보통의 경우 depth test가 필요할 경우 depth buffer를 RBO type으로 생한한 후 해당 FBO의 GL_DEPTH_ATTACHMENT에 attach해서 사용하지만, 만약 fragment shader에서 post processing을 수행할 때 depth 값이 필요하다면 texture object type으로 생성한 후 해당 FBO의 GL_DEPTH_ATTACHMENT에 attach해서 사용해야 한다.
Texture object를 생성하는 방법은 일반적으로 texture를 사용하는 경우와 동일하다.
다만 image data를 load하여 연결해줄 필요가 없으므로 glTexImage2D() 함수에서 맨 마지막 인자에는 NULL을 써주면 된다.

다음은 FBO를 한 개 생성한 후, depth buffer로 사용될 texture object를 생성하여 attach하는 예제이다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// framebuffer object
GLuint fboId;
glGenFramebuffers( 1, &fboId );
glBindFramebuffer( GL_FRAMEBUFFER, fboId );
 
// texture buffer object to be used for depth buffer
GLuint depthTexId;
glGenTextures( 1, &depthTexId );
glBindTexture( GL_TEXTURE_2D, depthTexId );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
 
// attachment
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE2D, depthTexId, 0 );


다음은 FBO를 한 개 생성한 후, depth buffer로 사용될 renderbuffer object를 생성하여 attach하는 예제이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// framebuffer object
GLuint fboId;
glGenFramebuffers( 1, &fboId );
glBindFramebuffer( GL_FRAMEBUFFER, fboId );
 
// renderbuffer object to be used for depth buffer
GLuint depthRboId;
glGenRenderbuffers( 1, &depthRboId );
glBindRenderBuffer( GL_RENDERBUFFER, depthRboId );
glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height );
 
// attachment
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRboId );


반응형

'CS > OpenGL' 카테고리의 다른 글

[OpenGL] 쓰레드 속도조절  (0) 2017.01.04
[OpenGL] 공부순서  (0) 2016.12.26
[OpenGL] FBO 관련 사이트  (0) 2016.12.21
[OpenGL]glReadPixels로 픽셀값을 읽어 glDrawPixels로 그리기  (0) 2016.12.21
[OpenGL] 텍스쳐 예제  (0) 2016.12.01
반응형

1.


한번 전반적인 flow를 따라 가면서 텍스처를 익혀보도록 해야겠다.



먼저 텍스처를 불러오는것부터!!

(그림에서 텍스처를 가져오는것을 목표로 함)


1)


 final int[] textureObjectIds = new int[1];

 glGenTextures(1, textureObjectIds, 0);


=> 텍스처를 생성하고! 그것의 아이디를 textureObjectIds에 넣는다.




2)

glBindTexture(GL_TEXTURE_2D,textureObjectIds[0]);


=> GL_TEXTURE_2D 속성을 가진 텍스처를 위에서 생성한 textureObjectIds와 바인딩시킨다.



3)

 //setup MipMap

 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);

=>텍스처 확대와 축소의 방법으로 Mipmap을 사용하는데, 이를 설정하고!




4)

 texImage2D(GL_TEXTURE_2D, 0 , bitmap, 0);


=> 제일 중요해보이는데, 위에서 만든 텍스쳐에다가 bitmap데이터를 이어주기!!!!!!!!!!

    이때 bitmap데이터는 openGL이 읽을수 있도록 디코딩된 상태여야 한다.




5)

  bitmap.recycle();

  glGenerateMipmap(GL_TEXTURE_2D);



   //바인딩 해제

  glBindTexture(GL_TEXTURE_2D,0);


=> 그림데이터를 바인딩해줬으니, 더이상 필요가 없다. 그래서 recycle로 해제

     그리고 밉맵을 설정하고,  텍스쳐의 바인딩도 해제 시킨다.




여기까지가 전반적인 textureHelper의 역할이다.

다음으로는 렌더링 과정이 필요하다.

여기에서 사용한 텍스쳐도 결국에는 쉐이더와 이어지게 되어있다.

렌더링 과정에서는 이를 쉐이더에 전달하고 그 결과를 받고, 화면에 뿌리는 전반적인 작업을 한다고 보면된다.

쉐이더는 두가지로 나뉘는데, 버텍스쉐이더와 프래그먼트 쉐이더 이다.




uniform mat4 u_Matrix;

attribute vec4 a_Position;
attribute vec2 a_TextureCoordinates;

varying vec2 v_TextureCoordinates;

void main()
{
v_TextureCoordinates = a_TextureCoordinates;
gl_Position = u_Matrix * a_Position;
}


위는 버텍스 쉐이더의 모습인데, 

u_Matrix는 관점매트릭스로 해당 좌표에 관한 것을 설명할때 사용한다. (uniform 형태)

그리고 attribute가 2개인데. 한개는 버텍스데이터를 넣는것과

나머지 한개는 텍스쳐좌표를 넣는거다!


a_TextureCoordinates 속성 -> varying으로 바로 출력해서, 프래그먼트 쉐이더에서 이 버텍스 위치에다 텍스쳐를 그릴수 있게 해주는 역할을 한다.


a_Position은 뭐... 테이블좌표를 나타내는것...!!!




precision mediump float;

uniform sampler2D u_TextureUnit;
varying vec2 v_TextureCoordinates;

void main()
{
gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);
}

위에꺼는 프래그먼트 쉐이더의 내용이다.

varying은 버텍스쉐이더에서의 입력값이고, 텍스쳐의 위치값을 가지고 있음.

그리고 uniform으로 설정된 sampler2D가 진짜 bitmap의 데이터인데,

이를 texture2D에 넣어서. 프래그먼트를 출력을 한다.




그러면 이 쉐이더의 속성과 유니폼을 어떻게 연결시키는지 알아보자.



// Shader program

protected final int program;

protected ShaderProgram(Context context, int vertexShaderResourceId, int fragmentShaderResourceId){


//Compile the shaders and link the program.

program = ShaderHelper.buildProgram(TextResourceReader.readTextFileFromResource(

                context, vertexShaderResourceId),

                TextResourceReader.readTextFileFromResource(

                        context, fragmentShaderResourceId));

}



먼저 쉐이더를 builProgram(->만든 매서드)를 통해서 컴파일과 프로그램 링크시킨다.

이는 쉐이더 항목에서 배운것이다.

그런 다음에 uniform과 attribute 위치를 가져온다.



//Uniform constants

protected static final String U_MATRIX = "u_Matrix";

protected static final String U_TEXTURE_UNIT = "u_TextureUnit";


//Attribute constants

protected static final String A_POSITION = "a_Position";

protected static final String A_COLOR = "a_Color";

protected static final String A_TEXTURE_COORDINATES = "a_TextureCoordinates";


//Retrieve uniform locations for the shader program.

uMatrixLocation = glGetUniformLocation(program, U_MATRIX);

uTextureUnitLocation = glGetUniformLocation(program, U_TEXTURE_UNIT);


//Retrieve attribute locations for the shader program.

aPositionLocation = glGetAttribLocation(program, A_POSITION);

aTextureCoordinatesLocation = glGetAttribLocation(program, A_TEXTURE_COORDINATES);



유니폼과 속성의 위치를 가지고 오면...

이제는 거기다가 데이터를 집어넣는 일을 해야된다.


먼저 유니폼데이터부터 하고,

그다음에 속성데이터를 넣고.

그다음에 그리면 된다.



//Pass the matrix into the shader program.
glUniformMatrix4fv(uMatrixLocation, 1, false, matrix, 0);

// Set the active texture unit to texture unit 0.
//유닛0 텍스처를 활성화해라!!!
glActiveTexture(GL_TEXTURE0);

//Bind the texture to this unit.
//텍스처를 유닛과 연결!!
glBindTexture(GL_TEXTURE_2D, textureId);

//Tell the texture uniform sampler to use this texture in the shader by
//telling it to read from texture unit 0.
//sampler에 0번 유닛을 넣어라!!
glUniform1i(uTextureUnitLocation,0);



위에 정점 쉐이더에서 말하기를  uniform 데이터가 한개인데, 

그게 uMatrixLocation 이다. 

glUniformMatrix4fv 안에 matrix 데이터를 집어넣는다.


그다음부터는 프로그먼트 쉐이더의 텍스처를 입히는것과 관련된 내용이다.


glActiveTexture(GL_TEXTURE0)으로 0번 텍스처를 활성화 시키고.

이를 glBindTexture를 통해서 유닛과 연결을 시킨다.

glUniform1l을 통해서 텍스처 유닛0번을 uTextureUniLocation에 있는 텍스처에다가 넣는다는 의미이다.


그런뒤에 draw를 하게되면 해당 모습이 그려지게 된다.


public void draw(){
glDrawArrays(GL_TRIANGLE_FAN, 0 ,6);
}



텍스쳐에 대한 전반적인 흐름을 쭈욱 살펴보았다.

다시 한번 처음부터 쭈욱 따라가서 해당부분에 대한 감을 익혔으면 한다.




반응형

'CS > OpenGL' 카테고리의 다른 글

[OpenGL] 쓰레드 속도조절  (0) 2017.01.04
[OpenGL] 공부순서  (0) 2016.12.26
[OpenGL] FBO 관련 사이트  (0) 2016.12.21
[OpenGL]glReadPixels로 픽셀값을 읽어 glDrawPixels로 그리기  (0) 2016.12.21
[OpenGL] Frambe buffer object(FBO)  (1) 2016.12.20
반응형

카메라 애플리케이션은 카메라를 제어할 때, 기본적으로 카메라 서비스로 제어를 요청한 후 대기한다. 카메라 서비스로 제어를 요청한 후 메소드의 리턴값만으로 수행 결과를 처리할 경우, 처리가 오래 걸려 애플리케이션이 응답하지 않아 시스템 감시에 의해 ANR(Application Not Responding)로 인식되는 문제가 발생한다. 또한 카메라 서비스가 제어를 수행하는 동안 애플리케이션이 대기하므로 사용자의 요청을 처리할 수 없게 된다. 이와 같은 문제를 해결하기 위하여 다양한 콜백 메서드를 사용한다.


콜백메서드는 카메라 시스템의 주요 기능인데, 크게 두가지로 나뉘어진다.

데이터를 받아오기 위한 dataCallback 메서드

동작에 대한 상태나 결과를 받아오기 위한 notifyCallback 메서드가 그것이다.


dataCallback 메서드는 카메라의 영상을 프레임이나 이미지 형태로 가져오기 위하여 사용하며, 데이터 포맷은 카메라 설정에 따라 다르나 프레임의 경우 NV21(yuv420sp)를 기본이고, 이미지의 경우에는 JPEG을 기본으로 한다.


notifyCallback 메서드는 요청한 기능에 대하여 수행상태나 수행 완료등의 제어 결과나 제어 상태 정보를 얻기 위하여 사용한다.





1) PreviewCallback


카메라 영상 데이터는 네이티브 프레임워크에서 처리되므로, 애플리케이션은 카메라 영상 데이터를 얻기 위하여 카메라 서비스에 요청해야 한다. 이때 콜백 메서드로 카메라 영상 데이터를 얻어오는데, PreviewCallback 메서드는 startPreview() 메서드를 이용해 카메라에서 입력받아 화면에 출력되는 영상을 프레임 단위로 받아올 수 있다. 카메라 영상을 직접 처리해야하는 애플리케이션의 경우 PreviewCallback 메서드를 사용한다.

PreviewCallback 메서드는 setPreviewCallbck()메서드나 setOneshot PreviewCallback()메서드로 카메라 서비스에 콜백 메서드를 등록하거나 해제할 수 있다.

setOneShot PreviewCallback() 메서드는 프레임 데이터를 한번만 받아오고, setPreviewCallback()메서드는 해제 전까지 지속적으로 프레임 데이터를 받아온다. 이 경우 데이터 복사등에 따른 데이터 처리량이 많아져 시스템에 부하가 걸릴수 있으므로, 원하는 용도에 맞게 사용을 해야한다.



2) PictureCallback


PictureCallback 메서드는 사진 촬영 시 촬영된 결과물을 얻기 위한 인터페이스로,

애플리케이션에서 인터페이스를 구현하여 목적에 맞게 사용한다.

이렇게 구현된 콜백 메서드는 RawPictureCallback, PostViewPictureCallback, JpegPictureCallback 이 있다




3) RawPictureCallback


RawPictureCallback 메서드는 사진 촬영 시, 촬영된 원본 데이터를 받아온다.

카메라의 기본 애플리케이션은 카메라 서비스를 이용해 카메라 촬영 요청 후 촬영을 완료하여 이미지를 생성 완료하는 과정에서 카메라가 촬영을 완료한 시점의 시간 정보를 획득하는 데 RawPictureCallback 메서드를 사용한다.





4) PostViewPictureCallback


PostViewPictureCallback 메서드는 촬영된 이미지를 화면에 출력할 목적으로 사용한다. 카메라 기본 애플리케이션은 PostViewPictureCallback 메서드 역시 촬영 기능에 대한 시간을 측정하기 위한 용도로 사용한다.




5) JpegPictureCallback


JpegPictureCallback 메서드는 RawPictureCallback 메서드와 마찬가지로 takePicture()메서드를 통해 카메라 서비스에 등록한다. 전달받는 데이터는 JPEG 이미지 데이터에 EXIF정보가 포함된 전체 데이터로, 저장소에 저장한다.




6) ShutterCallback


사진 촬영 시 카메라 장치에서 사진 촬영을 완료한 후 데이터를 받아오기 전에 ShutterCallback 메서드가 등록되어 있으면 이를 통해 사진이 촬영되었음을 알려준다. ShutterCallback메서드를 통해 카메라 서비스에서 카메라 촬영음을 낸다. 카메라 기본 애플리케이션은 ShutterCallback 메서드를 통해 카메라 동작에 대한 시간을 측정한다.




7)ErrorCallback


카메라 서비스가 동작 중 에러가 발생하는 경우, 이를 애플리케이션이 알기 위한 콜백 메서드로, 카메라 서비스가 잘못 동작해 카메라 서비스나 미디어 서버가 죽는 경우에 호출된다.


반응형
반응형

해당 부분은 개발자가 직접 개발할 수 있는 어플들에 관한 계층입니다.

시중에 나와있는 각종 안드로이드 책에서도 쉽게 볼 수 있는 부분입니다.

실제적으로 코딩을 해야되는 부분이므로, 천천히 읽어나가셨으면 합니다.

이 부분도 '안드로이드의 모든것 분석과 포팅'과 카메라 개발문서를 보면서 제 개인적으로 정리한 부분을 적어놓은것임을 미리 밝혀 드립니다.


카메라 애플리케이션을 만들기 위해서는 기본적으로 카메라영상을 사용자가 볼 수 있게 출력을 하는 Preview 부분이 먼저 구현이 되어야 한다.

그래서 카메라를 구동해서

영상을 입력받기 위한 카메라서비스 관련 기능과

영상을 화면에 출력하기 위한 SurfaceFlinger 서비스 관련 기능이 구현되어야 한다.



(카메라 예제 애플리케이션의 구조도)



애플리케이션을 코딩하기전에 androidManifest부터 설정을 해야한다.


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



그다음 영상을 위한 출력을 해보자.

먼저 출력할 영역을 설정을 해야하는데, 이부분은 xml로도 가능하고 바로 코딩으로도 가능하다. 출력은 SurfaceView에서하는데 Surface를 생성하도록 SurfaceFlinger서비스에 요청을 해야한다. 그런데 SurfaceView를 관리하기 위한 SurfaceHolder가 존재하고 이를 통해 SurfaceView영역에 대한 처리를 SurfaceFlinger에 요청을 한다.



public class CameraPreview extends Activity{

private Preview mPreview;

protected void onCreate(Bundle savedInstanceState){

mPreview = new Preview(this);

setContentView(mPreview);

}

}


Preview 클래스는 ViewGroup 클래스를 확장하고, SurfaceHolder.Callback 인터페이스를 구현하였다. Preview 클래스는 인스턴스 생성 시 SurfaceVIew와 관련된 처리를 수행한다.

ViewGroup은 android.view.ViewGroup으로 View클래스를 확장한것이다. 그런데 이는 다른뷰를 포함할 수 있는 특별한 뷰이다. 

SurfaceHolder.Callback 인터페이스는 SurfaceFlinger서비스에서 요청된 Surface를 생성하거나 소멸시킬 때를 알기 위한 것으로, 애플리케이션이 Surface에 직접 접근할 권한이 없기 때문에 SurfaceHolder.Callback 인터페이스를 통해 콜백 메서드를 구현하여 Surface를 처리하여야 한다.




class Preview extends ViewGroup implements surfaceholder.callback{

Surfaceview mSurfaceView;

SurfaceHolder mHolder;

Preview(Context context){

mSurfaceView = new SurfaceView(context);

addView(mSurfaceView);

//Install a SurfaceHolder. Callback so we get notified when the

//underlying surface is created and destroyed.

mHolder = mSurfaceView.getHolder();

mHolder.addCallback(this);

mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

}

}


SufaceView 와 SurfaceHolder를 연결을 시켜야 하는데, 이 역할을 addCallback()메서드로 하게 된다. 이후 Surface가 생성되거나 소멸될 때, 속성이 변경될 때 콜백 메서드를 통해 Preview 인스턴스의 메서드를 호출한다.


이렇게 출력할 화면이 준비가 되면, 그 다음으로 카메라 장치와 이를 연결을 해주면 된다. 위의 CameraPreview애플리케이션이 구동이 되면

onResume()메서드가 호출이 되고, 이때 카메라 서비스를 이용해 카메라를 구동한다.

android.hardware.Camera의 open()메서드로 카메라 서비스를 이용해 카메라 장치를 활성화 하고, Camera 인스턴스를 얻어 온다.

그 후 Preview의 setCamera() 메서드를 호출하여 카메라 정보를 기반으로 레이아웃을 설정한다.


protected void onResume(){

mCamera = Camera.open();

mPreview.setCamera(mCamera);

}



public void setCamera(Camera camera){

mCamera = camera;

if(mCamera !=null){

mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();

}

}



애플리케이션에서 카메라 서비스의 현재 설정값을 얻고자 할때는

android.hardware.Camera에서 제공하는 getParameters()메서드를 사용한다.

카메라의 매개변수 중에서 카메라가 지원하는 프리뷰 크기 정보를 기반으로 하여,

Preview의 onMeasure()메서드에서 적절한 프리뷰 크기를 찾고,

Preview의 onLayout()메서드에서 선택된 프리뷰 크기 정보를 기반으로 뷰를 생성하고 크기 및 위치를 조정한다.




카메라 영상이 출력될 Surface가 생성되면 surfaceCreate()메서드가 호출되고,

카메라 서비스에 프리뷰 영역으로 생성된 Surface에 카메라 프리뷰가 출력되도록 설정한다.


public void surfaceCreated(SurfaceHolder holder){

try{

if(mCamera != null){

mCamera.setPreviewDisplay(holder);

}

}

}





이후 Surface가 변경되어 프리뷰 인스턴스의 surfaceChanged()메서드가 호출되면,

카메라의 현재 매개변수 값을 다시 가져와 선택된 프리뷰 크기로 변경하고,

setParameters()메서드로 프리뷰 카메라에 설정한다.

이후 startPreview()메서드로 카메라 서비스에서 영상을 가져와 화면에 출력한다.



public void surfaceChanged(SurfaceHolder holder, int format, int w, int h){

//Now that the size is known, set up the camera parameters and begin the //preview.

Camera.Parameters parameters = mCamera.getParameters();

parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);

requestLayout();


mCamera.setParameters(parameters);

mCamera.startPreview();

}

반응형

'CS > 안드로이드' 카테고리의 다른 글

[안드로이드] 카메라 #3_Callback  (0) 2016.10.24
[안드로이드] 카메라 #1_매커니즘  (0) 2016.10.24

+ Recent posts