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 const int PIXEL_BIT_COUNT = 32;
/// <summary>
/// 이미지 바이트 배열
/// </summary>
public byte[] ImageByteArray;
/// <summary>
/// 행 바이트 수
/// </summary>
public int RowByteCount;
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 소스 비트맵
/// </summary>
private Bitmap sourceBitmap;
/// <summary>
/// 소스 비트맵 데이터
/// </summary>
private BitmapData sourceBitmapData;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 너비 - Width
/// <summary>
/// 너비
/// </summary>
public int Width
{
get
{
return this.sourceBitmap.Width;
}
}
#endregion
#region 높이 - Height
/// <summary>
/// 높이
/// </summary>
public int Height
{
get
{
return this.sourceBitmap.Height;
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - BitmapHelper(sourceBitmap)
/// <summary>
/// 생성자
/// </summary>
/// <param name="sourceBitmap">소스 비트맵</param>
public BitmapHelper(Bitmap sourceBitmap)
{
this.sourceBitmap = sourceBitmap;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Public
#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.sourceBitmapData.Stride + x * 4;
blue = ImageByteArray[i++];
green = ImageByteArray[i++];
red = ImageByteArray[i++];
alpha = ImageByteArray[i ];
}
#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.sourceBitmapData.Stride + x * 4;
return ImageByteArray[i + 2];
}
#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.sourceBitmapData.Stride + x * 4;
return ImageByteArray[i + 1];
}
#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.sourceBitmapData.Stride + x * 4;
return ImageByteArray[i];
}
#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.sourceBitmapData.Stride + x * 4;
return ImageByteArray[i + 3];
}
#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.sourceBitmapData.Stride + x * 4;
ImageByteArray[i++] = blue;
ImageByteArray[i++] = green;
ImageByteArray[i++] = red;
ImageByteArray[i ] = alpha;
}
#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.sourceBitmapData.Stride + x * 4;
ImageByteArray[i + 2] = red;
}
#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.sourceBitmapData.Stride + x * 4;
ImageByteArray[i + 1] = green;
}
#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.sourceBitmapData.Stride + x * 4;
ImageByteArray[i] = blue;
}
#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.sourceBitmapData.Stride + x * 4;
ImageByteArray[i + 3] = alpha;
}
#endregion
#region 비트맵 잠금 설정하기 - LockBitmap()
/// <summary>
/// 비트맵 잠금 설정하기
/// </summary>
public void LockBitmap()
{
Rectangle sourceRectangle = new Rectangle
(
0,
0,
this.sourceBitmap.Width,
this.sourceBitmap.Height
);
this.sourceBitmapData = this.sourceBitmap.LockBits
(
sourceRectangle,
ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb
);
RowByteCount = this.sourceBitmapData.Stride;
int totalByteCount = this.sourceBitmapData.Stride * this.sourceBitmapData.Height;
ImageByteArray = new byte[totalByteCount];
Marshal.Copy(this.sourceBitmapData.Scan0, ImageByteArray, 0, totalByteCount);
}
#endregion
#region 비트맵 잠금 해제하기 - UnlockBitmap()
/// <summary>
/// 비트맵 잠금 해제하기
/// </summary>
public void UnlockBitmap()
{
int totalByteCount = this.sourceBitmapData.Stride * this.sourceBitmapData.Height;
Marshal.Copy(ImageByteArray, 0, this.sourceBitmapData.Scan0, totalByteCount);
this.sourceBitmap.UnlockBits(this.sourceBitmapData);
ImageByteArray = null;
this.sourceBitmapData = null;
}
#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
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Enumeration
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 픽셀 타입 - PixelType
/// <summary>
/// 픽셀 타입
/// </summary>
private enum PixelType
{
/// <summary>
/// 적색
/// </summary>
Red,
/// <summary>
/// 녹색
/// </summary>
Green,
/// <summary>
/// 청색
/// </summary>
Blue,
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 소스 비트맵
/// </summary>
private Bitmap sourceBitmap = null;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary>
/// 생성자
/// </summary>
public MainForm()
{
InitializeComponent();
this.openMenuItem.Click += openMenuItem_Click;
this.saveAsMenuItem.Click += saveAsMenuItem_Click;
this.applyButton.Click += applyButton_Click;
}
#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.sourceBitmap = GetBitmap(this.openFileDialog.FileName);
this.pictureBox.Image = this.sourceBitmap;
this.pictureBox.Visible = true;
this.saveAsMenuItem.Enabled = true;
this.applyButton.Enabled = true;
}
}
#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)
{
SaveImage(this.pictureBox.Image, this.saveFileDialog.FileName);
}
}
#endregion
#region 적용 버튼 클릭시 처리하기 - applyButton_Click(sender, e)
/// <summary>
/// 적용 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void applyButton_Click(object sender, EventArgs e)
{
PixelType pixelType = PixelType.Red;
if(this.greenRadioButton.Checked)
{
pixelType = PixelType.Green;
}
else if(this.blueRadioButton.Checked)
{
pixelType = PixelType.Blue;
}
int threshold = int.Parse(this.thresholdTextBox.Text);
float multiplier = float.Parse(this.multiplierTextBox.Text);
this.pictureBox.Image = GetBitmap(this.sourceBitmap, pixelType, threshold, multiplier);
}
#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 이미지 저장하기 - SaveImage(image, filePath)
/// <summary>
/// 이미지 저장하기
/// </summary>
/// <param name="image">이미지</param>
/// <param name="filePath">파일 경로</param>
private void SaveImage(Image image, string filePath)
{
string fileExtension = Path.GetExtension(filePath);
switch(fileExtension.ToLower())
{
case ".bmp" : image.Save(filePath, ImageFormat.Bmp ); break;
case ".exif" : image.Save(filePath, ImageFormat.Exif); break;
case ".gif" : image.Save(filePath, ImageFormat.Gif ); break;
case ".jpg" :
case ".jpeg" : image.Save(filePath, ImageFormat.Jpeg); break;
case ".png" : image.Save(filePath, ImageFormat.Png ); break;
case ".tif" :
case ".tiff" : image.Save(filePath, ImageFormat.Tiff); break;
default : throw new NotSupportedException("Unknown file extension " + fileExtension);
}
}
#endregion
#region 비트맵 구하기 - GetBitmap(sourceBitmap, pixelType, threshold, multiplier)
/// <summary>
/// 비트맵 구하기
/// </summary>
/// <param name="sourceBitmap">소스 비트맵</param>
/// <param name="pixelType">픽셀 타입</param>
/// <param name="threshold">임계값</param>
/// <param name="multiplier">승수</param>
/// <returns>비트맵</returns>
private Bitmap GetBitmap(Bitmap sourceBitmap, PixelType pixelType, int threshold, float multiplier)
{
Bitmap targetBitmap = new Bitmap(sourceBitmap);
BitmapHelper targetBitmapHelper = new BitmapHelper(targetBitmap);
targetBitmapHelper.LockBitmap();
int targetWidth = targetBitmap.Width;
int targetHeight = targetBitmap.Height;
for(int y = 0; y < targetHeight; y++)
{
for(int x = 0; x < targetWidth; x++)
{
byte red;
byte green;
byte blue;
byte alpha;
targetBitmapHelper.GetPixel(x, y, out red, out green, out blue, out alpha);
switch(pixelType)
{
case PixelType.Red :
if((red >= green + threshold) && (red > blue + threshold))
{
int newRed = (int)(red * multiplier);
if(newRed > 255)
{
newRed = 255;
}
else if(newRed < 0)
{
newRed = 0;
}
red = (byte)newRed;
}
break;
case PixelType.Green :
if((green >= red + threshold) && (green > blue + threshold))
{
int newGreen = (int)(green * multiplier);
if(newGreen > 255)
{
newGreen = 255;
}
else if(newGreen < 0)
{
newGreen = 0;
}
green = (byte)newGreen;
}
break;
case PixelType.Blue :
if((blue >= red + threshold) && (blue > green + threshold))
{
int newBlue = (int)(blue * multiplier);
if(newBlue > 255)
{
newBlue = 255;
}
else if(newBlue < 0)
{
newBlue = 0;
}
blue = (byte)newBlue;
}
break;
}
targetBitmapHelper.SetPixel(x, y, red, green, blue, alpha);
}
}
targetBitmapHelper.UnlockBitmap();
return targetBitmap;
}
#endregion
}
}
728x90
반응형
그리드형(광고전용)
'C# > WinForm' 카테고리의 다른 글
[C#/WINFORM] Application 클래스 : SetSuspendState 정적 메소드를 사용해 절전 모드 만들기 (0) | 2020.12.27 |
---|---|
[C#/WINFORM] 지정 시간 경과 후 절전 모드에서 활성화하기 (0) | 2020.12.27 |
[C#/WINFORM] Graphics 클래스 : DrawImage 메소드 사용시 이미지 어트리뷰트 설정하기 (0) | 2020.12.27 |
[C#/WINFORM] Image 클래스 : 이미지 복사하기 (0) | 2020.12.26 |
[C#/WINFORM] Image 클래스 : 이미지 복사하기 (0) | 2020.12.26 |
[C#/WINFORM] 레이더 차트 그리기 (0) | 2020.12.26 |
[C#/WINFORM] Graphics 클래스 : DrawString 메소드를 사용해 회전 텍스트 그리기 (0) | 2020.12.26 |
[C#/WINFORM] PointF 구조체 : 포인트 밀접 여부 구하기 (0) | 2020.12.26 |
[C#/WINFORM] RichTextBox 클래스 : 테이블 추가하기 (0) | 2020.12.26 |
[C#/WINFORM] RichTextBox 클래스 : 이미지 캡처하기 (0) | 2020.12.25 |
댓글을 달아 주세요