첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

728x90
반응형

■ Bitmap 클래스 : 이미지 비트 단위 블렌딩하기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip



BitwiseBlendType.cs

 

 

namespace TestProject

{

    public enum BitwiseBlendType

    {

        /// <summary>

        /// NONE

        /// </summary>

        NONE,

 

        /// <summary>

        /// OR

        /// </summary>

        OR,

 

        /// <summary>

        /// AND

        /// </summary>

        AND,

 

        /// <summary>

        /// XOR

        /// </summary>

        XOR

    }

}

 

 

BitmapHelper.cs

 

 

using System.Drawing;

using System.Drawing.Drawing2D;

using System.Drawing.Imaging;

using System.Runtime.InteropServices;

 

namespace TestProject

{

    /// <summary>

    /// 비트맵 헬퍼

    /// </summary>

    public static class BitmapHelper

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region 비트맵 복사하기 - CopyBitmap(sourceBitmap, targetWidth)

 

        /// <summary>

        /// 비트맵 복사하기

        /// </summary>

        /// <param name="sourceBitmap">소스 비트맵</param>

        /// <param name="targetWidth">타겟 너비</param>

        /// <returns>비트맵</returns>

        public static Bitmap CopyBitmap(Bitmap sourceBitmap, int targetWidth)

        {

            float ratio = 1.0f;

 

            int maximumSize = sourceBitmap.Width > sourceBitmap.Height ? sourceBitmap.Width : sourceBitmap.Height;

 

            ratio = (float)maximumSize / (float)targetWidth;

 

            Bitmap targetBitmap = (sourceBitmap.Width > sourceBitmap.Height ? new Bitmap(targetWidth, (int)(sourceBitmap.Height / ratio)) :

                                                                              new Bitmap((int)(sourceBitmap.Width / ratio), targetWidth));

 

            using(Graphics targetGraphics = Graphics.FromImage(targetBitmap))

            {

                targetGraphics.CompositingQuality = CompositingQuality.HighQuality;

                targetGraphics.InterpolationMode  = InterpolationMode.HighQualityBicubic;

                targetGraphics.PixelOffsetMode    = PixelOffsetMode.HighQuality;

 

                targetGraphics.DrawImage

                (

                    sourceBitmap,

                    new Rectangle(0, 0, targetBitmap.Width, targetBitmap.Height),

                    new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height),

                    GraphicsUnit.Pixel

                );

 

                targetGraphics.Flush();

            }

 

            return targetBitmap;

        }

 

        #endregion

        #region 비트맵 블렌딩하기 - BelndBitmap(sourceBitmap1, sourceBitmap2, blueBlendType, greenBlendType, redBlendType)

 

        /// <summary>

        /// 비트맵 블렌딩하기

        /// </summary>

        /// <param name="sourceBitmap1">소스 비트맵 1</param>

        /// <param name="sourceBitmap2">소스 비트맵 2</param>

        /// <param name="blueBlendType">청색 블렌딩 타입</param>

        /// <param name="greenBlendType">녹색 블렌딩 타입</param>

        /// <param name="redBlendType">적색 블렌딩 타입</param>

        /// <returns>비트맵</returns>

        public static Bitmap BelndBitmap

        (

            Bitmap           sourceBitmap1,

            Bitmap           sourceBitmap2,

            BitwiseBlendType blueBlendType,

            BitwiseBlendType greenBlendType,

            BitwiseBlendType redBlendType

        )

        {

            BitmapData sourceBitmapData1 = sourceBitmap1.LockBits

            (

                new Rectangle(0, 0, sourceBitmap1.Width, sourceBitmap1.Height),

                ImageLockMode.ReadOnly,

                PixelFormat.Format32bppArgb

            );

 

            byte[] sourceByteArray1 = new byte[sourceBitmapData1.Stride * sourceBitmapData1.Height];

 

            Marshal.Copy(sourceBitmapData1.Scan0, sourceByteArray1, 0, sourceByteArray1.Length);

 

            sourceBitmap1.UnlockBits(sourceBitmapData1);

 

            BitmapData sourceBitmapData2 = sourceBitmap2.LockBits

            (

                new Rectangle(0, 0, sourceBitmap2.Width, sourceBitmap2.Height),

                ImageLockMode.ReadOnly,

                PixelFormat.Format32bppArgb

            );

 

            byte[] sourceByteArray2 = new byte[sourceBitmapData2.Stride * sourceBitmapData2.Height];

 

            Marshal.Copy(sourceBitmapData2.Scan0, sourceByteArray2, 0, sourceByteArray2.Length);

 

            sourceBitmap2.UnlockBits(sourceBitmapData2);

 

            int blue  = 0;

            int green = 0;

            int red   = 0;

 

            for(int k = 0; (k + 4 < sourceByteArray1.Length) && (k + 4 < sourceByteArray2.Length); k += 4)

            {

                if(blueBlendType == BitwiseBlendType.AND)

                {

                    blue = sourceByteArray1[k] & sourceByteArray2[k];

                }

                else if(blueBlendType == BitwiseBlendType.OR)

                {

                    blue = sourceByteArray1[k] | sourceByteArray2[k];

                }

                else if(blueBlendType == BitwiseBlendType.XOR)

                {

                    blue = sourceByteArray1[k] ^ sourceByteArray2[k];

                }

 

                if(greenBlendType == BitwiseBlendType.AND)

                {

                    green = sourceByteArray1[k+1] & sourceByteArray2[k+1];

                }

                else if(greenBlendType == BitwiseBlendType.OR)

                {

                    green = sourceByteArray1[k+1] | sourceByteArray2[k+1];

                }

                else if(greenBlendType == BitwiseBlendType.XOR)

                {

                    green = sourceByteArray1[k+1] ^ sourceByteArray2[k+1];

                }

 

                if(redBlendType == BitwiseBlendType.AND)

                {

                    red = sourceByteArray1[k+2] & sourceByteArray2[k+2];

                }

                else if(redBlendType == BitwiseBlendType.OR)

                {

                    red = sourceByteArray1[k+2] | sourceByteArray2[k+2];

                }

                else if(redBlendType == BitwiseBlendType.XOR)

                {

                    red = sourceByteArray1[k+2] ^ sourceByteArray2[k+2];

                }

 

                if(blue < 0)

                {

                    blue = 0;

                }

                else if(blue > 255)

                {

                    blue = 255;

                }

 

                if(green < 0)

                {

                    green = 0;

                }

                else if(green > 255)

                {

                    green = 255;

                }

 

                if(red < 0)

                {

                    red = 0;

                }

                else if(red > 255)

                {

                    red = 255;

                }

 

                sourceByteArray1[k    ] = (byte)blue;

                sourceByteArray1[k + 1] = (byte)green;

                sourceByteArray1[k + 2] = (byte)red;

            }

 

            Bitmap targetBitmap = new Bitmap(sourceBitmap1.Width, sourceBitmap1.Height);

 

            BitmapData targetBitmapData = targetBitmap.LockBits

            (

                new Rectangle(0, 0, targetBitmap.Width, targetBitmap.Height),

                ImageLockMode.WriteOnly,

                PixelFormat.Format32bppArgb

            );

 

            Marshal.Copy(sourceByteArray1, 0, targetBitmapData.Scan0, sourceByteArray1.Length);

 

            targetBitmap.UnlockBits(targetBitmapData);

 

            return targetBitmap;

        }

 

        #endregion

    }

}

 

 

MainForm.cs

 

 

using System;

using System.Drawing;

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>

        /// 소스 비트맵 1

        /// </summary>

        private Bitmap sourceBitmap1 = null;

 

        /// <summary>

        /// 소스 비트맵 2

        /// </summary>

        private Bitmap sourceBitmap2 = null;

 

        /// <summary>

        /// 타겟 비트맵

        /// </summary>

        private Bitmap targetBitmap = null;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            this.blueBlendTypeComboBox.Items.Add(BitwiseBlendType.NONE);

            this.blueBlendTypeComboBox.Items.Add(BitwiseBlendType.AND );

            this.blueBlendTypeComboBox.Items.Add(BitwiseBlendType.OR  );

            this.blueBlendTypeComboBox.Items.Add(BitwiseBlendType.XOR );

 

            this.blueBlendTypeComboBox.SelectedIndex = 0;

 

            this.greenBlendTypeComboBox.Items.Add(BitwiseBlendType.NONE);

            this.greenBlendTypeComboBox.Items.Add(BitwiseBlendType.AND );

            this.greenBlendTypeComboBox.Items.Add(BitwiseBlendType.OR  );

            this.greenBlendTypeComboBox.Items.Add(BitwiseBlendType.XOR );

 

            this.greenBlendTypeComboBox.SelectedIndex = 0;

 

            this.redBlendTypeComboBox.Items.Add(BitwiseBlendType.NONE);

            this.redBlendTypeComboBox.Items.Add(BitwiseBlendType.AND );

            this.redBlendTypeComboBox.Items.Add(BitwiseBlendType.OR  );

            this.redBlendTypeComboBox.Items.Add(BitwiseBlendType.XOR );

 

            this.redBlendTypeComboBox.SelectedIndex = 0;

 

            this.loadSourceImage1Button.Click                += loadSourceImageButton_Click;

            this.loadSourceImage2Button.Click                += loadSourceImageButton_Click;

            this.blueBlendTypeComboBox.SelectedIndexChanged  += blendTypeComboBox_SelectedIndexChanged;

            this.greenBlendTypeComboBox.SelectedIndexChanged += blendTypeComboBox_SelectedIndexChanged;

            this.redBlendTypeComboBox.SelectedIndexChanged   += blendTypeComboBox_SelectedIndexChanged;

            this.saveImageButton.Click                       += saveImageButton_Click;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 소스 이미지 로드 버튼 클릭시 처리하기 - loadSourceImageButton_Click(sender, e)

 

        /// <summary>

        /// 소스 이미지 로드 버튼 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void loadSourceImageButton_Click(object sender, EventArgs e)

        {

            OpenFileDialog openFileDialog = new OpenFileDialog();

 

            openFileDialog.Title  = "이미지 파일 로드";

            openFileDialog.Filter = "PNG 파일(*.png)|*.png|JPEG 파일(*.jpg)|*.jpg|비트맵 파일(*.bmp)|*.bmp";

 

            if(openFileDialog.ShowDialog() == DialogResult.OK)

            {

                if(sender == this.loadSourceImage1Button)

                {

                    StreamReader streamReader = new StreamReader(openFileDialog.FileName);

 

                    this.sourceBitmap1 = Bitmap.FromStream(streamReader.BaseStream) as Bitmap;

 

                    streamReader.Close();

 

                    this.sourceImage1PictureBox.Image = BitmapHelper.CopyBitmap(this.sourceBitmap1, this.targetImagePictureBox.Width);

                }

                else if(sender == this.loadSourceImage2Button)

                {

                    StreamReader streamReader = new StreamReader(openFileDialog.FileName);

 

                    this.sourceBitmap2 = Bitmap.FromStream(streamReader.BaseStream) as Bitmap;

 

                    streamReader.Close();

 

                    this.sourceImage2PictureBox.Image = BitmapHelper.CopyBitmap(this.sourceBitmap2, this.targetImagePictureBox.Width);

                }

 

                ApplyFilter(true);

            }

        }

 

        #endregion

        #region 블렌딩 타입 콤보 박스 선택 인덱스 변경시 처리하기 - blendTypeComboBox_SelectedIndexChanged(sender, e)

 

        /// <summary>

        /// 블렌딩 타입 콤보 박스 선택 인덱스 변경시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void blendTypeComboBox_SelectedIndexChanged(object sender, EventArgs e)

        {

            ApplyFilter(true);

        }

 

        #endregion

        #region 이미지 저장 버튼 클릭시 처리하기 - saveImageButton_Click(sender, e)

 

        /// <summary>

        /// 이미지 저장 버튼 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void saveImageButton_Click(object sender, EventArgs e)

        {

            ApplyFilter(false);

 

            if(this.targetBitmap != null)

            {

                SaveFileDialog saveFileDialog = new SaveFileDialog();

 

                saveFileDialog.Title  = "이미지 파일 저장";

                saveFileDialog.Filter = "PNG 파일(*.png)|*.png|JPEG 파일(*.jpg)|*.jpg|비트맵 파일(*.bmp)|*.bmp";

 

                if(saveFileDialog.ShowDialog() == DialogResult.OK)

                {

                    string fileExtension = Path.GetExtension(saveFileDialog.FileName).ToUpper();

 

                    ImageFormat imageFormat = ImageFormat.Png;

 

                    if(fileExtension == "BMP")

                    {

                        imageFormat = ImageFormat.Bmp;

                    }

                    else if(fileExtension == "JPG")

                    {

                        imageFormat = ImageFormat.Jpeg;

                    }

 

                    StreamWriter streamWriter = new StreamWriter(saveFileDialog.FileName, false);

 

                    targetBitmap.Save(streamWriter.BaseStream, imageFormat);

 

                    streamWriter.Flush();

                    streamWriter.Close();

 

                    targetBitmap = null;

                }

            }

        }

 

        #endregion

 

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

 

        #region 필터 적용하기 - ApplyFilter(preview)

 

        /// <summary>

        /// 필터 적용하기

        /// </summary>

        /// <param name="preview">미리보기 여부</param>

        private void ApplyFilter(bool preview)

        {

            if(this.sourceBitmap1 == null || this.sourceBitmap2 == null ||

               this.sourceImage2PictureBox.Image == null || this.sourceImage1PictureBox.Image == null)

            {

                return;

            }

 

            if(preview == true)

            {

                this.targetImagePictureBox.Image = BitmapHelper.BelndBitmap

                (

                    this.sourceImage1PictureBox.Image as Bitmap,

                    this.sourceImage2PictureBox.Image as Bitmap,

                    (BitwiseBlendType)this.blueBlendTypeComboBox.SelectedItem,

                    (BitwiseBlendType)this.greenBlendTypeComboBox.SelectedItem,

                    (BitwiseBlendType)this.redBlendTypeComboBox.SelectedItem

                );

            }

            else

            {

                this.targetBitmap = BitmapHelper.BelndBitmap

                (

                    this.sourceBitmap1,

                    this.sourceBitmap2,

                    (BitwiseBlendType)blueBlendTypeComboBox.SelectedItem,

                    (BitwiseBlendType)greenBlendTypeComboBox.SelectedItem,

                    (BitwiseBlendType)redBlendTypeComboBox.SelectedItem

                );

            }

        }

 

        #endregion

    }

}

 

------------------------------------------------------------------------------------------------------------------------

728x90
반응형
Posted by 사용자 icodebroker

댓글을 달아 주세요