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

TestProject.zip
0.01MB

▶ ASCIIArtHelper.cs

using System;
using System.Drawing;
using System.Text;

namespace TestProject
{
    /// <summary>
    /// ASCII 아트 헬퍼
    /// </summary>
    public static class ASCIIArtHelper
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 폰트 종횡비
        /// </summary>
        private const double FONT_ASPECT_RATIO = 0.5;
 
        /// <summary>
        /// 출력 문자 집합
        /// </summary>
        private const string OUTPUT_CHARACTER_SET = "@%#*+=-:. ";
 
        /// <summary>
        /// 출력 대체 문자 집합
        /// </summary>
        private const string OUTPUT_ALTERNATE_CHARACTER_SET = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'. ";

        #endregion

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

        #region ASCII 아트 문자열 구하기 - GetASCIIArtString(bitmap, targetWidth)

        /// <summary>
        /// ASCII 아트 문자열 구하기
        /// </summary>
        /// <param name="bitmap">비트맵</param>
        /// <param name="targetWidth">대상 너비</param>
        /// <returns>ASCII 아트 문자열</returns>
        public static string GetASCIIArtString(Bitmap bitmap, int targetWidth)
        {
            double pixelChunkWidth  = (double)bitmap.Width / (double)targetWidth;
            double pixelChunkHeight = pixelChunkWidth / FONT_ASPECT_RATIO;
 
            int targetHeight = (int)Math.Round((double)bitmap.Height / pixelChunkHeight);
 
            double pixelOffSetTop = 0.0;

            StringBuilder stringBuilder = new StringBuilder();
 
            for(int row = 1; row <= targetHeight; row++)
            {
                double pixelOffSetLeft = 0.0;
 
                for(int column = 1; column <= targetWidth; column++)
                {
                    double brightSummary = 0.0;
                    int    pixelCount    = 0;

                    for(int pixelLeftIndex = 0; pixelLeftIndex < (int)pixelChunkWidth; pixelLeftIndex++)
                    {
                        for(int pixelTopIndext = 0; pixelTopIndext < (int)pixelChunkHeight; pixelTopIndext++)
                        {
                            int x = (int)pixelOffSetLeft + pixelLeftIndex;
                            int y = (int)pixelOffSetTop  + pixelTopIndext;

                            if((x < bitmap.Width) && (y < bitmap.Height))
                            {
                                brightSummary += bitmap.GetPixel(x, y).GetBrightness();

                                pixelCount++;
                            }
                        }
                    }
 
                    double pixelChunkBrightness = brightSummary / pixelCount;
 
                    int targetIndex = (int)Math.Floor(pixelChunkBrightness * OUTPUT_CHARACTER_SET.Length);

                    if(targetIndex == OUTPUT_CHARACTER_SET.Length)
                    {
                        targetIndex--;
                    }
 
                    char targetCharacter = OUTPUT_CHARACTER_SET[targetIndex];
 
                    stringBuilder.Append(targetCharacter);
 
                    pixelOffSetLeft += pixelChunkWidth;
                }

                stringBuilder.AppendLine();

                pixelOffSetTop += pixelChunkHeight;
            }
 
            return stringBuilder.ToString();
        }

        #endregion
    }
}

 

728x90

 

▶ MainWindow.xaml

<Window x:Class="TestProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="800"
    Height="600"
    Title="ASCII 아트 문자열 구하기"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Button Name="selectFileButton" Grid.Row="0"
            HorizontalAlignment="Left"
            Margin="10 10 0 0"
            Width="120"
            Height="25"
            Content="파일 선택" />
        <Label Name="filePathLabel" Grid.Row="1"
            HorizontalAlignment="Left"
            Margin="10 10 0 0"
            Content="ASCII 아트에 사용하기 위해 이미지 파일을 선택해 주시기 바랍니다." />
        <TextBox Name="resultTextBox" Grid.Row="2"
            Margin="10"
            AcceptsReturn="True"
            IsReadOnly="True"
            FontSize="8" />
    </Grid>
</Window>

 

300x250

 

▶ MainWindow.xaml.cs

using Microsoft.Win32;
using System;
using System.Drawing;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;

namespace TestProject
{
    /// <summary>
    /// 메인 윈도우
    /// </summary>
    public partial class MainWindow : Window
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainWindow()

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

            this.selectFileButton.Click += selectFileButton_Click;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private
        //////////////////////////////////////////////////////////////////////////////// Event

        #region 파일 선택 버튼 클릭시 처리하기 - selectFileButton_Click(sender, e)

        /// <summary>
        /// 파일 선택 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        async private void selectFileButton_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.Title  = "이미지 파일 선택";
            openFileDialog.Filter = "이미지 파일|*.jpg;*.png;";
 
            try
            {
                bool result = openFileDialog.ShowDialog().GetValueOrDefault();

                if(result)
                {
                    this.filePathLabel.Content = openFileDialog.FileName;

                    await Task.Run(() => Generate(openFileDialog.FileName));
                }
            }
            catch(Exception exception)
            {
                MessageBox.Show
                (
                    this,
                    string.Format("에러 : {0}", exception.ToString()),
                    "Error",
                    MessageBoxButton.OK,
                    MessageBoxImage.Error
                );
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Function

        #region 생성하기 - Generate(filePath)

        /// <summary>
        /// 생성하기
        /// </summary>
        /// <param name="filePath">파일 경로</param>
        private void Generate(string filePath)
        {
            int targetWidth = 100;
 
            FileInfo fileInfo = new FileInfo(filePath);

            if(!fileInfo.Exists)
            {
                MessageBox.Show
                (
                    this,
                    string.Format("파일을 찾을 수 없습니다. : {0}", filePath),
                    "Information",
                    MessageBoxButton.OK,
                    MessageBoxImage.Information
                );

                return;
            }

            Bitmap bitmap = new Bitmap(filePath);
 
            if(targetWidth > bitmap.Width)
            {
                MessageBox.Show
                (
                    this,
                    string.Format("이미지 파일 너비는 {0} 픽셀 이상이어야 합니다.", targetWidth),
                    "Information",
                    MessageBoxButton.OK,
                    MessageBoxImage.Information
                );

                return;
            }
 
            string result = ASCIIArtHelper.GetASCIIArtString(bitmap, targetWidth);

            Dispatcher.Invoke(() => { this.resultTextBox.Text = result;  }, DispatcherPriority.Normal);
        }

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

댓글을 달아 주세요