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

■ WriteableBitmap 클래스 : 비트맵 픽셀 조작하기

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


TestProject.zip


BitmapPixelHelper.cs

 

 

using System;

using System.Windows;

using System.Windows.Media;

using System.Windows.Media.Imaging;

 

namespace TestProject

{

    /// <summary>

    /// 비트맵 픽셀 헬퍼

    /// </summary>

    /// <remarks>BGRA32 포맷</remarks>

    public class BitmapPixelHelper

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

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

 

        #region Field

 

        /// <summary>

        /// 너비

        /// </summary>

        public int Width;

        

        /// <summary>

        /// 높이

        /// </summary>

        public int Height;

 

        #endregion

 

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

 

        #region Field

 

        /// <summary>

        /// 픽셀 바이트 배열

        /// </summary>

        private byte[] pixelByteArray;

 

        /// <summary>

        /// 스트라이드

        /// </summary>

        /// <remarks>행당 바이트 수</remarks>

        private int stride;

 

        #endregion

 

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

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

 

        #region 생성자 - BitmapPixelHelper(width, height)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="width">너비</param>

        /// <param name="height">높이</param>

        public BitmapPixelHelper(int width, int height)

        {

            Initialize(width, height);

        }

 

        #endregion

        #region 생성자 - BitmapPixelHelper(bitmap)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="bitmap">쓰기 가능 비트맵</param>

        public BitmapPixelHelper(WriteableBitmap bitmap)

        {

            Initialize(bitmap);

        }

 

        #endregion

        #region 생성자 - BitmapPixelHelper(uri)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="uri">URI</param>

        public BitmapPixelHelper(Uri uri)

        {

            BitmapImage bitmapImage = new BitmapImage(uri);

 

            WriteableBitmap bitmap = new WriteableBitmap(bitmapImage);

 

            Initialize(bitmap);

        }

 

        #endregion

 

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

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

 

        #region 픽셀 구하기 - GetPixel(x, y, red, green, blue, alpha)

 

        /// <summary>

        /// 픽셀 구하기

        /// </summary>

        /// <param name="x">X</param>

        /// <param name="y">Y</param>

        /// <param name="red">적색</param>

        /// <param name="green">녹색</param>

        /// <param name="blue">청색</param>

        /// <param name="alpha">알파</param>

        public void GetPixel(int x, int y, out byte red, out byte green, out byte blue, out byte alpha)

        {

            int index = y * this.stride + x * 4;

 

            blue  = this.pixelByteArray[index++];

            green = this.pixelByteArray[index++];

            red   = this.pixelByteArray[index++];

            alpha = this.pixelByteArray[index];

        }

 

        #endregion

        #region 청색 구하기 - GetBlue(x, y)

 

        /// <summary>

        /// 청색 구하기

        /// </summary>

        /// <param name="x">X</param>

        /// <param name="y">Y</param>

        /// <returns>청색</returns>

        public byte GetBlue(int x, int y)

        {

            return this.pixelByteArray[y * this.stride + x * 4];

        }

 

        #endregion

        #region 녹색 구하기 - GetGreen(x, y)

 

        /// <summary>

        /// 녹색 구하기

        /// </summary>

        /// <param name="x">X</param>

        /// <param name="y">Y</param>

        /// <returns>녹색</returns>

        public byte GetGreen(int x, int y)

        {

            return this.pixelByteArray[y * this.stride + x * 4 + 1];

        }

 

        #endregion

        #region 적색 구하기 - GetRed(x, y)

 

        /// <summary>

        /// 적색 구하기

        /// </summary>

        /// <param name="x">X</param>

        /// <param name="y">Y</param>

        /// <returns>적색</returns>

        public byte GetRed(int x, int y)

        {

            return this.pixelByteArray[y * this.stride + x * 4 + 2];

        }

 

        #endregion

        #region 알파 구하기 - GetAlpha(x, y)

 

        /// <summary>

        /// 알파 구하기

        /// </summary>

        /// <param name="x">X</param>

        /// <param name="y">Y</param>

        /// <returns>알파</returns>

        public byte GetAlpha(int x, int y)

        {

            return this.pixelByteArray[y * this.stride + x * 4 + 3];

        }

 

        #endregion

        #region 픽셀 설정하기 - SetPixel(x, y, red, green, blue, alpha)

 

        /// <summary>

        /// 픽셀 설정하기

        /// </summary>

        /// <param name="x">X</param>

        /// <param name="y">Y</param>

        /// <param name="red">적색</param>

        /// <param name="green">녹색</param>

        /// <param name="blue">청색</param>

        /// <param name="alpha">알파</param>

        public void SetPixel(int x, int y, byte red, byte green, byte blue, byte alpha)

        {

            int index = y * this.stride + x * 4;

 

            this.pixelByteArray[index++] = blue;

            this.pixelByteArray[index++] = green;

            this.pixelByteArray[index++] = red;

            this.pixelByteArray[index++] = alpha;

        }

 

        #endregion

        #region 청색 설정하기 - SetBlue(x, y, blue)

 

        /// <summary>

        /// 청색 설정하기

        /// </summary>

        /// <param name="x">X</param>

        /// <param name="y">Y</param>

        /// <param name="blue">청색</param>

        public void SetBlue(int x, int y, byte blue)

        {

            this.pixelByteArray[y * this.stride + x * 4] = blue;

        }

 

        #endregion

        #region 녹색 설정하기 - SetGreen(x, y, green)

 

        /// <summary>

        /// 녹색 설정하기

        /// </summary>

        /// <param name="x">X</param>

        /// <param name="y">Y</param>

        /// <param name="green">녹색</param>

        public void SetGreen(int x, int y, byte green)

        {

            this.pixelByteArray[y * this.stride + x * 4 + 1] = green;

        }

 

        #endregion

        #region 적색 설정하기 - SetRed(x, y, red)

 

        /// <summary>

        /// 적색 설정하기

        /// </summary>

        /// <param name="x">X</param>

        /// <param name="y">Y</param>

        /// <param name="red">적색</param>

        public void SetRed(int x, int y, byte red)

        {

            this.pixelByteArray[y * this.stride + x * 4 + 2] = red;

        }

 

        #endregion

        #region 알파 설정하기 - SetAlpha(x, y, alpha)

 

        /// <summary>

        /// 알파 설정하기

        /// </summary>

        /// <param name="x">X</param>

        /// <param name="y">Y</param>

        /// <param name="alpha">적색</param>

        public void SetAlpha(int x, int y, byte alpha)

        {

            this.pixelByteArray[y * this.stride + x * 4 + 3] = alpha;

        }

 

        #endregion

        #region 색상 설정하기 - SetColor(red, green, blue, alpha)

 

        /// <summary>

        /// 색상 설정하기

        /// </summary>

        /// <param name="red">적색</param>

        /// <param name="green">녹섹</param>

        /// <param name="blue">청색</param>

        /// <param name="alpha">알파</param>

        public void SetColor(byte red, byte green, byte blue, byte alpha)

        {

            int byteCount = Width * Height * 4;

 

            int index = 0;

 

            while(index < byteCount)

            {

                this.pixelByteArray[index++] = blue;

                this.pixelByteArray[index++] = green;

                this.pixelByteArray[index++] = red;

                this.pixelByteArray[index++] = alpha;

            }

        }

 

        #endregion

        #region 색상 설정하기 - SetColor(red, green, blue)

 

        /// <summary>

        /// 색상 설정하기

        /// </summary>

        /// <param name="red">적색</param>

        /// <param name="green">녹섹</param>

        /// <param name="blue">청색</param>

        public void SetColor(byte red, byte green, byte blue)

        {

            SetColor(red, green, blue, 255);

        }

 

        #endregion

        #region 비트맵 구하기 - GetBitmap(dpiX, dpiY)

 

        /// <summary>

        /// 비트맵 구하기

        /// </summary>

        /// <param name="dpiX">DPI X</param>

        /// <param name="dpiY">DPI Y</param>

        /// <returns>쓰기 가능 비트맵</returns>

        public WriteableBitmap GetBitmap(double dpiX, double dpiY)

        {

            WriteableBitmap bitmap = new WriteableBitmap

            (

                Width,

                Height,

                dpiX,

                dpiY,

                PixelFormats.Bgra32,

                null

            );

 

            Int32Rect rectangle = new Int32Rect(0, 0, Width, Height);

 

            bitmap.WritePixels(rectangle, this.pixelByteArray, this.stride, 0);

 

            return bitmap;

        }

 

        #endregion

 

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

 

        #region 초기화하기 - Initialize(width, height)

 

        /// <summary>

        /// 초기화하기

        /// </summary>

        /// <param name="width">너비</param>

        /// <param name="height">높이</param>

        private void Initialize(int width, int height)

        {

            Width  = width;

            Height = height;

 

            this.pixelByteArray = new byte[width * height * 4];

 

            this.stride = width * 4;

        }

 

        #endregion

        #region 초기화하기 - Initialize(bitmap)

 

        /// <summary>

        /// 초기화하기

        /// </summary>

        /// <param name="bitmap">쓰기 가능 비트맵</param>

        private void Initialize(WriteableBitmap bitmap)

        {

            int width  = Convert.ToInt32(bitmap.Width);

            int height = Convert.ToInt32(bitmap.Height);

 

            Initialize(width, height);

 

            Int32Rect rectangle = new Int32Rect(0, 0, Width, Height);

 

            bitmap.CopyPixels(rectangle, this.pixelByteArray, this.stride, 0);

        }

 

        #endregion

    }

}

 

 

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="WriteableBitmap 클래스 : 비트맵 픽셀 조작하기"

    FontFamily="나눔고딕코딩"

    FontSize="16">

    <Grid Margin="10">

        <Image Name="image" Stretch="None" />

    </Grid>

</Window>

 

 

MainWindow.xaml.cs

 

 

using System;

using System.Windows;

using System.Windows.Media.Imaging;

 

namespace TestProject

{

    /// <summary>

    /// 메인 윈도우

    /// </summary>

    public partial class MainWindow : Window

    {

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

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

 

        #region 생성자 - MainWindow()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainWindow()

        {

            InitializeComponent();

 

            Loaded += Window_Loaded;

        }

 

        #endregion

 

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

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

 

        #region 윈도우 로드시 처리하기 - Window_Loaded(sender, e)

 

        /// <summary>

        /// 윈도우 로드시 처리하기

        /// </summary>

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

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

        private void Window_Loaded(object sender, RoutedEventArgs e)

        {

            Uri uri = new Uri("IMAGE/Smiley.png", UriKind.Relative);

 

            BitmapPixelHelper helper = new BitmapPixelHelper(uri);

 

            int cellWidth   = helper.Width  / 4;

            int cellHeight  = helper.Height / 4;

            int columnCount = helper.Width  / cellWidth;

            int rowCount    = helper.Height / cellHeight;

 

            for(int row = 0; row < rowCount; row++)

            {

                for(int column = 0; column < columnCount; column++)

                {

                    for(int i = 0; i < cellWidth; i++)

                    {

                        for(int j = 0; j < cellHeight; j++)

                        {

                            int x = column * cellWidth  + j;

                            int y = row    * cellHeight + i;

 

                            if((x < helper.Width) && (y < helper.Height))

                            {

                                byte red;

                                byte green;

                                byte blue;

                                byte alpha;

 

                                helper.GetPixel(x, y, out red, out green, out blue, out alpha);

 

                                if((column + row) % 2 == 0)

                                {

                                    red   = (byte)(255 - (255 - red  ) * 0.75);

                                    green = (byte)(255 - (255 - green) * 0.75);

                                    blue  = (byte)(255 - (255 - blue ) * 0.75);

                                }

                                else

                                {

                                    red   = (byte)(red   * 0.75);

                                    green = (byte)(green * 0.75);

                                    blue  = (byte)(blue  * 0.75);

                                }

 

                                helper.SetPixel(x, y, red, green, blue, alpha);

                            }

                        }

                    }

                }

            }

 

            WriteableBitmap bitmap = helper.GetBitmap(96, 96);

 

            this.image.Source = bitmap;

        }

 

        #endregion

    }

}

 

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

Posted by 사용자 icodebroker

댓글을 달아 주세요