Microsoft MVP성태의 닷넷 이야기
C#과 C++을 이용한 Image 처리. [링크 복사], [링크+제목 복사],
조회: 19753
글쓴 사람
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]

... 76  77  78  79  80  81  82  83  [84]  85  86  87  88  89  90  ...
NoWriterDateCnt.TitleFile(s)
350유지연4/17/20067910smartclient DB connection관련 질문 입니다. [2]파일 다운로드1
349선재빠4/17/20067646object tag를 2개 넣으면 IE가 죽어버리네요. [2]
347박찬용4/13/20067671COM+에 관한 질문입니다. [2]
345선재빠4/11/20068406Winform을 띄울 수 있는 방법이 있나요? [3]
344선재빠4/10/20069768ASP.NET 2.0에서는 VIEWASTEXT 이란 태그옵션을 지원하지 않는군요 [3]
343선재빠4/10/20068818아래와 같은 에러가 나네요.
341선재빠4/8/20068155테스트 페이지를 보면 프레임만 나오고 안에 내용이 나오지 않는군요 [1]
340김형태4/4/20067761파일서버 관련 질문드립니다.. (데브피아 답변에 이어) [2]
339조남정4/4/20068065post 주소 읽어오기 [1]
338장두헌4/4/20069513SDK PlatForm 다시 질문 - 데브피아의 내용 [1]
337강완모4/3/20069917Cab파일이 아닌 설치용 파일로 OCX들 설치하기... [1]
335비니3/23/200610502밑에 Smart Client에 대해서 질문했던 초보입니다.. TreeView컨트롤은 보이는데 안에 내용이 안보여요. [1]
336비니3/24/20068738    답변글 [재질문]:자꾸 죄송합니다...링크페이지로 이동을 안해요.... [1]
334비니3/23/20068170Smart Client강의 따라해보다가 xml에서 활성스키마는 <Tree>,<L> 요소는 지원하지 않는다고 나와요.ㅠㅠ [1]
332정준명3/21/20068146[자문자답] VS.NET에서 COM을 참조했는데, 강력한 서명이 없다고 사용불가네요.
333정성태3/22/20067011    답변글 [답변]: [자문자답] VS.NET에서 COM을 참조했는데, 강력한 서명이 없다고 사용불가네요. [1]
330심현철3/3/20069951[질문] VS2005에서 C#으로 개발한 DLL을 Javascript에서 접근할 수 없습니다. (ActiveX with C#) [2]
329권인성2/27/20068388스마트클라이언트(clickonce) 버전관리 [1]
327권인성2/24/20068001clickonce를 통해 설치 및 업데이트하려고 하는데요...보안때문에요..
331정성태3/12/20069103    답변글 [답변]: clickonce를 통해 설치 및 업데이트하려고 하는데요...보안때문에요..
325권인성2/23/20067657SETUP 및 배포관련 [1]
326권인성2/23/20067098    답변글 [답변]: 한가지만 더 질문할게요.... [1]
323정보문2/21/20067344메일 내용에서 한글이 깨집니다. [1]파일 다운로드1
321셈토2/18/20067224SPOOL --> EMF --> TEXTOUT [1]
320정보문2/18/20067161파일의 최대 크기2 [1]
318정보문2/18/20068136파일의 최대 크기
... 76  77  78  79  80  81  82  83  [84]  85  86  87  88  89  90  ...