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

1  2  3  4  5  6  [7]  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
5808근우1/30/202310791WPF 에서 UserControl 과 ControlTemplate 의 차이점은 무엇인가요? [6]
5807궁금맨1/28/202313127C# 10 책에 나온 예제의 결과가 제 컴에서는 좀 달라서요. 이유가 궁금합니다. [1]
5806스레드1/25/202310346총정리 - 다양한 스레드들 [초안] [1]파일 다운로드1
5805어웨이트1/25/202310133Taskcontinuewith vs Async/Await [2]파일 다운로드1
5804나이많은...1/25/20239923MS의 Dependency Injection(DI)에 AddSingleton으로 등록된 객체의 Event 등록후 사용시 앱 종료시 별도로 Event를 해지해야 하나요? [2]
5803dssc...1/24/202310324드라이브 문자를 통해서 물리 디스크 명칭을 알아내고 싶습니다. [1]
5802모바일앱1/22/202310799XAMARINE vs Android Studio [7]
5801블루투스1/19/202311477WPF 은행지폐계수기 개조 후 결과값 서버 전송 [2]파일 다운로드1
5800김민아1/19/202311652안녕하세요 가비지 컬렉터 동작 원리 중 궁금한점이 있습니다 [5]
5799guest1/19/202310955C# 공유폴더 내 Acess 디비 공유 [2]
5798kss1/19/202310112책 오탈인가요? [1]
5797이거비버1/19/20239895C# 공부 이후 MS 프레임워크.. 어느것을 공부해야할까요? 너무 많아서 정신이 없네요 [5]
5796guest1/19/20239678해킹 test [3]
5795동기1/18/20239009동기 스레드와 메서드와 While [2]
5794박규동1/18/20239197.net publish 할때마다 runtimeconfig 값이 바뀌는 현상 [1]
5793후후훗1/18/20239685.NET Core 에서 사용중인 함수 후킹 방법 [2]
5792Will...1/18/20239564소스코드 Log Write 기능을 리스트업 질문 [9]
5791PLC1/16/202310217C# - 실시간 5개 룸 모니터링 [15]
5790집으로 ...1/13/20239845[UI 멈춤 현상]deadlock 관련 글을 보고 혹시나 하고 문의 드립니다. [4]
5789guest1/10/20239731스레드와 Async Task [2]파일 다운로드1
5788kr11/10/202310182C# 에서 제공하는 컬렉션들의 차이점이 궁금합니다. [3]
5787stack1/10/202310082STACKOVERFLOW [1]
5786Dev ...1/9/202311928익명 클래스 말고 익명 구조체는 불가능한걸까요? [4]
5785음성인식1/8/202311641음성인식 System.Speech - 문법에 사용된 언어가 음성 인식기의 언어와 일치하지 않습니다. [2]
5784MS워드1/8/202310867MS워드에서 ctrl Z는 클립보드를 이용하나요? 아니면 참조자 이용하나요? [7]
5783구직자1/7/202310136C#개발자 구인광고와 초급개발자 [3]파일 다운로드1
1  2  3  4  5  6  [7]  8  9  10  11  12  13  14  15  ...