첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
본 블로그는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 블로그 콘텐츠 향상을 위해 쓰여집니다.

728x90
반응형
728x170

TestProject.zip
다운로드

▶ BooleanFilterType.cs

namespace TestProject
{
    /// <summary>
    /// 부울 필터 타입
    /// </summary>
    public enum BooleanFilterType
    {
        /// <summary>
        /// 가장자리 탐지
        /// </summary>
        EdgeDetection,

        /// <summary>
        /// 선명화
        /// </summary>
        Sharpen
    }
}

 

728x90

 

▶ BitmapHelper.cs

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// 비트맵 헬퍼
    /// </summary>
    public static class BitmapHelper
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 가장자리 마스크 리스트
        /// </summary>
        private static List<string> _edgeMaskList;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Static

        #region 생성자 - BitmapHelper()

        /// <summary>
        /// 생성자
        /// </summary>
        static BitmapHelper()
        {
            _edgeMaskList = new List<string>();

            _edgeMaskList.Add("011011011");
            _edgeMaskList.Add("000111111");
            _edgeMaskList.Add("110110110");
            _edgeMaskList.Add("111111000");
            _edgeMaskList.Add("011011001");
            _edgeMaskList.Add("100110110");
            _edgeMaskList.Add("111011000");
            _edgeMaskList.Add("111110000");
            _edgeMaskList.Add("111011001");
            _edgeMaskList.Add("100110111");
            _edgeMaskList.Add("001011111");
            _edgeMaskList.Add("111110100");
            _edgeMaskList.Add("000011111");
            _edgeMaskList.Add("000110111");
            _edgeMaskList.Add("001011011");
            _edgeMaskList.Add("001011011");
            _edgeMaskList.Add("110110100");
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 비트맵 로드하기 - LoadBitmap(filePath)

        /// <summary>
        /// 비트맵 로드하기
        /// </summary>
        /// <param name="filePath">파일 경로</param>
        /// <returns>비트맵</returns>
        public static Bitmap LoadBitmap(string filePath)
        {
            using(Bitmap bitmap = new Bitmap(filePath))
            {
                return new Bitmap(bitmap);
            }
        }

        #endregion
        #region 부울 가장자리 탐지 필터 적용하기 - ApplyBooleanEdgeDetectionFilter(sourceBitmap, filterType, redFactor, greenFactor, blueFactor, threshold)

        /// <summary>
        /// 부울 가장자리 탐지 필터 적용하기
        /// </summary>
        /// <param name="sourceBitmap">소스 비트맵</param>
        /// <param name="filterType">필터 타입</param>
        /// <param name="redFactor">적색 팩터</param>
        /// <param name="greenFactor">녹색 팩터</param>
        /// <param name="blueFactor">청색 팩터</param>
        /// <param name="threshold">임계치</param>
        /// <returns>비트맵</returns>
        public static Bitmap ApplyBooleanEdgeDetectionFilter
        (
            Bitmap            sourceBitmap,
            BooleanFilterType filterType,
            float             redFactor   = 1.0f,
            float             greenFactor = 1.0f,
            float             blueFactor  = 1.0f,
            byte              threshold   = 0
        )
        {
            BitmapData sourceBitmapData = sourceBitmap.LockBits
            (
                new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height),
                ImageLockMode.ReadOnly,
                PixelFormat.Format32bppArgb
            );

            byte[] sourceByteArray = new byte[sourceBitmapData.Stride * sourceBitmapData.Height];
            byte[] targetByteArray = new byte[sourceBitmapData.Stride * sourceBitmapData.Height];

            Marshal.Copy(sourceBitmapData.Scan0, sourceByteArray, 0, sourceByteArray.Length);

            sourceBitmap.UnlockBits(sourceBitmapData);

            int filterOffset = 1;
            int sourceOffset = 0;
            int targetOffset = 0;

            int    matrixMean     = 0;
            int    matrixTotal    = 0;
            double matrixVariance = 0;

            double blueValue  = 0;
            double greenValue = 0;
            double redValue   = 0;

            string matrixPatern = string.Empty;

            for(int offsetY = filterOffset; offsetY < sourceBitmap.Height - filterOffset; offsetY++)
            {
                for(int offsetX = filterOffset; offsetX < sourceBitmap.Width - filterOffset; offsetX++)
                {
                    targetOffset = offsetY * sourceBitmapData.Stride + offsetX * 4;

                    matrixMean     = 0;
                    matrixTotal    = 0;
                    matrixVariance = 0;

                    matrixPatern = string.Empty;

                    for(int filterY = -filterOffset; filterY <= filterOffset; filterY++)
                    {
                        for(int filterX = -filterOffset; filterX <= filterOffset; filterX++)
                        {
                            sourceOffset = targetOffset + (filterX * 4) + (filterY * sourceBitmapData.Stride);

                            matrixMean += sourceByteArray[sourceOffset    ];
                            matrixMean += sourceByteArray[sourceOffset + 1];
                            matrixMean += sourceByteArray[sourceOffset + 2];
                        }
                    }

                    matrixMean = matrixMean / 9;

                    for(int filterY = -filterOffset; filterY <= filterOffset; filterY++)
                    {
                        for(int filterX = -filterOffset; filterX <= filterOffset; filterX++)
                        {
                            sourceOffset = targetOffset + (filterX * 4) + (filterY * sourceBitmapData.Stride);

                            matrixTotal =  sourceByteArray[sourceOffset    ];
                            matrixTotal += sourceByteArray[sourceOffset + 1];
                            matrixTotal += sourceByteArray[sourceOffset + 2];

                            matrixPatern += (matrixTotal > matrixMean ? "1"  : "0" );

                            matrixVariance += Math.Pow
                            (
                                matrixMean - (sourceByteArray[sourceOffset    ] +
                                              sourceByteArray[sourceOffset + 1] +
                                              sourceByteArray[sourceOffset + 2]),
                                2
                            );
                        }
                    }

                    matrixVariance = matrixVariance / 9;

                    if(filterType == BooleanFilterType.Sharpen)
                    {
                        blueValue  = sourceByteArray[targetOffset    ];
                        greenValue = sourceByteArray[targetOffset + 1];
                        redValue   = sourceByteArray[targetOffset + 2];

                        if(matrixVariance > threshold)
                        {
                            if(_edgeMaskList.Contains(matrixPatern))
                            {
                                blueValue  = (blueValue  * blueFactor );
                                greenValue = (greenValue * greenFactor);
                                redValue   = (redValue   * redFactor  );

                                blueValue  = (blueValue  > 255 ? 255 : (blueValue  < 0 ? 0 : blueValue ));
                                greenValue = (greenValue > 255 ? 255 : (greenValue < 0 ? 0 : greenValue));
                                redValue   = (redValue   > 255 ? 255 : (redValue   < 0 ? 0 : redValue  ));
                            }
                        }
                    }
                    else  if(matrixVariance > threshold && _edgeMaskList.Contains(matrixPatern))
                    {
                        blueValue  = 255;
                        greenValue = 255;
                        redValue   = 255;
                    }
                    else
                    {
                        blueValue  = 0;
                        greenValue = 0;
                        redValue   = 0;
                    }

                    targetByteArray[targetOffset    ] = (byte)blueValue;
                    targetByteArray[targetOffset + 1] = (byte)greenValue;
                    targetByteArray[targetOffset + 2] = (byte)redValue;
                    targetByteArray[targetOffset + 3] = 255;
                }
            }

            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(targetByteArray, 0, targetBitmapData.Scan0, targetByteArray.Length);

            targetBitmap.UnlockBits(targetBitmapData);

            return targetBitmap;
        }

        #endregion
    }
}

 

300x250

 

▶ MainForm.cs

using System.Drawing;
using System.Windows.Forms;

namespace TestProject
{
    /// <summary>
    /// 메인 폼
    /// </summary>
    public partial class MainForm : Form
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainForm()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            Bitmap sourceBitmap = BitmapHelper.LoadBitmap("IMAGE\\sample.jpg");
            Bitmap targetBitmap = BitmapHelper.ApplyBooleanEdgeDetectionFilter(sourceBitmap, BooleanFilterType.EdgeDetection, 1, 1, 1, 64);

            this.pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
            this.pictureBox.Image    = targetBitmap;
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요