Microsoft MVP성태의 닷넷 이야기
C#과 C++을 이용한 Image 처리. [링크 복사], [링크+제목 복사],
조회: 19480
글쓴 사람
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)
816박진오7/29/200910659다국어 사이트의 컨텐츠 저장 방식에 대해.. [2]
814서광원7/16/200919660IWebBrowser2를 이용한 프로그램에서 javascript의 alert 창 무시하는 법? [1]
813윤상균7/16/200910905비관리코드와의 상호운용에서 마샬링 질문 [1]
812김현우7/13/200911320usercontrol은 mdi container가 될수 없는데 이를 구현할 방법은 무엇일런지요? [2]
811조민수7/3/200910931MSDN Magazine 한글화 않되나요? [1]
810세경6/29/200916234SmartClient Vista 64bit IE7 [4]
809윤석준6/24/200916161IE -nomerge 옵션으로 새창을 열려고 합니다. [1]
808한승훈6/4/200914304dll import하기 위해 struct 구성시에 struct가 struct를 가지고 있고 포함된 struct가 ByValArray형태일때 해결 [1]
806곰티5/26/200912783defcon pro 설치 원천 봉쇄 방법 문의 [3]
802채승수5/8/200912091신뢰사이트 등록/적용에 관해 질문드립니다. [1]
801채승수4/15/200912826IE8 새세션을 코드로 구현할수 없을까요 [1]
800신동열4/7/200913264IE8에서 스마트 클라이언트 로딩 문제 [2]
7993/27/200916966이벤트 로그 오류 [1]
798천해3/26/200913258IE8.0 에 관해 질문 드립니다. [2]
797궁금..3/23/200913146IE 8 관련 질문.. [2]
796정성태3/20/200912118스마트클라이언트와 ActiveX에 관한 질문 [1]
795김기용3/19/200911726[질문] DHTML 다이얼로그 관련 [2]
794박평옥3/18/200912145Vista에서 URL Shortcut 실행 시 SetSite가 두 번 호출되는 증상에 관해 조언 부탁드립니다. [2]
792김기용3/12/200911302어제 세미나 잘 들었습니다. 질문사항이 있습니다.(ie8 마이그레이션 관련) [4]
791vb표성백2/17/200916531ATL 로 만든 COM 에 문자열 전달하기! C#에서 어떻게 하나요? [1]
790고민중2/16/20099645vista에 vs2005를 사용중입니다. [1]
789지언2/14/200911767MFC & C#(COM) 호환 관련하여 답변좀 부탁드립니다 [2]
788하루야채2/3/200910987스마트클라이언트 Windowless 설정에 대해서 문의드립니다. [2]
787궁금이2/2/200911256TFS 관련하여 질문드리고자 합니다. [2]
786맨날맑음1/30/200912324WPF를 SmartClient로 배포할순 없을까요? [2]
785정성우12/16/200811581Vista 환경에서 VB6로 개발한 어플리케이션이 IE 통해서는 런칭이 안됩니다.. [4]
... 61  62  63  64  65  66  67  68  [69]  70  71  72  73  74  75  ...