728x90
반응형
728x170
▶ BitmapHelper.cs
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace TestProject
{
/// <summary>
/// 비트맵 헬퍼
/// </summary>
public class BitmapHelper
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Public
#region Field
/// <summary>
/// 이미지 바이트 배열
/// </summary>
public byte[] ImageByteArray;
/// <summary>
/// 행 크기 바이트 수
/// </summary>
public int RowSizeByteCount;
/// <summary>
/// 픽셀 데이터 크기
/// </summary>
public const int PixelDataSize = 32;
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 비트맵
/// </summary>
private Bitmap bitmap;
/// <summary>
/// 비트맵 데이터
/// </summary>
private BitmapData bitmapData;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 너비 - Width
/// <summary>
/// 너비
/// </summary>
public int Width
{
get
{
return this.bitmap.Width;
}
}
#endregion
#region 높이 - Height
/// <summary>
/// 높이
/// </summary>
public int Height
{
get
{
return this.bitmap.Height;
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - BitmapHelper(bitmap)
/// <summary>
/// 생성자
/// </summary>
/// <param name="bitmap">비트맵</param>
public BitmapHelper(Bitmap bitmap)
{
this.bitmap = bitmap;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 비트맵 잠그기 - LockBitmap()
/// <summary>
/// 비트맵 잠그기
/// </summary>
public void LockBitmap()
{
Rectangle boundRectangle = new Rectangle(0, 0, this.bitmap.Width, this.bitmap.Height);
this.bitmapData = this.bitmap.LockBits
(
boundRectangle,
ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb
);
RowSizeByteCount = this.bitmapData.Stride;
int totalSize = this.bitmapData.Stride * this.bitmapData.Height;
ImageByteArray = new byte[totalSize];
Marshal.Copy(this.bitmapData.Scan0, ImageByteArray, 0, totalSize);
}
#endregion
#region 비트맵 잠금 해제하기 - UnlockBitmap()
/// <summary>
/// 비트맵 잠금 해제하기
/// </summary>
public void UnlockBitmap()
{
int totalSize = this.bitmapData.Stride * this.bitmapData.Height;
Marshal.Copy(ImageByteArray, 0, this.bitmapData.Scan0, totalSize);
this.bitmap.UnlockBits(this.bitmapData);
ImageByteArray = null;
this.bitmapData = null;
}
#endregion
#region 픽셀 구하기 - GetPixel(x, y, red, green, blue, alpha)
/// <summary>
/// 픽셀 구하기
/// </summary>
/// <param name="x">X</param>
/// <param name="y">Y</param>
/// <param name="red">빨강색</param>
/// <param name="green">녹색</param>
/// <param name="blue">파랑색</param>
/// <param name="alpha">불투명도</param>
public void GetPixel(int x, int y, out byte red, out byte green, out byte blue, out byte alpha)
{
int i = y * this.bitmapData.Stride + x * 4;
blue = ImageByteArray[i++];
green = ImageByteArray[i++];
red = ImageByteArray[i++];
alpha = ImageByteArray[i ];
}
#endregion
#region 픽셀 설정하기 - SetPixel(x, y, red, green, blue, alpha)
/// <summary>
/// 픽셀 설정하기
/// </summary>
/// <param name="x">X</param>
/// <param name="y">Y</param>
/// <param name="red">빨강색</param>
/// <param name="green">녹색</param>
/// <param name="blue">파랑색</param>
/// <param name="alpha">불투명도</param>
public void SetPixel(int x, int y, byte red, byte green, byte blue, byte alpha)
{
int i = y * this.bitmapData.Stride + x * 4;
ImageByteArray[i++] = blue;
ImageByteArray[i++] = green;
ImageByteArray[i++] = red;
ImageByteArray[i ] = alpha;
}
#endregion
#region 빨강색 구하기 - GetRed(x, y)
/// <summary>
/// 빨강색 구하기
/// </summary>
/// <param name="x">X</param>
/// <param name="y">Y</param>
/// <returns>빨강색</returns>
public byte GetRed(int x, int y)
{
int i = y * this.bitmapData.Stride + x * 4;
return ImageByteArray[i + 2];
}
#endregion
#region 빨강색 설정하기 - SetRed(x, y, red)
/// <summary>
/// 빨강색 설정하기
/// </summary>
/// <param name="x">X</param>
/// <param name="y">Y</param>
/// <param name="red">빨강색</param>
public void SetRed(int x, int y, byte red)
{
int i = y * this.bitmapData.Stride + x * 4;
ImageByteArray[i + 2] = red;
}
#endregion
#region 녹색 구하기 - GetGreen(x, y)
/// <summary>
/// 녹색 구하기
/// </summary>
/// <param name="x">X</param>
/// <param name="y">Y</param>
/// <returns>녹색</returns>
public byte GetGreen(int x, int y)
{
int i = y * this.bitmapData.Stride + x * 4;
return ImageByteArray[i + 1];
}
#endregion
#region 녹색 설정하기 - SetGreen(x, y, green)
/// <summary>
/// 녹색 설정하기
/// </summary>
/// <param name="x">X</param>
/// <param name="y">Y</param>
/// <param name="green">녹색</param>
public void SetGreen(int x, int y, byte green)
{
int i = y * this.bitmapData.Stride + x * 4;
ImageByteArray[i + 1] = green;
}
#endregion
#region 파랑색 구하기 - GetBlue(x, y)
/// <summary>
/// 파랑색 구하기
/// </summary>
/// <param name="x">X</param>
/// <param name="y">Y</param>
/// <returns>파랑색</returns>
public byte GetBlue(int x, int y)
{
int i = y * this.bitmapData.Stride + x * 4;
return ImageByteArray[i];
}
#endregion
#region 파랑색 설정하기 - SetBlue(x, y, blue)
/// <summary>
/// 파랑색 설정하기
/// </summary>
/// <param name="x">X</param>
/// <param name="y">Y</param>
/// <param name="blue">파랑색</param>
public void SetBlue(int x, int y, byte blue)
{
int i = y * this.bitmapData.Stride + x * 4;
ImageByteArray[i] = blue;
}
#endregion
#region 붙투명도 구하기 - GetAlpha(x, y)
/// <summary>
/// 붙투명도 구하기
/// </summary>
/// <param name="x">X</param>
/// <param name="y">Y</param>
/// <returns>불투명도</returns>
public byte GetAlpha(int x, int y)
{
int i = y * this.bitmapData.Stride + x * 4;
return ImageByteArray[i + 3];
}
#endregion
#region 불투명도 설정하기 - SetAlpha(x, y, alpha)
/// <summary>
/// 불투명도 설정하기
/// </summary>
/// <param name="x">X</param>
/// <param name="y">Y</param>
/// <param name="alpha">불투명도</param>
public void SetAlpha(int x, int y, byte alpha)
{
int i = y * this.bitmapData.Stride + x * 4;
ImageByteArray[i + 3] = alpha;
}
#endregion
}
}
728x90
▶ MainForm.cs
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;
namespace TestProject
{
/// <summary>
/// 메인 폼
/// </summary>
public partial class MainForm : Form
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary>
/// 생성자
/// </summary>
public MainForm()
{
InitializeComponent();
this.openMenuItem.Click += openMenuItem_Click;
this.saveAsMenuItem.Click += saveAsMenuItem_Click;
this.exitMenuItem.Click += exitMenuItem_Click;
this.cutoffScrollBar.Scroll += cutoffScrollBar_Scroll;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 열기 메뉴 항목 클릭시 처리하기 - openMenuItem_Click(sender, e)
/// <summary>
/// 열기 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void openMenuItem_Click(object sender, EventArgs e)
{
if(this.openFileDialog.ShowDialog() == DialogResult.OK)
{
this.sourcePictureBox.Image = GetBitmap(this.openFileDialog.FileName);
ProcessBinaryContrast();
}
}
#endregion
#region 다른 이름으로 저장 메뉴 항목 클릭시 처리하기 - saveAsMenuItem_Click(sender, e)
/// <summary>
/// 다른 이름으로 저장 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void saveAsMenuItem_Click(object sender, EventArgs e)
{
if(this.saveFileDialog.ShowDialog() == DialogResult.OK)
{
SaveBitmap((Bitmap)this.targetPictureBox.Image, this.saveFileDialog.FileName);
}
}
#endregion
#region 종료 메뉴 항목 클릭시 처리하기 - exitMenuItem_Click(sender, e)
/// <summary>
/// 종료 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void exitMenuItem_Click(object sender, EventArgs e)
{
Close();
}
#endregion
#region 컷오프 스크롤바 스크롤시 처리하기 - cutoffScrollBar_Scroll(sender, e)
/// <summary>
/// 컷오프 스크롤바 스크롤시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void cutoffScrollBar_Scroll(object sender, ScrollEventArgs e)
{
this.cutoffValueLabel.Text = this.cutoffScrollBar.Value.ToString();
ProcessBinaryContrast();
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 비트맵 구하기 - GetBitmap(filePath)
/// <summary>
/// 비트맵 구하기
/// </summary>
/// <param name="filePath">파일 경로</param>
/// <returns>비트맵</returns>
private Bitmap GetBitmap(string filePath)
{
using(Bitmap bitmap = new Bitmap(filePath))
{
return new Bitmap(bitmap);
}
}
#endregion
#region 이진 대비 적용하기 - ApplyBinaryContrast(targetBitmap, cutoff)
/// <summary>
/// 이진 대비 적용하기
/// </summary>
/// <param name="targetBitmap">타겟 비트맵</param>
/// <param name="cutoff">컷오프</param>
private void ApplyBinaryContrast(Bitmap targetBitmap, int cutoff)
{
BitmapHelper helper = new BitmapHelper(targetBitmap);
helper.LockBitmap();
for(int y = 0; y < targetBitmap.Height; y++)
{
for(int x = 0; x < targetBitmap.Width; x++)
{
byte red;
byte green;
byte blue;
byte alpha;
helper.GetPixel(x, y, out red, out green, out blue, out alpha);
if(red + green + blue > cutoff)
{
helper.SetPixel(x, y, 255, 255, 255, 255);
}
else
{
helper.SetPixel(x, y, 0, 0, 0, 255);
}
}
}
helper.UnlockBitmap();
}
#endregion
#region 이진 대비 처리하기 - ProcessBinaryContrast()
/// <summary>
/// 이진 대비 처리하기
/// </summary>
private void ProcessBinaryContrast()
{
if(this.sourcePictureBox.Image == null)
{
return;
}
Cursor = Cursors.WaitCursor;
Bitmap bitmap = new Bitmap(this.sourcePictureBox.Image);
ApplyBinaryContrast(bitmap, 3 * this.cutoffScrollBar.Value);
if(this.targetPictureBox.Image != null)
{
this.targetPictureBox.Image.Dispose();
}
this.targetPictureBox.Image = bitmap;
this.targetPictureBox.Left = this.sourcePictureBox.Right + 4;
Cursor = Cursors.Default;
}
#endregion
#region 비트맵 저장하기 - SaveBitmap(bitmap, filePath)
/// <summary>
/// 비트맵 저장하기
/// </summary>
/// <param name="bitmap">비트맵</param>
/// <param name="filePath">파일 경로</param>
public void SaveBitmap(Bitmap bitmap, string filePath)
{
string extension = Path.GetExtension(filePath);
switch(extension.ToLower())
{
case ".bmp" : bitmap.Save(filePath, ImageFormat.Bmp ); break;
case ".exif" : bitmap.Save(filePath, ImageFormat.Exif); break;
case ".gif" : bitmap.Save(filePath, ImageFormat.Gif ); break;
case ".jpg" :
case ".jpeg" : bitmap.Save(filePath, ImageFormat.Jpeg); break;
case ".png" : bitmap.Save(filePath, ImageFormat.Png ); break;
case ".tif" :
case ".tiff" : bitmap.Save(filePath, ImageFormat.Tiff); break;
default : throw new NotSupportedException("Unknown file extension " + extension);
}
}
#endregion
}
}
728x90
반응형
그리드형(광고전용)
'C# > WinForm' 카테고리의 다른 글
[C#/WINFORM] Control 클래스 : WndProc 메소드를 사용해 데이터 수신하기 (0) | 2020.12.05 |
---|---|
[C#/WINFORM] 특정 프로세스의 윈도우 핸들 구하기 (0) | 2020.12.05 |
[C#/WINFORM] 누겟 설치 : Microsoft.Windows.Shell (0) | 2020.11.17 |
[C#/WINFORM] TextBox 클래스 : 영숫자/통화/날짜/정수/마스크/숫자 입력하기 (0) | 2020.11.13 |
[C#/WINFORM] SendKeys 클래스 : Send 정적 메소드를 사용해 이동 키 누르기 (0) | 2020.11.12 |
[C#/WINFORM] 비트맵 이진화 적용하기 (0) | 2020.10.31 |
[C#/WINFORM] Graphics 클래스 : CopyFromScreen 메소드를 사용해 RichTextBox 이미지 캡처하기 (0) | 2020.10.28 |
[C#/WINFORM] ComboBox 클래스 : KeyPress/DropDownClosed 이벤트를 사용해 콤보 박스 열기 (0) | 2020.10.28 |
[C#/WINFORM] Graphics 클래스 : 그래픽 변환 사용하기 (0) | 2020.10.28 |
[C#/WINFORM] PowerStatus 클래스 : 배터리 정보 구하기 (0) | 2020.09.24 |
[C#/WINFORM] 마우스/키보드 후킹하기 (0) | 2020.09.23 |
댓글을 달아 주세요