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

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

#region 회선 필터 적용하기 - ApplyConvolutionFilter(sourceBitmap, filterArray, factor, bias, grayscale)

/// <summary>
/// 회선 필터 적용하기
/// </summary>
/// <param name="sourceBitmap">소스 비트맵</param>
/// <param name="filterArray">필터 배열</param>
/// <param name="factor">팩터</param>
/// <param name="bias">바이어스</param>
/// <param name="grayscale">회색조 여부</param>
/// <returns>비트맵</returns>
public static Bitmap ApplyConvolutionFilter
(
    Bitmap    sourceBitmap,
    double[,] filterArray,
    double    factor    = 1,
    int       bias      = 0,
    bool      grayscale = false
)
{
    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);

    if(grayscale == true)
    {
        float rgb = 0;

        for(int k = 0; k < sourceByteArray.Length; k += 4)
        {
            rgb =  sourceByteArray[k    ] * 0.11f;
            rgb += sourceByteArray[k + 1] * 0.59f;
            rgb += sourceByteArray[k + 2] * 0.3f;

            sourceByteArray[k    ] = (byte )rgb;
            sourceByteArray[k + 1] = sourceByteArray[k];
            sourceByteArray[k + 2] = sourceByteArray[k];
            sourceByteArray[k + 3] = 255;
        }
    }

    double blue  = 0.0;
    double green = 0.0;
    double red   = 0.0;

    int filterWidth  = filterArray.GetLength(1);
    int filterHeight = filterArray.GetLength(0);

    int filterOffset = (filterWidth-1) / 2;
    int sourceOffset = 0;
    int targetOffset = 0;

    for(int offsetY = filterOffset; offsetY < sourceBitmap.Height - filterOffset; offsetY++)
    {
        for(int offsetX = filterOffset; offsetX < sourceBitmap.Width - filterOffset; offsetX++)
        {
            blue  = 0;
            green = 0;
            red   = 0;

            targetOffset = offsetY * sourceBitmapData.Stride + offsetX * 4;

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

                    blue  += (double)(sourceByteArray[sourceOffset    ]) *
                                filterArray[filterY + filterOffset, filterX + filterOffset];

                    green += (double)(sourceByteArray[sourceOffset + 1]) *
                                filterArray[filterY + filterOffset, filterX + filterOffset];

                    red   += (double)(sourceByteArray[sourceOffset + 2]) *
                                filterArray[filterY + filterOffset, filterX + filterOffset];
                }
            }

            blue  = factor * blue  + bias;
            green = factor * green + bias;
            red   = factor * red   + bias;

            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;
            }

            targetByteArray[targetOffset    ] = (byte)blue;
            targetByteArray[targetOffset + 1] = (byte)green;
            targetByteArray[targetOffset + 2] = (byte)red;
            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
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요