첨부 소스 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170
using System;
using System.Drawing;
using System.Drawing.Imaging;

#region 선 그리기 - DrawLine(sourceBitmapData, point1, point2, color)

/// <summary>
/// 선 그리기
/// </summary>
/// <param name="sourceBitmapData">소스 비트맵 데이타</param>
/// <param name="point1">위치 1</param>
/// <param name="point2">위치 2</param>
/// <param name="color">색상</param>
/// <remarks>소스 비트맵 데이타 픽셀 형식은 24비트 색상 또는 256 인덱스 색상이어야 합니다.</remarks>
public void DrawLine(BitmapData sourceBitmapData, Point point1, Point point2, Color color)
{
    int bitmapWidth  = sourceBitmapData.Width;
    int bitmapHeight = sourceBitmapData.Height;
    int stride       = sourceBitmapData.Stride;

    if(((point1.X < 0) && (point2.X < 0)) || ((point1.Y < 0) && (point2.Y < 0)) || ((point1.X >= bitmapWidth) && (point2.X >= bitmapWidth)) || ((point1.Y >= bitmapHeight) && (point2.Y >= bitmapHeight)))
    {
        return;
    }

    CheckEndPoint(bitmapWidth, bitmapHeight, point1, ref point2);
    CheckEndPoint(bitmapWidth, bitmapHeight, point2, ref point1);

    if(((point1.X < 0) && (point2.X < 0)) || ((point1.Y < 0) && (point2.Y < 0)) || ((point1.X >= bitmapWidth) && (point2.X >= bitmapWidth)) || ((point1.Y >= bitmapHeight) && (point2.Y >= bitmapHeight)))
    {
        return;
    }

    int startX = point1.X;
    int startY = point1.Y;
    int endX   = point2.X;
    int endY   = point2.Y;

    byte gray = 0;

    if(sourceBitmapData.PixelFormat == PixelFormat.Format8bppIndexed)
    {
        gray = (byte)(0.2125d * color.R + 0.7154d * color.G + 0.0721d * color.B);
    }

    int deltaX = endX - startX;
    int deltaY = endY - startY;

    unsafe
    {
        if(Math.Abs(deltaX) >= Math.Abs(deltaY))
        {
            float slope = (float)deltaY / (float)deltaX;
            int   step  = (deltaX > 0) ? 1 : -1;

            deltaX += step;

            if(sourceBitmapData.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                for(int x = 0; x != deltaX; x += step)
                {
                    int temporaryX = startX + x;
                    int temporaryY = (int) ((float) startY + (slope * (float) x));

                    byte* ptrSource = (byte*) sourceBitmapData.Scan0.ToPointer() + temporaryY * stride + temporaryX;

                    *ptrSource = gray;
                }
            }
            else
            {
                for(int x = 0; x != deltaX; x += step)
                {
                    int temporaryX = startX + x;
                    int temporaryY = (int)((float)startY + (slope * (float)x));

                    byte* sourcePointer = (byte*) sourceBitmapData.Scan0.ToPointer() + temporaryY * stride + temporaryX * 3;

                    sourcePointer[2] = color.R;
                    sourcePointer[1] = color.G;
                    sourcePointer[0] = color.B;
                }
            }
        }
        else
        {
            float slope = (float)deltaX / (float)deltaY;
            int   step  = (deltaY > 0) ? 1 : -1;

            deltaY += step;

            if(sourceBitmapData.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                for(int y = 0; y != deltaY; y += step)
                {
                    int temporaryX = (int)((float)startX + (slope * (float)y));
                    int temporaryY = startY + y;

                    byte* sourcePointer = (byte*)sourceBitmapData.Scan0.ToPointer() + temporaryY * stride + temporaryX;

                    *sourcePointer = gray;
                }
            }
            else
            {
                for(int y = 0; y != deltaY; y += step)
                {
                    int temporaryX = (int)((float)startX + (slope * (float)y));
                    int temporaryY = startY + y;

                    byte* sourcePointer = (byte*)sourceBitmapData.Scan0.ToPointer() + temporaryY * stride + temporaryX * 3;

                    sourcePointer[2] = color.R;
                    sourcePointer[1] = color.G;
                    sourcePointer[0] = color.B;
                }
            }
        }
    }
}

#endregion

#region 종단점 조사하기 - CheckEndPoint(width, height, startPoint, endPoint)

/// <summary>
/// 종단점 조사하기
/// </summary>
/// <param name="width">너비</param>
/// <param name="height">높이</param>
/// <param name="startPoint">시작 위치</param>
/// <param name="endPoint">종료 위치</param>
private void CheckEndPoint(int width, int height, Point startPoint, ref Point endPoint)
{
    if(endPoint.X >= width)
    {
        int newEndX = width - 1;

        double coefficient = (double)(newEndX - startPoint.X) / (endPoint.X - startPoint.X);

        endPoint.Y = (int)(startPoint.Y + coefficient * (endPoint.Y - startPoint.Y));

        endPoint.X = newEndX;
    }

    if(endPoint.Y >= height)
    {
        int newEndY = height - 1;

        double coefficient = (double)(newEndY - startPoint.Y) / (endPoint.Y - startPoint.Y);

        endPoint.X = (int)(startPoint.X + coefficient * (endPoint.X - startPoint.X));

        endPoint.Y = newEndY;
    }

    if(endPoint.X < 0)
    {
        double coefficient = (double)(0 - startPoint.X) / (endPoint.X - startPoint.X);

        endPoint.Y = (int)(startPoint.Y + coefficient * (endPoint.Y - startPoint.Y));
        endPoint.X = 0;
    }

    if(endPoint.Y < 0)
    {
        double coefficient = (double)(0 - startPoint.Y) / (endPoint.Y - startPoint.Y);

        endPoint.X = (int)(startPoint.X + coefficient * (endPoint.X - startPoint.X));

        endPoint.Y = 0;
    }
}

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

댓글을 달아 주세요