728x90
반응형
728x170
▶ ColorSubstitutionFilter.cs
using System.Drawing;
namespace TestProject
{
/// <summary>
/// 색상 대체 필터
/// </summary>
public class ColorSubstitutionFilter
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 임계치 값
/// </summary>
private int thresholdValue = 10;
/// <summary>
/// 소스 색상
/// </summary>
private Color sourceColor = Color.White;
/// <summary>
/// 타겟 색상
/// </summary>
private Color targetColor = Color.White;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 임계치 값 - ThresholdValue
/// <summary>
/// 임계치 값
/// </summary>
public int ThresholdValue
{
get
{
return this.thresholdValue;
}
set
{
this.thresholdValue = value;
}
}
#endregion
#region 소스 색상 - SourceColor
/// <summary>
/// 소스 색상
/// </summary>
public Color SourceColor
{
get
{
return this.sourceColor;
}
set
{
this.sourceColor = value;
}
}
#endregion
#region 타겟 색상 - TargetColor
/// <summary>
/// 타겟 색상
/// </summary>
public Color TargetColor
{
get
{
return this.targetColor;
}
set
{
this.targetColor = value;
}
}
#endregion
}
}
728x90
▶ BitmapHelper.cs
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace TestProject
{
/// <summary>
/// 비트맵 헬퍼
/// </summary>
public static class BitmapHelper
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region 비트맵 구하기 - GetBitmap(sourceBitmap)
/// <summary>
/// 비트맵 구하기
/// </summary>
/// <param name="sourceBitmap">소스 비트맵</param>
/// <returns>비트맵</returns>
public static Bitmap GetBitmap(Bitmap sourceBitmap)
{
Bitmap targetBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height, PixelFormat.Format32bppArgb);
using(Graphics graphics = Graphics.FromImage(targetBitmap))
{
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.DrawImage
(
sourceBitmap,
new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height),
new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height),
GraphicsUnit.Pixel
);
}
return targetBitmap;
}
#endregion
#region 색상 대체하기 - SubstituteColor(sourceBitmap, colorSubstitutionFilter)
/// <summary>
/// 색상 대체하기
/// </summary>
/// <param name="sourceBitmap">소스 비트맵</param>
/// <param name="colorSubstitutionFilter">색상 대체 필터</param>
/// <returns>비트맵</returns>
public static Bitmap SubstituteColor(Bitmap sourceBitmap, ColorSubstitutionFilter colorSubstitutionFilter)
{
BitmapData sourceBitmapData = sourceBitmap.LockBits
(
new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb
);
Bitmap targetBitmap = new Bitmap
(
sourceBitmap.Width,
sourceBitmap.Height,
PixelFormat.Format32bppArgb
);
BitmapData targetBitmapData = targetBitmap.LockBits
(
new Rectangle(0, 0, targetBitmap.Width, targetBitmap.Height),
ImageLockMode.WriteOnly,
PixelFormat.Format32bppArgb
);
byte[] targetByteArray = new byte[targetBitmapData.Stride * targetBitmapData.Height];
Marshal.Copy(sourceBitmapData.Scan0, targetByteArray, 0, targetByteArray.Length);
sourceBitmap.UnlockBits(sourceBitmapData);
byte sourceRed = 0;
byte sourceGreen = 0;
byte sourceBlue = 0;
byte sourceAlpha = 0;
int targetRed = 0;
int targetGreen = 0;
int targetBlue = 0;
byte newRedValue = colorSubstitutionFilter.TargetColor.R;
byte newGreenValue = colorSubstitutionFilter.TargetColor.G;
byte newBlueValue = colorSubstitutionFilter.TargetColor.B;
byte redFilter = colorSubstitutionFilter.SourceColor.R;
byte greenFilter = colorSubstitutionFilter.SourceColor.G;
byte blueFilter = colorSubstitutionFilter.SourceColor.B;
byte minimumValue = 0;
byte maximumValue = 255;
for(int k = 0; k < targetByteArray.Length; k += 4)
{
sourceAlpha = targetByteArray[k + 3];
if(sourceAlpha != 0)
{
sourceBlue = targetByteArray[k ];
sourceGreen = targetByteArray[k + 1];
sourceRed = targetByteArray[k + 2];
if
(
(sourceBlue < blueFilter + colorSubstitutionFilter.ThresholdValue && sourceBlue > blueFilter - colorSubstitutionFilter.ThresholdValue) &&
(sourceGreen < greenFilter + colorSubstitutionFilter.ThresholdValue && sourceGreen > greenFilter - colorSubstitutionFilter.ThresholdValue) &&
(sourceRed < redFilter + colorSubstitutionFilter.ThresholdValue && sourceRed > redFilter - colorSubstitutionFilter.ThresholdValue)
)
{
targetBlue = blueFilter - sourceBlue + newBlueValue;
if(targetBlue > maximumValue)
{
targetBlue = maximumValue;
}
else if(targetBlue < minimumValue)
{
targetBlue = minimumValue;
}
targetGreen = greenFilter - sourceGreen + newGreenValue;
if(targetGreen > maximumValue)
{
targetGreen = maximumValue;
}
else if(targetGreen < minimumValue)
{
targetGreen = minimumValue;
}
targetRed = redFilter - sourceRed + newRedValue;
if(targetRed > maximumValue)
{
targetRed = maximumValue;
}
else if(targetRed < minimumValue)
{
targetRed = minimumValue;
}
targetByteArray[k ] = (byte)targetBlue;
targetByteArray[k + 1] = (byte)targetGreen;
targetByteArray[k + 2] = (byte)targetRed;
targetByteArray[k + 3] = sourceAlpha;
}
}
}
Marshal.Copy(targetByteArray, 0, targetBitmapData.Scan0, targetByteArray.Length);
targetBitmap.UnlockBits(targetBitmapData);
return targetBitmap;
}
#endregion
}
}
300x250
▶ 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
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 색상 대체 필터
/// </summary>
private ColorSubstitutionFilter filter = new ColorSubstitutionFilter();
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Consructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary>
/// 생성자
/// </summary>
public MainForm()
{
InitializeComponent();
this.sourcePictureBox.MouseUp += pictureBox_MouseUp;
this.targetPictureBox.MouseUp += pictureBox_MouseUp;
this.thresholdTrackBar.ValueChanged += thresholdTrackBar_ValueChanged;
this.selectSourceColorButton.Click += selectColorButton_Click;
this.selectReplacementColorButton.Click += selectColorButton_Click;
this.loadImageButton.Click += loadImageButton_Click;
this.saveImageButton.Click += saveImageButton_Click;
this.setSourceButton.Click += setSourceButton_Click;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 픽처 박스 마우스 UP 처리하기 - pictureBox_MouseUp(sender, e)
/// <summary>
/// 픽처 박스 마우스 UP 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void pictureBox_MouseUp(object sender, MouseEventArgs e)
{
if(sender is PictureBox)
{
PictureBox pictureBox = sender as PictureBox;
using(Bitmap bitmap = new Bitmap(pictureBox.Width, pictureBox.Height))
{
this.sourcePictureBox.DrawToBitmap(bitmap, new Rectangle(0, 0, pictureBox.Width, pictureBox.Height));
this.sourceColorPanel.BackColor = bitmap.GetPixel(e.X, e.Y);
}
ApplyFilter();
}
}
#endregion
#region 임계치 트랙바 값 변경시 처리하기 - thresholdTrackBar_ValueChanged(sender, e)
/// <summary>
/// 임계치 트랙바 값 변경시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void thresholdTrackBar_ValueChanged(object sender, EventArgs e)
{
this.thresholdValueLabel.Text = this.thresholdTrackBar.Value.ToString() + "%";
ApplyFilter();
}
#endregion
#region 색상 선택 버튼 클릭시 처리하기 - selectColorButton_Click(sender, e)
/// <summary>
/// 색상 선택 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void selectColorButton_Click(object sender, EventArgs e)
{
using(ColorDialog colorDialog = new ColorDialog())
{
colorDialog.AllowFullOpen = true;
colorDialog.AnyColor = true;
colorDialog.FullOpen = true;
if(sender == this.selectSourceColorButton)
{
colorDialog.Color = this.sourceColorPanel.BackColor;
}
else if(sender == this.selectReplacementColorButton)
{
colorDialog.Color = this.replacementColorPanel.BackColor;
}
if(colorDialog.ShowDialog() == DialogResult.OK)
{
if(sender == this.selectSourceColorButton)
{
this.sourceColorPanel.BackColor = colorDialog.Color;
}
else if(sender == this.selectReplacementColorButton)
{
this.replacementColorPanel.BackColor = colorDialog.Color;
}
ApplyFilter();
}
}
}
#endregion
#region 이미지 로드 버튼 클릭시 처리하기 - loadImageButton_Click(sender, e)
/// <summary>
/// 이미지 로드 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void loadImageButton_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Title = "이미지 파일 선택";
openFileDialog.Filter = "JPEG 이미지(*.jpg)|*.jpg|PNG 이미지(*.png)|*.png|비트맵 이미지(*.bmp)|*.bmp";
if(openFileDialog.ShowDialog() == DialogResult.OK)
{
StreamReader streamReader = new StreamReader(openFileDialog.FileName);
Bitmap sourceBitmap = new Bitmap(streamReader.BaseStream);
streamReader.Close();
this.sourcePictureBox.Image = BitmapHelper.GetBitmap(sourceBitmap);
ApplyFilter();
}
}
#endregion
#region 이미지 저장 버튼 클릭시 처리하기 - saveImageButton_Click(sender, e)
/// <summary>
/// 이미지 저장 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void saveImageButton_Click(object sender, EventArgs e)
{
if(this.targetPictureBox.Image != null)
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Title = "이미지 파일 선택";
saveFileDialog.Filter = "JPEG 이미지(*.jpg)|*.jpg|PNG 이미지(*.png)|*.png|비트맵 이미지(*.bmp)|*.bmp";
if(saveFileDialog.ShowDialog() == DialogResult.OK)
{
string fileExtension = Path.GetExtension(saveFileDialog.FileName).ToUpper();
ImageFormat imageFormat = ImageFormat.Png;
if(fileExtension == "BMP")
{
imageFormat = ImageFormat.Bmp;
}
else if(fileExtension == "JPG")
{
imageFormat = ImageFormat.Jpeg;
}
StreamWriter streamWriter = new StreamWriter(saveFileDialog.FileName, false);
this.targetPictureBox.Image.Save(streamWriter.BaseStream, imageFormat);
streamWriter.Flush();
streamWriter.Close();
}
}
}
#endregion
#region 타겟을 소스로 설정 버튼 클릭시 처리하기 - setSourceButton_Click(sender, e)
/// <summary>
/// 타겟을 소스로 설정 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void setSourceButton_Click(object sender, EventArgs e)
{
Bitmap targetBitmap = this.targetPictureBox.Image as Bitmap;
this.sourcePictureBox.Image = BitmapHelper.GetBitmap(targetBitmap);
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 필터 적용하기 - ApplyFilter()
/// <summary>
/// 필터 적용하기
/// </summary>
private void ApplyFilter()
{
if(this.sourcePictureBox.Image != null)
{
this.filter.SourceColor = this.sourceColorPanel.BackColor;
this.filter.ThresholdValue = (byte)(255.0f / 100.0f * (float)this.thresholdTrackBar.Value);
this.filter.TargetColor = this.replacementColorPanel.BackColor;
Bitmap sourceBitmap = this.sourcePictureBox.Image as Bitmap;
this.targetPictureBox.Image = BitmapHelper.SubstituteColor(sourceBitmap, filter);
this.colorFilterPanel.Enabled = true;
this.saveImageButton.Enabled = true;
this.setSourceButton.Enabled = true;
}
}
#endregion
}
}
728x90
반응형
그리드형(광고전용)
'C# > WinForm' 카테고리의 다른 글
[C#/WINFORM] SendKeys 클래스 : 키 코드 사용하기 (0) | 2021.04.03 |
---|---|
[C#/WINFORM] SendKeys 클래스 : SendWait 정적 메소드를 사용해 ESC 키 누르기 (0) | 2021.04.03 |
[C#/WINFORM] k-평균 클러스터링(k-means clustering) 사용하기 (0) | 2021.03.11 |
[C#/WINFORM] PictureBox 클래스 : 배경 이미지 위에 낙서하기 (0) | 2021.03.10 |
[C#/WINFORM] Bitmap 클래스 : 오버레이 비트맵 혼합하기 (0) | 2021.03.09 |
[C#/WINFORM] Bitmap 클래스 : 색상 대체하기 (0) | 2021.03.08 |
[C#/WINFORM] Bitmap 클래스 : ARGB 색상 채널 교환하기 (0) | 2021.03.08 |
[C#/WINFORM] Bitmap 클래스 : 부분 색상 반전하기 (0) | 2021.02.24 |
[C#/WINFORM] Bitmap 클래스 : 색상 균형 필터(Color Balance Filter) 사용하기 (0) | 2021.02.24 |
[C#/WINFORM] Screen 클래스 : 모니터 핸들 구하기 (0) | 2021.02.05 |
[C#/WINFORM] 잠금 화면 설정하기 (기능 개선) (0) | 2021.02.02 |
댓글을 달아 주세요