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

 

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
    }
}

 

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="WriteableBitmap 클래스 : 비트맵 픽셀 조작하기"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <Grid Margin="10">
        <Image Name="image" Stretch="None" />
    </Grid>
</Window>

 

300x250

 

▶ 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
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요