일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 리그오브레전드
- 압축프로그램
- 메모장
- 히어로즈오브더스톰
- NuGet
- Facebook developer
- OAuth 2.0
- ogn
- lck
- .NET
- 리뷰
- c#
- HGC
- Xamarin
- 돋보기
- 히오스
- 음악플레이어
- 롤
- 게임의 심리학
- winmm.dll
- 탐색기
- lol
- Chromium Embedded Framework
- 그림판
- Today
- Total
1인 콘텐츠 개발실
[c#] 간단한 유틸을 만들어보자! - [DIY 돋보기] 편 본문
해당 포스팅은 C#을 이용하여 간단한 유틸리티 프로그램을 개발하면서, 그 안에 쓰이는 라이브러리나 알고리즘(로직) 등을 다뤄보고 학습하는 포스팅입니다. 이 글을 통해 기존에 있던 프로그램과 비교하면서 해당 프로그램의 쓰임새, 동작 방식 등을 분석하거나 조금은 다른 관점으로 접근하여 생각해 보는것이 이 글과 앞으로 있을 포스팅의 목표입니다.
# 개요
이번에 다룰 유틸리티 프로그램은 [돋보기]입니다. 돋보기 프로그램은 화면의 모습을 확대하여 해당 부분을 집중적으로 보기 위한 유틸리티 프로그램으로써, 글씨가 작아서 이름처럼 돋보기를 놓고 보듯이 확대해서 본다거나, 프리젠테이션을 할 때나 직접 화면을 송출하면서 방송할 때 특정 영역을 집중해서 보기 위한 용도로 사용되고 있습니다.
윈도우에서 제공하는 돋보기 프로그램의 모습
윈도우 OS에서 기본으로 제공하고 있긴 하지만, 애초에 사용할 일이 적기 때문에 많이 사용하지는 않는 편입니다. 또한 현재 사용되고 있는 여러 스크린샷 프로그램들은 기본적으로 제공하고 있는 기능들이 출중해서 여러 파일 저장 방식 뿐 아니라 돋보기 기능을 제공하므로, 충분히 사용자에게 편의를 제공하고 있습니다. 따라서 오히려 스크린샷 프로그램을 다루는게 낫지 않을까 싶을 정도로 여러 기능들이 포함되어 있습니다.
반디카메라에서 제공하는 영역캡쳐 기능에는 돋보기 기능을 제공
(https://www.bandisoft.co.kr/bandicamera/help/features/)
그럼에도 불구하고 돋보기를 포스팅하는 이유는 두 가지 입니다.
첫번째로 돋보기 개발과정에서 사용되는 기본 기능들이 스크린샷 프로그램의 기능과 일맥상통하다는 점이고, 돋보기를 만들면서 스크린샷 프로그램들에 대한 기능들에 대해서도 언급할 수 있지 않을까 생각했습니다. 스크린샷 프로그램이 "순간 지정한 영역의 그대로의 모습을 그림 파일(.bmp, .png, .jpg 등 등)로 저장한다."라면, 돋보기 프로그램은 "매번 마우스 커서 주변의 영역을 실시간으로 보여준다."로 설명할 수 있습니다. 즉 돋보기의 배율을 x1.0로 설정하고 현재 영역을 그림 파일로 저장하게 된다면, 돋보기가 곧 간단한 스크린샷 프로그램이 되는것입니다.
두번째는 이번 포스팅에서는 실시간으로 마우스의 위치에 따른 영역을 보여주는 기능을 간단히 다뤄보고 싶었는데, 스크린샷 프로그램은 다룰 내용도 많고 어찌보면 주 기능은 파일 저장이기 때문에 화면을 보여주는 것이 주 기능인 돋보기 프로그램은 바로 위에 언급한 기능 구현에 온전히 집중할 수 있어서 이를 선택하게 되었습니다.
그럼 이제 [DIY 돋보기]를 한번 만들어보도록 하겠습니다.
# [DIY 돋보기] 기능
[DIY 돋보기]는 마우스가 위치한 근처 영역을 정한 배율대로 확대해서 보여주는 기능만을 갖고 있습니다. 배율은 버튼이나 단축키를 통해 x0.2 ~ x5.0까지 설정 가능합니다.
이미지 확대 방법으로는 이웃 화소 보간법이 가장 적당합니다. 이웃 화소 보간법은 말 그대로 늘어난 해상도로 인해 중간중간 빈 픽셀을 인접한 기존의 픽셀 색상값 그대로 채워 넣는 방법을 말합니다. 이 방법은 별다른 연산이 없기 때문에 매우 빠르게게 동작하는 장점이 있습니다. 또한 돋보기라는 특성상 픽셀 수가 늘어난 느낌 보다는 픽셀의 크기 자체가 커졌다는 느낌을 줘야 하기 때문에 돋보기 기능에 적용할 방법으로써는 안성맞춤인 방식입니다.
이웃 화소 보간법. 배율에 따라 많아진 픽셀을 기존 색상값 그대로 채우는 방식.
아래는 이웃 화소 보간법의 로직을 그대로 적용한 코드입니다. 또한 일단 돋보기를 비추고 싶은 영역에 돋보기 폼을 갖다댄 후 폼 가운데를 더블 클릭했을때 확대된 모습이 보이게 처리해봤습니다.
[비 주기적인 확대와 이웃 화소 보간법 적용]
private void pictureBox1_DoubleClick(object sender, EventArgs e) { int curX = Cursor.Position.X; int curY = Cursor.Position.Y; int screenWidth = 50; int screeHeight = 50; Size size = new Size(screenWidth, screeHeight); Bitmap bitmap = new Bitmap(size.Width, size.Height); double rate = 2.0; Graphics graphic = Graphics.FromImage(bitmap); graphic.CopyFromScreen(curX - (screenWidth / 2), curY - (screeHeight / 2), 0, 0, size); int zoominWidth = (int)(screenWidth * rate); int zoominHeight = (int)(screeHeight * rate); Bitmap zoomin = new Bitmap(zoominWidth, zoominHeight); for (int i = 0; i < zoominWidth; i++) { for (int j = 0; j < zoominHeight; j++) { int row = (int)(i / rate); int col = (int)(j / rate); zoomin.SetPixel(i, j, bitmap.GetPixel(row, col)); } } }
마우스 커서 위치를 가져오는 방법은 여러 방법이 있는데, 일단은 Cursor 클래스를 이용하여 가져왔습니다. 3, 4번째줄의 Cursor.Position.X와 Cursor.Position.Y는 각각 화면 해상도 기준으로 마우스 커서의 x, y 좌표값을 가져옵니다.
또한 바탕화면의 모습을 가져오는 방법은 Graphic 클래스 인스턴스를 선언 후에 CopyFromScreen 함수를 이용하여 가져옵니다. 위에서는 원본이 되는 이미지의 시작 좌표(x, y)와 옮겨 놓을 이미지 공간의 시작 좌표(x, y) 그리고 얼만큼 복사할것인지 Size를 지정해줬습니다.
따라서 커서 위치를 기준으로 width, height값의 절반보다 전에 있는 픽셀부터, 나머지 절반보다 뒤에 있는 픽셀까지의 영역을 가져오는 처리를 하였습니다. 이렇게 가져온 이미지를 보간법으로 확대하는 처리를 하였습니다.
확대하여 볼 수 있는 기능까지는 완료하였고, 이제는 마우스를 움직일 때마다 실시간으로 보여지는 기능이 필요합니다. 아래는 코드 최적화와 함께 그 기능을 적용한 코드입니다.
[주기적인 확대와 PictureBox의 Stretch SizeMode를 이용한 최적화]
private void timer1_Tick(object sender, EventArgs e) { label1.Text = "배율 : x" + rate; Size size = new Size(pictureBox1.Width, pictureBox1.Height); Bitmap bitmap = new Bitmap((int)(size.Width / rate), (int)(size.Height / rate)); Graphics graphics = Graphics.FromImage(bitmap); graphics.CopyFromScreen((int)(MousePosition.X - size.Width / (rate * 2)), (int)(MousePosition.Y - size.Height / (rate * 2)), 0, 0, size, CopyPixelOperation.SourceCopy); pictureBox1.Image = bitmap; }
Timer를 추가하여 틱으로 설정한 시간마다 이미지를 갱신할 수 있도록 작성하였습니다. 또한 PictureBox의 SizeMode 속성값 중에 "StretchImage"를 선택하면 PictureBox보다 작은 이미지를 강제로 늘려주는데 이를 활용하면 위의 로직만으로도 배율이 적용된 이미지를 보여줄 수 있습니다.
[배율 확대/축소 기능]
private void button1_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left && rate < 5.0) { rate += 0.1; } } private void button2_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left && rate > 0.2) { rate -= 0.1; } } private void button1_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == '+' && rate < 5.0) { rate += 0.1; } else if (e.KeyChar == '-' && rate > 0.2) { rate -= 0.1; } } private void Form_MouseWheel(object sender, MouseEventArgs e) { if (e.Delta < 0 && rate > 0.2) { rate -= 0.1; } else if (e.Delta > 0 && rate < 5.0) { rate += 0.1; } }
# 완성 및 마무리
- [DIY 돋보기] 소스 파일 : https://github.com/hyunil-stdlib/SimpleMagnifier
(소스코드와 실행 파일을 받으실 수 있습니다.)
[DIY 돋보기] 프로그램이 적용된 모습
프로그램을 실행하면 윈도우 폼이 열리고 마우스를 움직일때 마다 해당 영역을 보여줍니다.
배율 조절 버튼인 ▲,▼ 버튼뿐만 아니라 키보드의 "+", "-"키와, 마우스 휠로 배율 확대/축소 조절이 가능합니다. 다만 돋보기 프로그램에서 벗어난채 다른 프로그램이 활성화 되면 단축키와 마우스 휠이 적용되지 않는 단점이 있습니다. 이 부분을 수정하고 UI를 다듬으면 윈도우에서 제공하는 돋보기 프로그램과 비등해질듯 합니다.
프로그램 창이 웬만한 프로그램 창 보다 항상 위에 있게 하고 싶으면 Form 속성값 중에 TopMost값을 True로 설정하면 됩니다.
TopMost는 창이 보여지는 순서에서 우선권을 가지게 함.
이번 [DIY 돋보기] 포스팅은 이것으로 마치고, 다음에 올라오게 될 포스팅도 기대해주시면 감사하겠습니다.
# 참조
- Lupa, Lente de Aumento " Magnifier " C# - HD - Sko.Lex : https://youtu.be/zWbtnV4TupE
- 반디카메라 주요 기능 설명 : https://www.bandisoft.co.kr/bandicamera/help/features/
- 마이크로소프트 Developer Network (msdn) : https://msdn.microsoft.com/ko-kr/library/618ayhy6.aspx
'개발&제작 > 프로그램' 카테고리의 다른 글
[c#] 간단한 유틸을 만들어보자! - [DIY 탐색기] 편 (0) | 2017.04.21 |
---|---|
[c#] 간단한 유틸을 만들어보자! - [DIY 그림판] 편 (4) | 2017.04.14 |
[c#] 간단한 유틸을 만들어보자! - [DIY 메모장] 편 (0) | 2017.04.01 |
[c#] CEF를 이용한 페이스북 자동화 프로그램 (5) (3) | 2017.03.02 |
[c#] CEF를 이용한 페이스북 자동화 프로그램 (4) (0) | 2017.02.27 |