첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
------------------------------------------------------------------------------------------------------------------------------------------------------
728x90
728x170

TestProject.zip
다운로드

▶ EdgeFilterType.cs

namespace TestProject
{
    /// <summary>
    /// 가장자리 필터 타입
    /// </summary>
    public enum EdgeFilterType
    {
        /// <summary>
        /// Edge Detection Mono
        /// </summary>
        EdgeDetectionMono,

        /// <summary>
        /// Edge Detection Gradient
        /// </summary>
        EdgeDetectionGradient,

        /// <summary>
        /// Sharpen
        /// </summary>
        Sharpen,

        /// <summary>
        /// Sharpen Gradient
        /// </summary>
        SharpenGradient
    }
}

 

728x90

 

▶ DerivativeLevel.cs

namespace TestProject
{
    /// <summary>
    /// 미분 레벨
    /// </summary>
    public enum DerivativeLevel : int
    {
        /// <summary>
        /// First
        /// </summary>
        First = 1,

        /// <summary>
        /// Second
        /// </summary>
        Second
    }
}

 

300x250

 

▶ BitmapHelper.cs

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

namespace TestProject
{
    /// <summary>
    /// 비트맵 헬퍼
    /// </summary>
    public static class BitmapHelper
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// 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 그라디언트 기반 가장자리 탐지 필터 적용하기 - ApplyGradientBasedEdgeDetectionFilter(sourceBitmap, filterType,
            derivativeLevel, redFactor, greenFactor, blueFactor, threshold)

        /// <summary>
        /// 그라디언트 기반 가장자리 탐지 필터 적용하기
        /// </summary>
        /// <param name="sourceBitmap">소스 비트맵</param>
        /// <param name="filterType">가장자리 필터 타입</param>
        /// <param name="derivativeLevel">미분 레벨</param>
        /// <param name="redFactor">적색 팩터</param>
        /// <param name="greenFactor">녹색 팩터</param>
        /// <param name="blueFactor">청색 팩터</param>
        /// <param name="threshold">임계치</param>
        /// <returns>비트맵</returns>
        public static Bitmap ApplyGradientBasedEdgeDetectionFilter
        (
            Bitmap          sourceBitmap,
            EdgeFilterType  filterType,
            DerivativeLevel derivativeLevel,
            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    derivative    = (int)derivativeLevel;
            int    byteOffset    = 0;
            int    blueGradient  = 0;
            int    greenGradient = 0;
            int    redGradient   = 0;
            double blue          = 0;
            double green         = 0;
            double red           = 0;

            bool exceedsThreshold = false;

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

                    blueGradient = Math.Abs
                    (
                        sourceByteArray[byteOffset - 4] -
                        sourceByteArray[byteOffset + 4]
                    ) / derivative;

                    blueGradient += Math.Abs
                    (
                        sourceByteArray[byteOffset - sourceBitmapData.Stride] -
                        sourceByteArray[byteOffset + sourceBitmapData.Stride]
                    ) / derivative;

                    byteOffset++;

                    greenGradient = Math.Abs
                    (
                        sourceByteArray[byteOffset - 4] -
                        sourceByteArray[byteOffset + 4]
                    ) / derivative;

                    greenGradient += Math.Abs
                    (
                        sourceByteArray[byteOffset - sourceBitmapData.Stride] -
                        sourceByteArray[byteOffset + sourceBitmapData.Stride]
                    ) / derivative;

                    byteOffset++;

                    redGradient = Math.Abs
                    (
                        sourceByteArray[byteOffset - 4] -
                        sourceByteArray[byteOffset + 4]
                    ) / derivative;

                    redGradient += Math.Abs
                    (
                        sourceByteArray[byteOffset - sourceBitmapData.Stride] -
                        sourceByteArray[byteOffset + sourceBitmapData.Stride]
                    ) / derivative;

                    if(blueGradient + greenGradient + redGradient > threshold)
                    {
                        exceedsThreshold = true ;
                    }
                    else
                    {
                        byteOffset -= 2;

                        blueGradient = Math.Abs
                        (
                            sourceByteArray[byteOffset - 4] -
                            sourceByteArray[byteOffset + 4]
                        );
                
                        byteOffset++;

                        greenGradient = Math.Abs
                        (
                            sourceByteArray[byteOffset - 4] -
                            sourceByteArray[byteOffset + 4]
                        );

                        byteOffset++;

                        redGradient = Math.Abs
                        (
                            sourceByteArray[byteOffset - 4] -
                            sourceByteArray[byteOffset + 4]
                        );

                        if(blueGradient + greenGradient + redGradient > threshold)
                        {
                            exceedsThreshold = true ;
                        }
                        else
                        {
                            byteOffset -= 2;

                            blueGradient = Math.Abs
                            (
                                sourceByteArray[byteOffset - sourceBitmapData.Stride] -
                                sourceByteArray[byteOffset + sourceBitmapData.Stride]
                            );

                            byteOffset++;

                            greenGradient = Math.Abs
                            (
                                sourceByteArray[byteOffset - sourceBitmapData.Stride] -
                                sourceByteArray[byteOffset + sourceBitmapData.Stride]
                            );

                            byteOffset++;

                            redGradient = Math.Abs
                            (
                                sourceByteArray[byteOffset - sourceBitmapData.Stride] -
                                sourceByteArray[byteOffset + sourceBitmapData.Stride]
                            );

                            if(blueGradient + greenGradient + redGradient > threshold)
                            {
                                exceedsThreshold = true ;
                            }
                            else
                            {
                                byteOffset -= 2;

                                blueGradient = Math.Abs
                                (
                                    sourceByteArray[byteOffset - 4 - sourceBitmapData.Stride] -
                                    sourceByteArray[byteOffset + 4 + sourceBitmapData.Stride]
                                ) / derivative;

                                blueGradient += Math.Abs
                                (
                                    sourceByteArray[byteOffset - sourceBitmapData.Stride + 4] -
                                    sourceByteArray[byteOffset + sourceBitmapData.Stride - 4]
                                ) / derivative;

                                byteOffset++;

                                greenGradient = Math.Abs
                                (
                                    sourceByteArray[byteOffset - 4 - sourceBitmapData.Stride] -
                                    sourceByteArray[byteOffset + 4 + sourceBitmapData.Stride]
                                ) / derivative;

                                greenGradient += Math.Abs
                                (
                                    sourceByteArray[byteOffset - sourceBitmapData.Stride + 4] -
                                    sourceByteArray[byteOffset + sourceBitmapData.Stride - 4]
                                ) / derivative;

                                byteOffset++;

                                redGradient = Math.Abs
                                (
                                    sourceByteArray[byteOffset - 4 - sourceBitmapData.Stride] -
                                    sourceByteArray[byteOffset + 4 + sourceBitmapData.Stride]
                                ) / derivative;

                                redGradient += Math.Abs
                                (
                                    sourceByteArray[byteOffset - sourceBitmapData.Stride + 4] -
                                    sourceByteArray[byteOffset + sourceBitmapData.Stride - 4]
                                ) / derivative;

                                if(blueGradient + greenGradient + redGradient > threshold)
                                {
                                    exceedsThreshold = true ;
                                }
                                else
                                {
                                    exceedsThreshold = false ;
                                }
                            }
                        }
                    }

                    byteOffset -= 2;

                    if(exceedsThreshold)
                    {
                        if(filterType == EdgeFilterType.EdgeDetectionMono)
                        {
                            blue = green = red = 255;
                        }
                        else if(filterType == EdgeFilterType.EdgeDetectionGradient)
                        {
                            blue  = blueGradient  * blueFactor;
                            green = greenGradient * greenFactor;
                            red   = redGradient   * redFactor;
                        }
                        else if(filterType == EdgeFilterType.Sharpen)
                        {
                            blue  = sourceByteArray[byteOffset    ] * blueFactor;
                            green = sourceByteArray[byteOffset + 1] * greenFactor;
                            red   = sourceByteArray[byteOffset + 2] * redFactor;
                        }
                        else if(filterType == EdgeFilterType.SharpenGradient)
                        {
                            blue  = sourceByteArray[byteOffset    ] + blueGradient  * blueFactor;
                            green = sourceByteArray[byteOffset + 1] + greenGradient * greenFactor;
                            red   = sourceByteArray[byteOffset + 2] + redGradient   * redFactor;
                        }
                    }
                    else
                    {
                        if(filterType == EdgeFilterType.EdgeDetectionMono ||
                           filterType == EdgeFilterType.EdgeDetectionGradient)
                        {
                            blue = green = red = 0;
                        }
                        else if(filterType == EdgeFilterType.Sharpen ||
                                filterType == EdgeFilterType.SharpenGradient)
                        {
                            blue  = sourceByteArray[byteOffset    ];
                            green = sourceByteArray[byteOffset + 1];
                            red   = sourceByteArray[byteOffset + 2];
                        }
                    }

                    blue  = (blue  > 255 ? 255 : (blue  < 0 ? 0 : blue ));
                    green = (green > 255 ? 255 : (green < 0 ? 0 : green));
                    red   = (red   > 255 ? 255 : (red   < 0 ? 0 : red  ));

                    targetByteArray[byteOffset    ] = (byte)blue;
                    targetByteArray[byteOffset + 1] = (byte)green;
                    targetByteArray[byteOffset + 2] = (byte)red;
                    targetByteArray[byteOffset + 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
    }
}

 

▶ 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.ApplyGradientBasedEdgeDetectionFilter
            (
                sourceBitmap,
                EdgeFilterType.EdgeDetectionGradient,
                DerivativeLevel.First,
                1,
                1,
                1,
                128
            );

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

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