Microsoft MVP성태의 닷넷 이야기
C#과 C++을 이용한 Image 처리. [링크 복사], [링크+제목 복사]
조회: 13408
글쓴 사람
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++ 데이타 타입 질문에 대한
답변도 자세히 좀 부탁드립니다.
자료를 찾아보았는데 쉽게 검색이 안되네요.
혹, 좋은 서적도 추천해주시면 감사하겠습니다.

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







donaricano-btn



[최초 등록일: ]
[최종 수정일: 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으로 정의행하나요?
[손님]
2014-06-03 07시27분
C++에서 이미지를 만들었으면, 그에 대한 포인터 주소값만 C#에 전달하면 됩니다. IntPtr로 전달하시면 될 듯한데요. 어렵게 생각할 필요없습니다. 어차피 같은 프로세스의 주소이기 때문에.
정성태
2014-06-03 01시31분
[Jongha Kim] 답변 감사합니다.
다시 한번 살펴보고 있습니다.
어렵게 생각안하려하는데 그게..ㅎㅎ
[손님]
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);
}
[손님]
2014-06-04 02시49분
[Jongha Kim] --// 아래 부분 정정합니다.
EXPORTDLL void DrawImage(HWND hWnd);
EXPORTDLL void DrawImage(HWND hWnd)
[손님]
2014-06-04 02시51분
[Jongha Kim] --// ㅡㅡa c# 코드는 아래 함수정의 추가요.
private static extern void DrawImage(IntPtr handle);
[손님]
2014-06-04 02시52분
[Jongha Kim] 어? 그러고 보니? 계시판 뎃글의 시간이 이상하네요. ^^v
[손님]
2014-06-08 03시24분
재미있군요. ^^ 일단 소스코드로 봐서는 잘 하신 것 같은데요. 혹시, 위의 소스코들르 담은 (바로 테스트할 수 있는) 최소한의 예제 프로젝트를 구성해서 첨부해 주시겠어요? (첨부 방법은 '수정' 버튼을 눌러서 파일만 첨부하시면 됩니다.)

그리고, 덧글의 시간은 의도된 것입니다. ^^
정성태
2014-06-08 11시23분
[Jongha Kim] 댓글이후로 일이생겨 이제야 다시 일상으로 돌아왔네요.
저녁에 소스 프로젝트 업로드 한번 하겠습니다.
그사이에 구글링이 되면 좋겠는데...
관심가져 주셔서 감사합니다.
[손님]
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() 이 둘의 차이인듯 한데..
조언 좀 부탁드립니다.
[손님]
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초 정도 되어야 빠르다라고 느낄텐데 말이죠..

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

... 31  32  33  34  35  36  37  38  [39]  40  41  42  43  44  45  ...
NoWriterDateCnt.TitleFile(s)
1303김동진8/7/20146579vmware환경에서 Guest IP를 192대역으로 받을 수 있는 방법은 없을까요~? [3]
1302김문경7/31/20145896스마트클라이언트 오라클 연결 [1]
1314이재균8/20/20145415    답변글 [답변]: 스마트클라이언트 오라클 연결
1300아로스7/28/201416507c# 인터넷 임시 파일 삭제 문의 [12]파일 다운로드1
1299서동원7/28/20145837안녕하세요. 혹시 Internet_Zone과 관련된문제인가 해서 질문드립니다. [1]
1298(none)7/25/20149970(글쓴이의 요청으로 삭제합니다.) [15]
1295서동원7/22/20146766안녕하세요. 스마트클라이언트에 대해 질문드립니다. [2]파일 다운로드1
1294(none)7/20/20146167(글쓴이의 요청으로 삭제합니다.) [2]
1293VS20137/20/20147043VS2013 Ultimate에 Windows Phone 프로젝트 템플릿 추가 방법 문의 [1]파일 다운로드2
1292(none)7/20/20145275(글쓴이의 요청으로 삭제합니다.) [2]
1291zino7/16/20145620chromium 배포본 만들기~ [1]
1290(none)7/13/20146524(글쓴이의 요청으로 삭제합니다.) [3]
1288박주만7/8/201415681C# 서비스 기반 데이터베이스(mdf) & InstallShield Limited Edition 설치 및 배포 [2]파일 다운로드1
1287김용환7/8/201413251오라클 db 사용관련 문의입니다. [4]파일 다운로드1
1286C#조으다7/8/20145774WebBrowser 공유기 관리 웹 페이지 인증 [3]
1285C#조으다7/5/20146424IE DocumentComplete 이벤트가 발생되지 않습니다. [2]
1284(none)7/4/20146160(글쓴이의 요청으로 삭제합니다.) [3]
1283김영대7/3/20148387안녕하십니까 정성태님 죄송하지만 SmartClient 에 관한 질문이 있습니다. [9]
1282(none)7/2/20145543(글쓴이의 요청으로 삭제합니다.) [2]
1281(none)7/1/20146227(글쓴이의 요청으로 삭제합니다.) [4]
1280동동이6/25/20146304안녕하세요. ocx의 비동기 또는 쓰레드에서 호출 [1]
1279(none)6/23/20146141(글쓴이의 요청으로 삭제합니다.) [17]
1278이상식6/19/20147283.net DLL 내 자바스크립트를 수정 또는 재정의 할 수 있을까요? [3]
1277김솔지6/18/20145527silverlight에서 datagrid, listbox질문이여 [2]
1276정우석6/16/20145209쿠키 [1]
1274김솔지6/10/20148940배포 페이지 url을 얻고 싶습니다. [8]
... 31  32  33  34  35  36  37  38  [39]  40  41  42  43  44  45  ...