■ Bitmap 클래스 : 대비 필터(Contrast Filter) 사용하기
------------------------------------------------------------------------------------------------------------------------
▶ BitmapHelper.cs
using System; 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 비트맵 복사하기 - CopyBitmap(sourceBitmap, targetWidth)
/// <summary> /// 비트맵 복사하기 /// </summary> /// <param name="sourceBitmap">소스 비트맵</param> /// <param name="targetWidth">타겟 대상</param> /// <returns>비트맵</returns> public static Bitmap CopyBitmap(Bitmap sourceBitmap, int targetWidth) { float ratio = 1.0f;
int maximumSize = sourceBitmap.Width > sourceBitmap.Height ? sourceBitmap.Width : sourceBitmap.Height;
ratio = (float)maximumSize / (float)targetWidth;
Bitmap targetBitmap = (sourceBitmap.Width > sourceBitmap.Height ? new Bitmap(targetWidth, (int)(sourceBitmap.Height / ratio)) : new Bitmap((int)(sourceBitmap.Width / ratio), targetWidth));
using(Graphics targetGraphics = Graphics.FromImage(targetBitmap)) { targetGraphics.CompositingQuality = CompositingQuality.HighQuality; targetGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic; targetGraphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
targetGraphics.DrawImage ( sourceBitmap, new Rectangle(0, 0, targetBitmap.Width, targetBitmap.Height), new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), GraphicsUnit.Pixel );
targetGraphics.Flush(); }
return targetBitmap; }
#endregion #region 대비 필터 적용하기 - ApplyContrastFilter(sourceBitmap, threshold)
/// <summary> /// 대비 필터 적용하기 /// </summary> /// <param name="sourceBitmap">소스 비트맵</param> /// <param name="threshold">임계치</param> /// <returns>비트맵</returns> public static Bitmap ApplyContrastFilter(Bitmap sourceBitmap, int threshold) { BitmapData sourceBitmapData = sourceBitmap.LockBits ( new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb );
byte[] sourceByteArray = new byte[sourceBitmapData.Stride * sourceBitmapData.Height];
Marshal.Copy(sourceBitmapData.Scan0, sourceByteArray, 0, sourceByteArray.Length);
sourceBitmap.UnlockBits(sourceBitmapData);
double contrastLevel = Math.Pow((100.0 + threshold) / 100.0, 2);
double blue = 0; double green = 0; double red = 0;
for(int k = 0; k + 4 < sourceByteArray.Length; k += 4) { blue = ((((sourceByteArray[k ] / 255.0) - 0.5) * contrastLevel) + 0.5) * 255.0; green = ((((sourceByteArray[k + 1] / 255.0) - 0.5) * contrastLevel) + 0.5) * 255.0; red = ((((sourceByteArray[k + 2] / 255.0) - 0.5) * contrastLevel) + 0.5) * 255.0;
if(blue > 255) { blue = 255; } else if(blue < 0) { blue = 0; }
if(green > 255) { green = 255; } else if(green < 0) { green = 0; }
if(red > 255) { red = 255; } else if(red < 0) { red = 0; }
sourceByteArray[k ] = (byte)blue; sourceByteArray[k + 1] = (byte)green; sourceByteArray[k + 2] = (byte)red; }
Bitmap targetBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height);
BitmapData targetBitmapData = targetBitmap.LockBits ( new Rectangle(0, 0, targetBitmap.Width, targetBitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb );
Marshal.Copy(sourceByteArray, 0, targetBitmapData.Scan0, sourceByteArray.Length);
targetBitmap.UnlockBits(targetBitmapData);
return targetBitmap; }
#endregion } }
|
▶ 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 Bitmap sourceBitmap = null;
/// <summary> /// 미리보기 비트맵 /// </summary> private Bitmap previewBitmap = null;
/// <summary> /// 타겟 비트맵 /// </summary> private Bitmap targetBitmap = null;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent();
this.thresholdTrackBar.ValueChanged += thresholdTrackBar_ValueChanged; this.loadImageButton.Click += loadImageButton_Click; this.saveImageButton.Click += saveImageButton_Click; }
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private //////////////////////////////////////////////////////////////////////////////// Event
#region 임계치 트랙바 값 변경시 처리하기 - thresholdTrackBar_ValueChanged(sender, e)
/// <summary> /// 임계치 트랙바 값 변경시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void thresholdTrackBar_ValueChanged(object sender, EventArgs e) { this.contrastValueLabel.Text = this.thresholdTrackBar.Value.ToString();
ApplyFilter(true); }
#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 = "PNG 파일(*.png)|*.png|JPEG 파일(*.jpg)|*.jpg|비트맵 파일(*.bmp)|*.bmp";
if(openFileDialog.ShowDialog() == DialogResult.OK) { StreamReader streamReader = new StreamReader(openFileDialog.FileName);
this.sourceBitmap = (Bitmap)Bitmap.FromStream(streamReader.BaseStream);
streamReader.Close();
this.previewBitmap = BitmapHelper.CopyBitmap(this.sourceBitmap, this.pictureBox.Width);
this.pictureBox.Image = this.previewBitmap;
ApplyFilter(true); } }
#endregion #region 이미지 저장 버튼 클릭시 처리하기 - saveImageButton_Click(sender, e)
/// <summary> /// 이미지 저장 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void saveImageButton_Click(object sender, EventArgs e) { ApplyFilter(false);
if(this.targetBitmap != null) { SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Title = "이미지 파일명 선택"; saveFileDialog.Filter = "PNG 파일(*.png)|*.png|JPEG 파일(*.jpg)|*.jpg|비트맵 파일(*.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.targetBitmap.Save(streamWriter.BaseStream, imageFormat);
streamWriter.Flush(); streamWriter.Close();
this.targetBitmap = null; } } }
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 필터 적용하기 - ApplyFilter(preview)
/// <summary> /// 필터 적용하기 /// </summary> /// <param name="preview">미리보기 여부</param> private void ApplyFilter(bool preview) { if(this.previewBitmap == null) { return; }
if(preview == true) { this.pictureBox.Image = BitmapHelper.ApplyContrastFilter(this.previewBitmap, this.thresholdTrackBar.Value); } else { this.targetBitmap = BitmapHelper.ApplyContrastFilter(this.sourceBitmap, this.thresholdTrackBar.Value); } }
#endregion } }
|
------------------------------------------------------------------------------------------------------------------------
'C# > WinForm' 카테고리의 다른 글
[C#/WINFORM] Bitmap 클래스 : 바이-톤 필터(Bi-tonal Filter) 사용하기 (0) | 2021.01.30 |
---|---|
[C#/WINFORM] Bitmap 클래스 : 색조 필터(Color Tint Filter) 사용하기 (0) | 2021.01.28 |
[C#/WINFORM] Bitmap 클래스 : 색상 음영 필터(Color Shading Filter) 사용하기 (0) | 2021.01.27 |
[C#/WINFORM] Bitmap 클래스 : 열화 필터(Solar Filter) 사용하기 (0) | 2021.01.27 |
[C#/WINFORM] Form 클래스 : 높은 DPI에서 흐릿하게 출력 방지하기 (0) | 2021.01.23 |
[C#/WINFORM] Bitmap 클래스 : 대비 필터(Contrast Filter) 사용하기 (0) | 2021.01.14 |
[C#/WINFORM] Bitmap 클래스 : 이미지 비트 단위 블렌딩하기 (0) | 2021.01.13 |
[C#/WINFORM] Bitmap 클래스 : 이미지 연산하기 (0) | 2021.01.12 |
[C#/WINFORM] Bitmap 클래스 : 키르시 3X3 가장자리 탐지 필터(Kirsch 3X3 Edge Detection Filter) 사용하기 (0) | 2021.01.11 |
[C#/WINFORM] Bitmap 클래스 : 프리윗 3X3 가장자리 탐지 필터(Prewitt 3X3 Edge Detection Filter) 사용하기 (0) | 2021.01.11 |
[C#/WINFORM] Bitmap 클래스 : 소벨 3X3 가장자리 탐지 필터(Sobel 3X3 Edge Detection Filter) 사용하기 (0) | 2021.01.11 |
댓글을 달아 주세요