윈도우용 프로그램을 개발할 때 VS 출력창에 TRACE를 하여서 값을 볼 수 도 있다.. 하지만.. 그렇게 보다보면 창도 너무 작고, 일일이 값을 디버깅하면서 보면, 실시간적인 흐름을 확인하기 힘들다....

 그럴 때 콘솔창을 띄우고 개발을 하면 훨씬 출력 값을 보기가 용의하다. 

 속성에서 여러가지 설정을 바꿔도 되지만, 가장 쉬운 방법은.. 

 프로젝트의 main함수가 있는 cpp 안에 헤더파일 인클루드 아랫 부분에다가... 

#pragma comment(linker, "/entry:WinMainCRTStartup /subsystem:console")

이 부분을 넣어주면, 실행과 동시에 콘솔창이 뜨게 된다...
(단, 전체 화면에서는 뒤로 가려지기 때문에, 그냥 일반 해상도로 개발할 때 디버깅용으로 사용하면 될 것이다.)
Posted by 바람처럼..
|

표준(Normal)
계산식 : (Cs*As) + (Cd*(1-As))
(덮힐칼러*덮힐알파) + (깔린칼러*(1-덮힐알파))
SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD ) : SRC + DEST
SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA) : 덮힐칼러 * 덮힐알파
SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ) : 깔린칼러 * (1-덮힐알파)
일명 알파블렌딩이다.
덮여지는 알파값의 나머지 만큼 밑의 그림이 보인다.
투명한 셀로판지 위에 그림을 그린것과 같다.


어둡게(Darken)
계산식 : MIN( Cs, Cd )
SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_MIN ) : MIN( Cs, Cd )
SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE ) : Cs * 1
SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE ) : Cd * 1
둘중 어두운색을 취한다.


곱하기(Multiply)
계산식 : Cs * Cd
SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD ) : 0 + Cs * Cd
SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ZERO ) : Cs * 0
SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR ) : Cs * Cd
색과 색을 곱하므로 점점 어두워진다는 특징이 있다.
형광펜의 느낌이 난다.


밝게(Lighten)
계산식 : MAX( Cs, Cd )
SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_MAX ) : MAX( Cs, Cd )
SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE ) : Cs * 1
SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE ) : Cd * 1
둘중 밝은 색을 취한다.


스크린(Screen)
계산식 : 1 - ( 1-Cs ) * ( 1-Cd)
1 - ( 1 - Cd - Cs + (Cs+Cd)
1 - 1 + Cd + Cs - (Cs*Cd)
Cd + Cs - (Cs+Cd)
Cd + Cs * (1-Cd)
SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD ) : Cs * (1-Cd) + Cd
SetRenderState( D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR ) : Cs * (1-Cd)
SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE ) : Cd * 1
곱하기의 반대효과가 나와서 더 밝아집니다.
여러장의 사진 슬라이드를 포개서 투영하는것과 유사합니다.


선형닷지(Linear Dodge, Add)
계산식 : Cs + Cd
SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD ) : Cs + Cd
SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE ) : Cs * 1
SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE ) : Cd * 1
색을 더해서 명도를 증가시킵니다.
마법, 총알등의 이펙드로 밝아지는 효과는 Add혹은 Screen을 많이 사용합니다.


빼기(Subtract)
계산식 : Cd - Cs
SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT ) : Cd - Cs
SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE ) : Cs * 1
SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE ) : Cd * 1
색을 빼서 명도를 감소시킵니다.
흑마법에 사용하면 좋은결과가 나오지 않을까 생각듭니다.
실제로 마법관련 이펙트에서는 사용해보지는 않았습니다.
바로가기
Posted by 바람처럼..
|

두 벡터의 각도를 구하는 방법은 두 벡터의 내적 값을 이용하는 것이다.
두 벡터의 내적값을 acos() 에 넣으면 라디안으로 변환 된 각도 세타가 나온다.
하지만, 내적으로 나오는 각도는 0~180 으로만 나온다.
물론 이 것만 가지고도 충분하기는 한데.. 그래도 확실한 360도를 알고 싶다면,
두 벡터를 외적한 벡터의 방향이 어디인지를 판단하면, 기준이 됬던 벡터가 실제 2번째 벡터의 왼쪽에 있는지, 오른쪽에 있는지를 판단할 수 있기 때문에, 그냥 90인지 -90인지를 쉽게 파악할 수 있다.
단, 모든 연산에 앞서서 벡터들은 노멀라이즈 연산(벡터의 크기를 1로 만듬)을 해놓아야한다.
Posted by 바람처럼..
|
mfc를 쓰다보면, CString으로 editbox의 값을 입력 받았다가, 숫자로 변환하여 쓰는 경우가 많다. 그럴때 숫자로 변환하는 방법이다.
(물론 다른 방법도 있다. float 일때 이렇게 사용된다. )
CString strValue;
GetDlgItemText( IDC_EDIT1, strValue);
float fValue = _tstof( strValue );

출처 :    http://gigaboy.egloos.com/10709387
Posted by 바람처럼..
|


얼마전에 분명히 문제 없으리라 생각하고 넣은 코드가...

분명히 조건도 다 맞는데 오작동을 하였다.....

흠.. 환장하겠네.. 라고 하는 순간.. 응?? if 문의 조건에.. == 이 아니라.. = 만 있었다....

허허.. 이 것참.. 내 실수이니 뭐라 할 수는 없지만.. 정말 짜증나는 상황이다...

그래서 이럴 경우를 대비해 조건문의 순서를 바꿔쓰면된다...

예전에 어느 블로그에서 본 글이였는데..

예를들어서 a == 0 이라는 조건이 있었는데..

실수로 a = 0 이라고 쓴다면, 머.. 간단한 코드 사이에 껴있다면 금방찾지만, 복잡한 코드속에 묻혀 있다면

정말 찾기 어려울 것이다.. 이럴 때.. 0 == a 라고 쓰는 습관을 들인다면,

0 == a 는 제대로 동작하지만 0 = a 는 에러를 발생 시킨다.. 0이라는 상수에 a를 대입할 수는 없으니 말이다...

이런 식으로 순서를 바꾼다면, 이런 간단한 실수에 시간을 잡아 먹지는 않을 것이다...

물론 처음에 익숙치 않으면 익숙해 지는데 시간이 걸리고, 혹 다른 사람과 같이 소스를 공유하며 작업하는

프로젝트에서는 소스의 가독성이 떨어질 지도 모른다..

하지만 이런 습관들이 디버깅에 드는 시간을 줄여 줄 수 있다면, 작성할 때 한번 쯤 고려해 보는 것도 나쁘지 않을 것이다.
Posted by 바람처럼..
|


 간단한 프로그램을 만든다면, 솔직히 디버깅 모드로 몇번만 코드를 훓으면, 버그를 찾아내기는 어렵지 않다.

하지만 점점 더 프로그램이 커져 나갈 수록, 우리는 간단하다고 생각했던 부분의 치명적인 실수로 프로그램이 연산도중

죽어버리는 상황에 맞닥드리게 된다....

머.. 운이 좋아서 한번에 디버깅 모드로 찾아 갈 수도 있지만, 매번 그렇게 되리라는 보장은 없다...

그럴 때 만약 절때 계산에서 들어가지 말아야 할 조건이 있다면 쓸 수있는 assert() 함수를 이용해 보자...

기본적으로 assert() 함수는 디버그 모드에서 동작하는 디버깅용 함수라고 생각하면 되는데...

assert(a == 0 ) 처럼.. 뒤에 조건을 넣으면 된다...

assert를 사용하기 위해서는 #include <assert.h> 헤더를 추가하고 필요한 부분에서 사용하면 된다..

이 assert가 유용하게 쓰이는 경우가 바로 위의 예 처럼, 0이 절때 들어가서는 안되는 경우나 또 절때 2개의 값이 같을 수 없는

경우(배열의 크기는 10인데 10이 들어간다든지 하는..) 그럴때 유용하다.

assert의 조건문에 걸릴 경우 메세지 박스가 뜨며 어떤 파일, 몇번쨰 줄에서 떳는지 바로 기록해 주기 때문에..

유용하게 사용할 수 있다.
Posted by 바람처럼..
|


흔히 코딩을 짜다보면 현재 true 라면 false를..

반대로 false라면 true를 만들거나, 리턴해야 하는 상황이 있다.

그럴때

if( 변수 == true )
{
       변수 = false ;
}else
{
       변수 = true ;
}

이렇게 넣어주거나......

bool BoolChange(bool 변수)
{
        return !변수 ;
}


함수를 만들어 쓸수도 있다.....

하지만 ? 와 : 만 있으면 한줄로 해결 할 수 있다.

바로 글 제목 처럼

bool 변수 = 변수 ? false : true ;

라고 입력하면 된다.. 저 ? 와 : 의 사용 방법은...

A ? B : C ; 라고 생각했을 때 A가 참이면 B를 리턴, 거짓이면 C를 리턴한다.

예를 들어 보면..

bool b = true ;

b = b ? false : true ; 
라고 하면 b 에는 b가 현재 참이기 때문에 : 앞에 있는 false가 리턴되서 b는 false 로 바뀌게 된다. 

A 위치에는 다른 조건들도 가능하니.. 많이 활용하면 좋을 듯....

Posted by 바람처럼..
|

이번에 프로젝트를 하면서 키보드 입력 값을 받아서 EditBox 처럼 만들어야 하는 일이 있었다.

처음에 아무 생각없이 그냥 키보드 Input을 처리하듯이 WM_KEYDOWN 메시지를 받아서 처리하려 했었다.

로직을 완성하고 프로그램을 실행 시키는 순간.... 어랏??? ... 그냥 a 라고 생각하고 눌렸는데 A가 나왓다.... 숫자 키는 shift를

눌려도 1, 안눌려도 1이 나왔다.... 흠.... 처음에는 쉬프트에 따른 연산을 따로 해야하는 줄 알았다.

그래서 검색을 해본결과..... 이런..... 키입력을 받으려면.. WM_CHAR를 써야 한다는 것이다.

그냥 WM_KEYDOWN을 쓰면 처음 입력 된 것처럼... 그냥 A, 1 이렇게 나올뿐이고 우리가 흔히 EditBox에 입력되는 형태로 글

자를 출력하려면 WM_CHAR에 들어온 인풋 값을 그대로 배열에 대입해 주면 된다..

간단하지만, 정확히 모르면 헷갈리기 쉬운 메시지.
Posted by 바람처럼..
|
  


 아.. openCV를 쓰다가.. openCV 캠입력은 윈도우나 하드웨어나 여러가지 특성때문에 가끔 화면 출력이 안되는 경우가 있다.
(화면이 완전 회색이거나 완전 검정)

 그래서 검색을 하고, 하고 또 하다가.. 웹캠을 DirectShow로 출력하라는 글을 보았다.

 그때 부터 바로 서치를 시작했지만.. 필터니, 그래프니.. 이건.. 생전 처음 듣던 용어 들이였다. 물론 좀 더 공부를 해 나가다 보면  익숙해 지겠지만.. 일단은 지금 시간이 없는지라 계속 검색을 하던 중.. 한 클래스를 발견했다. ( 역시 구글~) 

 클래스 작성자가 공개를 해 놓은 것이라.. 써도 될 것 같아서.. 일단 가져와서 쓰고 여기다가도 공유를 해 놓는다.
( 문제가 생긴다면 답글을 달아주시면 바로 삭제하겠습니다. )

 일단 저 클래스를 추가를 하고, main.cpp를 만든 다음에 아래의 예제를 붙이면 된다.

#include <cstdio>
#include "VideoCapture.h"

#define TEST(x) printf("\nPress enter to test: " #x); getchar(); fflush(stdin); x;

void callback(unsigned char* data, int len, int bpp)
{
       printf("DATA %d %d\n",len, bpp);
}

int main()
{
 VideoCapture* vc        = new VideoCapture(callback);

 VideoDevice* devices    = vc->GetDevices();

 int num_devices         = vc->NumDevices();

 for (int i=0; i<num_devices; i++)
 {
  printf("%s\n", devices[i].GetFriendlyName());
 }
 
TEST(vc->Select(devices));
TEST(vc->Start());
 //TEST(vc->Select(devices));
 //TEST(vc->Stop());
 //TEST(vc->Start());
 //TEST(vc->Stop());
 
 printf("Done testing...");

 getchar();
 
 return 0;
}

ps. 물론 dshow가 설치된 경로를 프로젝트에 속성에서 추가를 해주어야 정상적으로 동작을 할 것이다. 
 또 dshow가 컴파일을 하며 내부 .h 에 의한 에러가 난다면 유용한 팁의 다른 글을 참조 하시면 쉽게 해결 될 것이다.

 

 

 

Posted by 바람처럼..
|

예전에는 도구의 옵션으로 들어가서 include 폴더 경로와 lib 폴더 경로를 적었었다.

그렇게 되면, 한번 저장된 경로는 모든 프로젝트에 적용 되었으므로, 다음번에 새 프로젝트를 만들더라도 손을 볼 필요가 없었다.

하지만!!! 벗!!! 이제 2010 부터는 각 프로젝트에 속성에 있는 VC++ 경로에 모든 폴더 경로를 지정해야한다........


헤매지 말고 바로 여기서 적으면 된다는 것을 알면 된다.... 하지만... 무지막지하게 귀찮아 진 것이 무엇이냐면.....

이런식으로 프로젝트 속성에서 관리하기 때문에 새 프로젝트를 만들 시 모든 경로를 다시 지정해 줘야한다 ㅠ,ㅠ

물론 좋은 방법이 있을 수 있지만, 현재로는 못 찾아서 그냥 예전 경로를 계속 복사해 줄뿐.......
Posted by 바람처럼..
|


웹캠의 영상을 입력 받기 위해서 dsshow 헤더를 인클루드 시켰다..

예전에는 dx 8.0x 버전까지만 나오고 이후 버전에 없었기 때문에 예전 버전을 썻지만 요즘에는 WPF에 함께 설치가 되어 확실히 간편해 졌다.

하지만

#include <dshow.h> 와
#include <qedit.h>

헤더를 인클루드 시키고, lib 파일을 추가한 다음에 컴파일을 했더니

fatal error C1083: 포함 파일을 열 수 없습니다. 'dxtrans.h': No such file or directory

이런 에러가 떳다..... 응? ... 내부적인 에러였다.. 머 검색을 좀 하다보니 최신 버전으로 바뀌며 먼가 안맞아 져서 수정을 해야한다는데......

결국 해결책을 찾았다.

해결책은

#include <dshow.h> 와
#include <qedit.h> 사이에

#pragma include_alias( "dxtrans.h", "qedit.h" )
 
#define __IDxtCompositor_INTERFACE_DEFINED__
 
#define __IDxtAlphaSetter_INTERFACE_DEFINED__
 
#define __IDxtJpeg_INTERFACE_DEFINED__
 
#define __IDxtKey_INTERFACE_DEFINED__

이 부분을 추가해주면 끝.

Posted by 바람처럼..
|


 얼마전 VS 2008로 만든 릴리즈 버전 프로그램을 배포 하려 했는데 문제가 있었다.

 되는 컴퓨터가 있고, 안되는 컴퓨터가 있는 것이다.

 그래서 그냥 필요하다는 dll을 모두 릴리즈 폴더안에 넣어 두었다.

 하지만 그렇게 하더라도, 시작점을 제대로 초기화 하지 못했다면서 죽어 버리는 문제가 발생하였다. 

 이것의 원인이 무엇인가 하고 계속 검색을 해보니.. 2003 이후부터 (2005인지 2008인지 모르지만 일단 넘어감) dll을 링크할 시에

widows폴더에 winSxS 라는 폴더에 각 버전에 맞는 dll을 링크 하도록 바뀌었다고 한다 ..

 즉 예전에는, 그냥 컴파일 했던 컴퓨터의 dll을 폴더에 넣어만 줘도 해결 되던 문제들이 이제는 안되는 것이다.

 그래서 생각한 첫번째 해결책은 재배포 패키지를 설치하는 것이다. (각 버전에 맞는 패키지 들은 마이크로소프트 다운로드 센터에서 받을 수 있다.)

 하지만.. 그렇게 설치를 했지만 문제가 생겼다.. 여전히 같은 증상인 것이다. 참고로 나는 2008로 컴파일을 했기 때문에 2008 기본 재배포와 sp1 재배포를 설치했었다.

 그래서 또 알아보니, 여기에 링크되고 있던 라이브러리 중 하나가 예전 버전 dll을 이용하고 있었던 것이다.

 그래서 이전 버전 재배포 까지 깔고 나서야... 겨우 문제가 해결되었다.

 하지만, 또 한가지 문제가 있었으니... xp용 컴퓨터에서는 잘 동작하는데.. 윈도우 7에서는 먹통이 되는 것이였다.. 분명히 재배포도 깔고 다 깔았는데 why? 라고 생각했지만, 이것도 사실 간단한 문제였었다.

 윈도우 7은 다이렉트 11을 기본적으로 설치해 놓고 있는데.. 프로그램을 개발할 때 썻던 버전은 다이렉트9 였던 것이다. 그래서 다이렉트 9 버전의 런타임 라이브러리를 설치했더니 7에서도 문제 없이 돌아갔다.

 사실 알고 보면 참 원인은 간단한데.. 모를 땐 답답하니... 이렇게 정리를..

 ps. 한가지 해결책이 더 있는데 그것은 매니페스트 파일(2008인지 2005부터 생김)을 직접 손을 봐서 해결 하는 방법이다. 

 - 윗 부분 생략 -

<dependency>

    <dependentAssembly>

<assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.30729.1" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>

    </dependentAssembly>

  </dependency>

</assembly>

 

위의 설정을 보면 Microsoft.VC90.CRT 관련하여 9.0.30729.1 버전의 32bit dll을 링크한다는 의미이다.  현재

publicKeyToken
에 대해서 없어야 된다는 의견도 있으나, 저것이 있어도 실행되는 컴퓨터에서는 전혀 이상없이 동

작하기 때문에 조금 더 옵션에 대해 알아봐야 할 것 같다.


ps. 아 또 한가지 해결책이 있는데 컴파일 옵션을 dll을 애초에 컴파일 하면서 포함하도록 하면, 용량은 좀 늘어나지만, 배포하

기는 훨씬 수월해진다. 하지만, 이 것은 미리 컴파일 된 해더와 서로 충돌이 있어, 이 문제를 해결 하고 사용해야 할 것이다.



Posted by 바람처럼..
|