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

728x90
반응형
728x170

TestProject.zip
다운로드

▶ MainForm.cs

using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;

namespace TestProject
{
    /// <summary>
    /// 메인 폼
    /// </summary>
    public partial class MainForm : Form
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 워터마크 비트맵
        /// </summary>
        private Bitmap watermarkBitmap;

        /// <summary>
        /// 처리 수
        /// </summary>
        private int processedCount = 0;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainForm()

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

            Load                                     += Form_Load;
            this.inputDirectoryPathButton.Click      += inputDirectoryPathButton_Click;
            this.outputDirectoryPathButton.Click     += outputDirectoryPathButton_Click;
            this.watermarkButton.Click               += watermarkButton_Click;
            this.processFileButton.Click             += processFileButton_Click;
            this.backgroundWorker.DoWork             += backgroundWorker_DoWork;
            this.backgroundWorker.ProgressChanged    += backgroundWorker_ProgressChanged;
            this.backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
        }

        #endregion

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

        #region 폼 로드시 처리하기 - Form_Load(sender, e)

        /// <summary>
        /// 폼 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Form_Load(object sender, EventArgs e)
        {
            this.watermarkBitmap = this.watermarkPictureBox.Image as Bitmap;

            this.filePathLabel.Text = string.Empty;
        }

        #endregion
        #region 입력 디렉토리 경로 버튼 클릭시 처리하기 - inputDirectoryPathButton_Click(sender, e)

        /// <summary>
        /// 입력 디렉토리 경로 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void inputDirectoryPathButton_Click(object sender, EventArgs e)
        {
            this.folderBrowseDialog.SelectedPath = this.inputDirectoryPathTextBox.Text;

            if(this.folderBrowseDialog.ShowDialog() == DialogResult.OK)
            {
                this.inputDirectoryPathTextBox.Text = this.folderBrowseDialog.SelectedPath;
            }
        }

        #endregion
        #region 출력 디렉토리 경로 버튼 클릭시 처리하기 - outputDirectoryPathButton_Click(sender, e)

        /// <summary>
        /// 출력 디렉토리 경로 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void outputDirectoryPathButton_Click(object sender, EventArgs e)
        {
            this.folderBrowseDialog.SelectedPath = this.outputDirectoryPathTextBox.Text;

            if(this.folderBrowseDialog.ShowDialog() == DialogResult.OK)
            {
                this.outputDirectoryPathTextBox.Text = this.folderBrowseDialog.SelectedPath;
            }
        }

        #endregion
        #region 워터마크 버튼 클릭시 처리하기 - watermarkButton_Click(sender, e)

        /// <summary>
        /// 워터마크 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void watermarkButton_Click(object sender, EventArgs e)
        {
            this.watermarkButton.Text = string.Empty;

            if(this.watermarkOpenFileDialog.ShowDialog() == DialogResult.OK)
            {
                this.watermarkBitmap = GetBitmap(this.watermarkOpenFileDialog.FileName);

                this.watermarkPictureBox.Image = this.watermarkBitmap;
            }
        }

        #endregion
        #region 파일 처리하기 버튼 클릭시 처리하기 - processFileButton_Click(sender, e)

        /// <summary>
        /// 파일 처리하기 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void processFileButton_Click(object sender, EventArgs e)
        {
            if(this.processFileButton.Text == "파일 처리하기")
            {
                this.processFileButton.Text = "처리 중단하기";

                Cursor = Cursors.WaitCursor;

                this.backgroundWorker.RunWorkerAsync();
            }
            else
            {
                processFileButton.Text = "파일 처리하기";

                this.backgroundWorker.CancelAsync();
            }
        }

        #endregion
        #region 백그라운드 작업자 작업 처리하기 - backgroundWorker_DoWork(sender, e)

        /// <summary>
        /// 백그라운드 작업자 작업 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            int   targetImageWidth  = int.Parse(this.targetImageWidthTextBox.Text);
            int   targetImageHeight = int.Parse(this.targetImageHeightTextBox.Text);
            int   watermarkWidth    = int.Parse(this.targetWatermarkWidthTextBox.Text);
            int   watermarkHeight   = int.Parse(this.targetWatermarkHeightTextBox.Text);
            int   marginX           = int.Parse(this.marginXTextBox.Text);
            int   marginY           = int.Parse(this.marginYTextBox.Text);
            float opacity           = float.Parse(opacityTextBox.Text);

            string outputDirectoryPath = this.outputDirectoryPathTextBox.Text;

            if(!outputDirectoryPath.EndsWith("\\"))
            {
                outputDirectoryPath += "\\";
            }

            Bitmap watermarkBitmap = SetOpacity(this.watermarkBitmap, opacity);

            RectangleF sourceRectangle = new RectangleF(0, 0, watermarkBitmap.Width, watermarkBitmap.Height);

            this.processedCount = 0;

            FileInfo[] fileInfoArray = null;

            try
            {
                DirectoryInfo inputDirectoryInfo = new DirectoryInfo(this.inputDirectoryPathTextBox.Text);

                fileInfoArray = inputDirectoryInfo.GetFiles();
            }
            catch(Exception exception)
            {
                MessageBox.Show(exception.Message);

                e.Cancel = true;

                return;
            }

            foreach(FileInfo fileInfo in fileInfoArray)
            {
                string filePath = Path.Combine(outputDirectoryPath, fileInfo.Name);

                Bitmap bitmap = null;

                try
                {
                    bitmap = new Bitmap(fileInfo.FullName);

                    float scaleX = targetImageWidth  / (float)bitmap.Width;
                    float scaleY = targetImageHeight / (float)bitmap.Height;
                    float scale  = Math.Min(scaleX, scaleY);

                    RectangleF targetRectangle = new RectangleF
                    (
                        marginX,
                        marginY,
                        watermarkWidth / scale,
                        watermarkHeight / scale
                    );

                    using(Graphics graphics = Graphics.FromImage(bitmap))
                    {
                        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

                        graphics.DrawImage(watermarkBitmap, targetRectangle, sourceRectangle, GraphicsUnit.Pixel);
                    }

                    SaveImage(bitmap, filePath);
                }
                catch(Exception excaption)
                {
                    Console.WriteLine("스킵 : {0} ; {1}", fileInfo.Name, excaption.Message);
                }

                this.processedCount++;

                int completeRatio = (100 * this.processedCount) / fileInfoArray.Length;

                Progress progress = new Progress(bitmap, filePath);

                backgroundWorker.ReportProgress(completeRatio, progress);

                if(this.backgroundWorker.CancellationPending)
                {
                    e.Cancel = true;

                    break;
                }
            }
        }

        #endregion
        #region 백그라운드 작업자 진행 변경시 처리하기 - backgroundWorker_ProgressChanged(sender, e)

        /// <summary>
        /// 백그라운드 작업자 진행 변경시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar.Value = e.ProgressPercentage;

            Progress progress = (Progress)e.UserState;

            this.filePathLabel.Text = progress.FilePath;

            this.watermarkPictureBox.Image = progress.Image;

            this.watermarkPictureBox.Refresh();
        }

        #endregion
        #region 백그라운드 작업자 완료시 처리하기 - backgroundWorker_RunWorkerCompleted(sender, e)

        /// <summary>
        /// 백그라운드 작업자 완료시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.progressBar.Value = 0;

            this.filePathLabel.Text = string.Empty;

            this.watermarkPictureBox.Image = this.watermarkBitmap;

            Cursor = Cursors.Default;

            MessageBox.Show("처리 파일 수 : " + processedCount.ToString());

            this.processFileButton.Text = "파일 처리하기";
        }

        #endregion

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

        #region 비트맵 구하기 - GetBitmap(filePath)

        /// <summary>
        /// 비트맵 구하기
        /// </summary>
        /// <param name="filePath">파일 경로</param>
        /// <returns>비트맵</returns>
        private Bitmap GetBitmap(string filePath)
        {
            using(Bitmap bitmap = new Bitmap(filePath))
            {
                return new Bitmap(bitmap);
            }
        }

        #endregion
        #region 불투명도 설정하기 - SetOpacity(sourceBitmap, opacity)

        /// <summary>
        /// 불투명도 설정하기
        /// </summary>
        /// <param name="sourceBitmap">소스 비트맵</param>
        /// <param name="opacity">불투명도</param>
        /// <returns>비트맵</returns>
        private Bitmap SetOpacity(Bitmap sourceBitmap, float opacity)
        {
            Bitmap targetBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height);

            using(Graphics graphics = Graphics.FromImage(targetBitmap))
            {
                graphics.SmoothingMode = SmoothingMode.AntiAlias;

                ColorMatrix colorMatrix = new ColorMatrix();

                colorMatrix.Matrix33 = opacity;

                ImageAttributes imageAttributes = new ImageAttributes();

                imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

                Rectangle targetRectangle = new Rectangle(0, 0, targetBitmap.Width, targetBitmap.Height);

                graphics.DrawImage
                (
                    sourceBitmap,
                    targetRectangle,
                    0,
                    0,
                    sourceBitmap.Width,
                    sourceBitmap.Height,
                    GraphicsUnit.Pixel,
                    imageAttributes
                );
            }

            return targetBitmap;
        }

        #endregion
        #region 이미지 저장하기 - SaveImage(image, filePath)

        /// <summary>
        /// 이미지 저장하기
        /// </summary>
        /// <param name="image">이미지</param>
        /// <param name="filePath">파일 경로</param>
        public void SaveImage(Image image, string filePath)
        {
            string extension = Path.GetExtension(filePath);

            switch(extension.ToLower())
            {
                case ".bmp"  : image.Save(filePath, ImageFormat.Bmp ); break;
                case ".exif" : image.Save(filePath, ImageFormat.Exif); break;
                case ".gif"  : image.Save(filePath, ImageFormat.Gif ); break;
                case ".jpg"  :
                case ".jpeg" : image.Save(filePath, ImageFormat.Jpeg); break;
                case ".png"  : image.Save(filePath, ImageFormat.Png ); break;
                case ".tif"  :
                case ".tiff" : image.Save(filePath, ImageFormat.Tiff); break;
                default      : throw new NotSupportedException("Unknown file extension " + extension);
            }
        }

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

댓글을 달아 주세요