Microsoft MVP성태의 닷넷 이야기
C#과 C++을 이용한 Image 처리. [링크 복사], [링크+제목 복사],
조회: 19479
글쓴 사람
Jongha Kim (zzolzzoly at naver.com)
홈페이지
첨부 파일
 

영자님 안녕하세요.
항상 좋은 정보 잘 읽고 있습니다.
어떻게 항상 새로운 글을 쓸수있는지.. 부럽습니다.

글을 쓴 이유는 c++을 경험하지 못해 질문 하나 하려합니다.
현재 .net 기반 c/s 프로그램을 운영중인데 현업요청 사항 중
image drawing 시 백만건이상(천만건)까지도 가능토록 하고
이 Image를 여러장 표시하길 원합니다.

현재 gdi+를 이용해 데이타를 처리해 보았는데 drawing 처리가 가능하긴 합니다.
물론, 성능저하가 심합니다.
서버를 사용하는 방법도 있긴하지만 Client 기반에서 성능을 최대화해보고 싶습니다.

하여, 자료를 찾아보니 C++과 .Net의 graphic 처리 방식에 차이점이 있어
그부분을 테스트를 해보고 싶습니다.(gdi, gdi+)

첫번째는 Control Handle과 데이타 Array를 넘겨 c++에서 drawing과 display를 처리해주는 방식이구요.
(대량 데이타를 Array로 담는것 자체가 말이 안되지만 구현은 해보고 싶습니다. 공유할 수 있는 Array 타입이 있나요?)

두번째는 C++을 C#의 Graphic 객체과 유사한 dll로 제공해주고 c++에서 drawing만 담당하고 image를 return 받는 방법입니다.
(return Image 사이즈가 클경우 오히려 성능에 영향을 줄것 같습니다. return 받는 image 타입을 어떻게 정의해야 하나요?)

세번째는 첫번째와 두번째를 혼합하여 c#에서 c++ graphic 객체(dll)로 drawing 후 Control Handle을 넘겨 받아 display 해주는 겁니다.
(첫번째의 c++내에서 Array로 돌렸을때와 성능면에서 차이는 없을까요?)

일단은 직접 테스트를 해볼건데
이런, 방법에 대한 의견이 좀 듣고 싶구요.
혹, 다른 접근 방법이 있는지 궁금합니다.

그리고 첫번째, 두번째 c#, c++ 데이타 타입 질문에 대한
답변도 자세히 좀 부탁드립니다.
자료를 찾아보았는데 쉽게 검색이 안되네요.
혹, 좋은 서적도 추천해주시면 감사하겠습니다.

너무 많은 질문을...ㅡㅡ;











[최초 등록일: ]
[최종 수정일: 6/2/2014]


비밀번호

댓글 작성자
 



2014-06-02 02시05분
그러게요. 일단, C# Windows Form을 쓰신다면 결국 Win32 Window Handle이 있기 때문에 C++에 넘겨주는 것도 자연스럽고 별 무리 없이 작업할 수 있습니다. 배열도 결국 내부적인 byte의 연속이기 때문에 C++과 C# 사이에 넘나드는 것도 됩니다.

Control Handle을 넘겨주느냐 Graphic 객체를 넘겨주느냐는 크게 차이가 없을 것입니다. 이미지 처리에 대부분의 부하는 개별 바이트를 로드해서 처리하는 것이기 때문에 그에 비하면 다른 작업들은 부하가 거의 없다고 보시면 됩니다.

데이터 타입은 결국, 메모리 상의 포인터이기 때문에 x86/x64에 따른 포인터와 적절한 부가데이터만 왔다갔다 하면 될 것입니다.

그리고 현재 가정한 상황이 재미있는데요. 백만건의 이미지가 있는데, 그걸 화면에 다 보여주는 것은 아닐텐데요. 이미지 하나당 점으로 표현할 것도 아닐텐데... ^^ 그렇다면 결국 백만건을 로드하는 것은 별로 의미가 없습니다. (괜히 메모리 부하만 됩니다.) 화면에 10개의 이미지가 보일수 있다면 앞 뒤로 10개씩 총 30개 정도만 미리 로드하는 식으로 처리하면 될텐데요. (현업 요청 사항이 구체적으로 어떤지 몰라서... 그냥 대충 말씀드리는 것입니다. ^^)
정성태
2014-06-02 10시51분
[Jongha Kim] 답변을 주셔서 감사합니다.
말씀하신데로 화면에 표시되는 최소 이미지에 대해서만 메모리에 올릴생각이구요.
이미지에 표시되는 대부분은 점으로 표시되게 될겁니다.
톨러런스를 적용하자 하였는데 모두 찍어달라네요. ^^a
그리고 지금 테스트 중인데 잘안되는게 있네요.
c++에서 이미지를 만들고 c#에서 dllimport를 통해 이미지를 받는 부분인데
이부분 간단 샘플로 좀 보여주시면 안될까요?
데이타 type을 어떤 type으로 정의행하나요?
[guest]
2014-06-03 07시27분
C++에서 이미지를 만들었으면, 그에 대한 포인터 주소값만 C#에 전달하면 됩니다. IntPtr로 전달하시면 될 듯한데요. 어렵게 생각할 필요없습니다. 어차피 같은 프로세스의 주소이기 때문에.
정성태
2014-06-03 01시31분
[Jongha Kim] 답변 감사합니다.
다시 한번 살펴보고 있습니다.
어렵게 생각안하려하는데 그게..ㅎㅎ
[guest]
2014-06-04 02시47분
[Jongha Kim] 이상하네...
왜 PictureBox 핸들을 인식못할까요?
오늘은 이걸로 시간을 다 보내네요.
아래 소스 뭐가 잘못된건가요? ^^; 살짝 보주세요.

-C#
[DllImport("GDISample.dll", CallingConvention = CallingConvention.Cdecl)]

public Form1()
{
InitializeComponent();
DrawImage(this.pictureBox1.Handle);
}

-C++
#define EXPORTDLL extern "C" __declspec(dllexport)
EXPORTDLL void DrawImage(void* hWndPointer);
EXPORTDLL void DrawImage(HWND hWnd)
{
  HDC pDC, memDC;
HBITMAP memIMG;
BITMAP bit;

pDC = GetDC(hWnd); <-- 표시안됨.
pDC = GetDC(NULL); <-- 윈도우 스크린에 정상표시됨
memDC = CreateCompatibleDC(pDC);

memIMG = (HBITMAP)LoadImage(NULL, L"F:\\aaa.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
HGDIOBJ old_bitmap = SelectObject(memDC, memIMG);

GetObject(memIMG, sizeof(BITMAP), &bit);
iWidth = bit.bmWidth;
iHeight = bit.bmHeight;    

BitBlt(pDC, 0, 0, iWidth, iHeight, memDC, 0, 0, SRCCOPY);

SelectObject(memDC, old_bitmap);
DeleteObject(memIMG);
DeleteDC(memDC);
ReleaseDC(hWnd, pDC);
}
[guest]
2014-06-04 02시49분
[Jongha Kim] --// 아래 부분 정정합니다.
EXPORTDLL void DrawImage(HWND hWnd);
EXPORTDLL void DrawImage(HWND hWnd)
[guest]
2014-06-04 02시51분
[Jongha Kim] --// ㅡㅡa c# 코드는 아래 함수정의 추가요.
private static extern void DrawImage(IntPtr handle);
[guest]
2014-06-04 02시52분
[Jongha Kim] 어? 그러고 보니? 계시판 뎃글의 시간이 이상하네요. ^^v
[guest]
2014-06-08 03시24분
재미있군요. ^^ 일단 소스코드로 봐서는 잘 하신 것 같은데요. 혹시, 위의 소스코드를 담은 (바로 테스트할 수 있는) 최소한의 예제 프로젝트를 구성해서 첨부해 주시겠어요? (첨부 방법은 '수정' 버튼을 눌러서 파일만 첨부하시면 됩니다.)

그리고, 덧글의 시간은 의도된 것입니다. ^^
정성태
2014-06-08 11시23분
[Jongha Kim] 댓글이후로 일이생겨 이제야 다시 일상으로 돌아왔네요.
저녁에 소스 프로젝트 업로드 한번 하겠습니다.
그사이에 구글링이 되면 좋겠는데...
관심가져 주셔서 감사합니다.
[guest]
2014-06-09 12시51분
[Jongha Kim] 우선, 증상은 찾았습니다.
UI Control Visble 속성 때문인데요. 원인은 잘 모르겠습니다.

제가 UI Control 테스트 작업한 내용입니다.

첫번째로 Form 생성자 InitializeComponent() 호출 => draw함수 호출 : 안됨. (visible=false)

두번째로 Button Click 시 draw함수 호출 : 정상.(Visible=true)

세번째로 Button Click 시 Visible=false 변경 => draw함수 호출 => visable=true 변경 : 안됨.

네번째로 Button Click 시 Visible=false 변경 => visable=true 변경 => draw함수 호출 : 안됨.

다섯번째로 Button Click 시 Visible=false 변경 => visable=true 변경 => picturebox.Refresh() or Update() 호출 => draw함수 호출 : 정상.

여섯번째로 Form 생성자 InitializeComponent(); 아래 => visble=true > picturebox.Refresh() or Udpate() 호출 => draw함수 호출 : 안됨.

제가 화면 Rendering에 대해 아직 이해가 없나봅니다.

생성자, Refresh() 이 둘의 차이인듯 한데..
조언 좀 부탁드립니다.
[guest]
2014-06-09 01시10분
Visible = True로 한번이라도 윈도우가 생성되어야 합니다. Visible = False로 시작하는 경우에는, 이후 윈도우를 보이게 할 때까지는 내부적으로 Win32 Window Handle이 생성되지 않습니다. 관련해서 Spy++을 이용해 언제 PictureBox의 윈도우 핸들이 잡히는 지 테스트 해보시면 보다 더 자세하게 알 수 있을 것입니다.
정성태
2014-06-14 04시04분
[Jongha Kim] 안녕하세요. 또 인사드려요. 또 귀찮게 좀.. ^^;

전에 질문드렸던 내용들 테스트결과 조금 정리하면
c# 핸들을 C++로 넘겨 display하는 경우
PictureBox.Image나 Control.Backgroundimage 속성에 대한 Image 바인딩 개념을 생각하였는데
Graphic Painting 개념였습니다. Onpanint가 없으면 안되는 단점이 있었습니다.
그리고 이미지를 return 받는 부분은 handle 자료형만 잘 맞춰주면 잘되더라구요.
장미빛 앞날을 생각하고 라스트 성능 테스트를 하는데...
생각했던 만큼의 결과를 보지 못했습니다.
제 테스트가 잘못된건지 성능개선에 대한 다른 대안이 필요한건지 @.@ 골뱅이 상태입니다.

제가 얻은 결론은 이렇습니다.
C++이 빠른건 맞는데 체감속도는 똑같다는 겁니다.
예를들어 c#이 10초 걸렀다면 C++은 2~3초 더빠른 7~8초 정도였습니다.
(c#에서 loop를 돌려 함수를 호출하는 경우와 Array를 c++로 넘겨 처리하는 경우도 속도 차이가 있었습니다. 후자가 빨랐습니다)
하지만, 기다리는 시간인 체감 속도가 똑같다는 겁니다. ㅡㅜ
적어도 3~5초 정도 아니 2~4초 정도 되어야 빠르다라고 느낄텐데 말이죠..

빠르게 만들고 싶은데 잘못된건가요?
아니면 다른 접근방법을 찾아보야 하는건가요? @,,@
[guest]

... 61  62  63  64  65  66  67  68  69  70  71  [72]  73  74  75  ...
NoWriterDateCnt.TitleFile(s)
728정성태11/3/20079918    답변글 [답변]: 시스템 설계에 대한 문의드립니다. [2]
726한귀순10/24/200710622SQL 2005 Express 사용시.. [3]
725이방은10/23/200710606성태님 GDI+질문있어요.. [2]
724clic...10/17/200711895clickonce 작동시 무반응입니다. [1]
722한귀순10/11/200715581Internet Explorer 7.0 에서 ClickOnce Error [3]
721이카루스10/5/200711607WCF 질문드립니다.
723정성태10/14/20079936    답변글 [답변]: WCF 질문드립니다.
720limj...10/5/200711406인증서/스마트 카드에 기반한 Managed Card - STS 구현 질문 [2]
718DJ.처리10/2/200719833[VS.NET 2008] 스마트클라이언트 게시 오류...도와주세요~ [2]파일 다운로드2
716guest9/28/200714972실행시간이 긴 com+ 객체가 죽는거 같습니다. 어떻게 해야 할지.... [3]
713하민규9/19/200710372VC++ 6과 Vista UAC ..파일 다운로드1
715정성태9/28/200711234    답변글 [답변]: VC++ 6과 Vista UAC ..
711술푼어둠이9/17/200710323사설 IP 사용 문제?? [1]파일 다운로드1
709한귀순9/14/200710112asp.net 에서의 paging 관련. [2]
708이준영9/13/200712099마우스 커서의 움직이는 속도 알아내는 좋은 방법은?
712정성태9/17/200710605    답변글 [답변]: 마우스 커서의 움직이는 속도 알아내는 좋은 방법은?
707hatu...9/10/200710615window2000과 ssl 그리고 frame [2]
701소쿠리9/5/200710730Get 으로 넘긴 한글 문자열 Respose.AddHeader 에서 filename 으로 사용시 깨짐. [1]
699유현기9/3/200710677[질문1]스마트 클라이언트에서 웹의 변수를 스마트 클라이언트에서 받아쓰기(제발도와주세요 ㅠ.ㅠ)파일 다운로드1
700정성태9/3/20079863    답변글 [답변]: [질문1]스마트 클라이언트에서 웹의 변수를 스마트 클라이언트에서 받아쓰기(제발도와주세요 ㅠ.ㅠ)
696clev...8/31/200710201Exe COM으로 만들면 혹시 Bridge dll없이도 권한 상승이 가능한가요? [1]
702clev...9/5/20079813    답변글 [답변]: Exe COM으로 만들면 혹시 Bridge dll없이도 권한 상승이 가능한가요?
695스마일8/30/20079996Visaul Studio 2005에서 디버깅이 안되요...ㅠㅠ [1]
694이호정8/29/20079997[CardSpace 관련 질문] 정리해 좋으신 글 잘 보았습니다.
698정성태9/1/20079973    답변글 [답변]: [CardSpace 관련 질문] 정리해 좋으신 글 잘 보았습니다.
704이호정9/6/200710528        답변글 답변해주신 내용 잘 봤습니다. ^_^b
... 61  62  63  64  65  66  67  68  69  70  71  [72]  73  74  75  ...