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

728x90
반응형
728x170
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

#region 그라디언트 기반 가장자리 탐지 필터 적용하기 - ApplyGradientBasedEdgeDetectionFilter(sourceBitmap, edgeColor, threshold)

/// <summary>
/// 그라디언트 기반 가장자리 탐지 필터 적용하기
/// </summary>
/// <param name="sourceBitmap">소스 비트맵</param>
/// <param name="edgeColor">가장자리 색상</param>
/// <param name="threshold">임계치</param>
/// <returns>비트맵</returns>
public Bitmap ApplyGradientBasedEdgeDetectionFilter(Bitmap sourceBitmap, Color edgeColor, 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);
    Marshal.Copy(sourceBitmapData.Scan0, targetByteArray, 0, targetByteArray.Length);

    sourceBitmap.UnlockBits(sourceBitmapData);

    int  sourceOffset    = 0;
    int  gradientValue   = 0;
    bool exceedThreshold = false;

    for(int offsetY = 1; offsetY < sourceBitmap.Height - 1; offsetY++)
    {
        for(int offsetX = 1; offsetX < sourceBitmap.Width - 1; offsetX++)
        {
            sourceOffset    = offsetY * sourceBitmapData.Stride + offsetX * 4;
            gradientValue   = 0;
            exceedThreshold = true;

            CheckThreshold
            (
                sourceByteArray,
                sourceOffset - 4,
                sourceOffset + 4,
                ref gradientValue,
                threshold,
                2
            );

            exceedThreshold = CheckThreshold
            (
                sourceByteArray,
                sourceOffset - sourceBitmapData.Stride,
                sourceOffset + sourceBitmapData.Stride,
                ref gradientValue,
                threshold,
                2
            );

            if(exceedThreshold == false)
            {
                gradientValue = 0;

                exceedThreshold = CheckThreshold
                (
                    sourceByteArray,
                    sourceOffset - 4,
                    sourceOffset + 4,
                    ref gradientValue,
                    threshold
                );

                if(exceedThreshold == false)
                {
                    gradientValue = 0;

                    exceedThreshold = CheckThreshold
                    (
                        sourceByteArray,
                        sourceOffset - sourceBitmapData.Stride,
                        sourceOffset + sourceBitmapData.Stride,
                        ref gradientValue,
                        threshold
                    );

                    if(exceedThreshold == false)
                    {
                        gradientValue = 0;

                        CheckThreshold
                        (
                            sourceByteArray,
                            sourceOffset - 4 - sourceBitmapData.Stride,
                            sourceOffset + 4 + sourceBitmapData.Stride,
                            ref gradientValue,
                            threshold,
                            2
                        );

                        exceedThreshold = CheckThreshold
                        (
                            sourceByteArray,
                            sourceOffset - sourceBitmapData.Stride + 4,
                            sourceOffset - 4 + sourceBitmapData.Stride,
                            ref gradientValue,
                            threshold,
                            2
                        );

                        if(exceedThreshold == false)
                        {
                            gradientValue = 0;

                            exceedThreshold = CheckThreshold
                            (
                                sourceByteArray,
                                sourceOffset - 4 - sourceBitmapData.Stride,
                                sourceOffset + 4 + sourceBitmapData.Stride,
                                ref gradientValue,
                                threshold
                            );

                            if(exceedThreshold == false)
                            {
                                gradientValue = 0;

                                exceedThreshold = CheckThreshold
                                (
                                    sourceByteArray,
                                    sourceOffset - sourceBitmapData.Stride + 4,
                                    sourceOffset + sourceBitmapData.Stride - 4,
                                    ref gradientValue,
                                    threshold
                                );
                            }
                        }
                    }
                }
            }

            if(exceedThreshold == true)
            {
                targetByteArray[sourceOffset    ] = edgeColor.B;
                targetByteArray[sourceOffset + 1] = edgeColor.G;
                targetByteArray[sourceOffset + 2] = edgeColor.R;
            }

            targetByteArray[sourceOffset + 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
#region 임계치 체크하기 - CheckThreshold(sourceByteArray, offset1, offset2, gradientValue, threshold, divideBy)

/// <summary>
/// 임계치 체크하기
/// </summary>
/// <param name="sourceByteArray">소스 바이트 배열</param>
/// <param name="offset1">오프셋 1</param>
/// <param name="offset2">오프셋 2</param>
/// <param name="gradientValue">그라디언트 값</param>
/// <param name="threshold">임계치</param>
/// <param name="divideBy">젯수</param>
/// <returns>임계치 체크 결과</returns>
private bool CheckThreshold
(
    byte[]  sourceByteArray,
    int     offset1,
    int     offset2,
    ref int gradientValue,
    byte    threshold,
    int     divideBy = 1
)
{
    gradientValue += Math.Abs(sourceByteArray[offset1    ] - sourceByteArray[offset2    ]) / divideBy;
    gradientValue += Math.Abs(sourceByteArray[offset1 + 1] - sourceByteArray[offset2 + 1]) / divideBy;
    gradientValue += Math.Abs(sourceByteArray[offset1 + 2] - sourceByteArray[offset2 + 2]) / divideBy;

    return (gradientValue >= threshold);
}

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

댓글을 달아 주세요