첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

728x90
반응형

■ Bitmap 클래스 : 대비 필터(Contrast Filter) 사용하기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip


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

    }

}

 

------------------------------------------------------------------------------------------------------------------------

728x90
반응형
Posted by 사용자 icodebroker

댓글을 달아 주세요