그림의 내용을 배열에 담고 있을 때, 이 그림을 담은 Bitmap 객체를 만들거나,

혹은 그 반대의 동작을 하는 함수들을 담은 클래스입니다.

 

SetPixel()이나 GetPixel()을 사용하면 구현할 수 있으나 실용적으로 이용하기에는 너무 느리므로 다음의 클래스 함수가 유용합니다.

 


 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

class TBitmap
{
    //=========================================================================
    //  gray 2D array => bitmap
    //=========================================================================
    public static Bitmap BitmapOfGrayArr(int[,] inten2D, PixelFormat pxlformat)
    {
        int xsize = inten2D.GetLength(0);
        int ysize = inten2D.GetLength(1);
        Bitmap bitmap = null;

        if (pxlformat == PixelFormat.Format24bppRgb)
        {
            bitmap = new Bitmap(xsize, ysize, PixelFormat.Format24bppRgb);
            BitmapData bmpdata = bitmap.LockBits(
                  new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                  ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int stride = bmpdata.Stride;
            int nbytes = stride * bitmap.Height;
            byte[] rgb1D = new byte[nbytes];

            // 배열에 그림 내용 채우기
            int idxBlue = 0;
            for (int ix = 0; ix < xsize; ix++)
            {
                for (int iy = 0; iy < ysize; iy++)
                {
                    idxBlue = iy * stride + 3 * ix;
                    rgb1D[idxBlue + 0] = Convert.ToByte(inten2D[ix, iy]);
                    rgb1D[idxBlue + 1] = Convert.ToByte(inten2D[ix, iy]);
                    rgb1D[idxBlue + 2] = Convert.ToByte(inten2D[ix, iy]);
                }
            }

            // 배열에 있는 그림을 bitmap에 복사
            System.Runtime.InteropServices.Marshal.Copy(rgb1D, 0, bmpdata.Scan0, nbytes);
            bitmap.UnlockBits(bmpdata);
        }
        else if (pxlformat == PixelFormat.Format8bppIndexed)
        {
            bitmap = new Bitmap(xsize, ysize, PixelFormat.Format8bppIndexed);
            BitmapData bmpdata = bitmap.LockBits(
                  new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                  ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);

            int stride = bmpdata.Stride;
            int nbytes = stride * bitmap.Height;
            byte[] rgb1D = new byte[nbytes];

            // 배열에 그림 내용 채우기
            ColorPalette pal = bitmap.Palette;
            for (int i = 0; i < 256; i++)
                pal.Entries[i] = Color.FromArgb(255, i, i, i);
            bitmap.Palette = pal;

            int idxPxl = 0;
            for (int ix = 0; ix < xsize; ix++)
            {
                for (int iy = 0; iy < ysize; iy++)
                {
                    idxPxl = iy * stride + ix;
                    rgb1D[idxPxl + 0] = Convert.ToByte(inten2D[ix, iy]);
                }
            }

            // 배열에 있는 그림을 bitmap에 복사
            System.Runtime.InteropServices.Marshal.Copy(rgb1D, 0, bmpdata.Scan0, nbytes);
            bitmap.UnlockBits(bmpdata);
        }

        //~~~~  검증
        //for (int iy = 0; iy < ysize; iy++)
        //{
        //    for (int ix = 0; ix < xsize; ix++)
        //    {
        //        if (bitmap.GetPixel(ix, iy).R != inten2D[ix, iy])
        //        {
        //            Console.WriteLine("{0}, {1}, {2}", bitmap.GetPixel(ix, iy).R,
        //                                                bitmap.GetPixel(ix, iy).G,
        //                                                bitmap.GetPixel(ix, iy).B);
        //        }
        //    }
        //}

        return bitmap;
    }

    //=========================================================================
    //  rgb 2D array => bitmap (Format24bppRgb 포맷만)
    //=========================================================================
    public static Bitmap BitmapOfRGBArr(int[,] red, int[,] green, int[,] blue)
    {
        int xsize = red.GetLength(0);
        int ysize = red.GetLength(1);
        Bitmap bitmap = null;

        bitmap = new Bitmap(xsize, ysize, PixelFormat.Format24bppRgb);
        BitmapData bmpdata = bitmap.LockBits(
              new Rectangle(0, 0, bitmap.Width, bitmap.Height),
              ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

        int stride = bmpdata.Stride;
        int nbytes = stride * bitmap.Height;
        byte[] rgb1D = new byte[nbytes];

        // 배열에 그림 내용 채우기
        int idxBlue = 0;
        for (int ix = 0; ix < xsize; ix++)
        {
            for (int iy = 0; iy < ysize; iy++)
            {
                idxBlue = iy * stride + 3 * ix;
                rgb1D[idxBlue + 0] = Convert.ToByte(blue[ix, iy]);
                rgb1D[idxBlue + 1] = Convert.ToByte(green[ix, iy]);
                rgb1D[idxBlue + 2] = Convert.ToByte(red[ix, iy]);
            }
        }

        // 배열에 있는 그림을 bitmap에 복사
        System.Runtime.InteropServices.Marshal.Copy(rgb1D, 0, bmpdata.Scan0, nbytes);
        bitmap.UnlockBits(bmpdata);

        //~~~~  검증
        //for (int iy = 0; iy < ysize; iy++)
        //{
        //    for (int ix = 0; ix < xsize; ix++)
        //    {
        //        if ((bitmap.GetPixel(ix, iy).R != red[ix, iy]) ||
        //            (bitmap.GetPixel(ix, iy).G != green[ix, iy]) ||
        //            (bitmap.GetPixel(ix, iy).B != blue[ix, iy]))
        //        {
        //            Console.WriteLine("{0}, {1}, {2}", bitmap.GetPixel(ix, iy).R,
        //                                                bitmap.GetPixel(ix, iy).G,
        //                                                bitmap.GetPixel(ix, iy).B);
        //        }
        //    }
        //}

        return bitmap;
    }

    //=========================================================================
    //  bitmap => gray 2D array
    //=========================================================================
    public static byte[,] GrayArrOfBitmap(Bitmap bitmap)
    {
        int xsize = bitmap.Width;
        int ysize = bitmap.Height;
        byte[,] inten2D = new byte[xsize, ysize];

        if (bitmap.PixelFormat == PixelFormat.Format24bppRgb)
        {
            //  이미지의 좌측 상단에서 시작하여 가로방향으로 먼저 스캔.
            //  b,g,r, b,g,r, b,g,r, .... 순서로 저장
            //  x 방향 끝에는 옵셋이 들어 있으므로 stride를 사용해서 인덱싱 해야 함

            BitmapData bmpdata = bitmap.LockBits(
                  new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                  ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int stride = bmpdata.Stride;
            int nbytes = stride * bitmap.Height;
            byte[] rgb1D = new byte[nbytes];
            System.Runtime.InteropServices.Marshal.Copy(bmpdata.Scan0, rgb1D, 0, nbytes);
            bitmap.UnlockBits(bmpdata);

            // 2차원 배열에 옮기기
            int idxBlue = 0;
            for (int ix = 0; ix < xsize; ix++)
            {
                for (int iy = 0; iy < ysize; iy++)
                {
                    idxBlue = iy * stride + 3 * ix;
                    byte b = rgb1D[idxBlue + 0];
                    byte g = rgb1D[idxBlue + 1];
                    byte r = rgb1D[idxBlue + 2];
                    inten2D[ix, iy] = Convert.ToByte(0.299 * r + 0.587 * g + 0.114 * b);
                }
            }
        }
        else if (bitmap.PixelFormat == PixelFormat.Format8bppIndexed)
        {
            //  이미지의 좌측 상단에서 시작하여 가로방향으로 먼저 스캔.
            //  1. Pallette에 인덱싱 정보 들어있고
            //  2. inten, inten, inten,... 순서로 저장
            //  x 방향 끝에는 옵셋이 들어 있으므로 stride를 사용해서 인덱싱 해야 함

            BitmapData bmpdata = bitmap.LockBits(
                  new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                  ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);

            int stride = bmpdata.Stride;
            int nbytes = stride * bitmap.Height;
            byte[] rgb1D = new byte[nbytes];
            System.Runtime.InteropServices.Marshal.Copy(bmpdata.Scan0, rgb1D, 0, nbytes);
            bitmap.UnlockBits(bmpdata);

            // 2차원 배열에 옮기기
            ColorPalette pal = bitmap.Palette;

            int idxPxl = 0;
            for (int ix = 0; ix < xsize; ix++)
            {
                for (int iy = 0; iy < ysize; iy++)
                {
                    idxPxl = iy * stride + ix;
                    byte r = pal.Entries[rgb1D[idxPxl + 0]].R;
                    byte g = pal.Entries[rgb1D[idxPxl + 0]].G;
                    byte b = pal.Entries[rgb1D[idxPxl + 0]].B;
                    inten2D[ix, iy] = Convert.ToByte(0.299 * r + 0.587 * g + 0.114 * b);
                }
            }
        }

        //~~~~  검증
        //for (int iy = 0; iy < ysize; iy++)
        //{
        //    for (int ix = 0; ix < xsize; ix++)
        //    {
        //        if (bitmap.GetPixel(ix, iy).R != inten2D[ix, iy])
        //        {
        //            Console.WriteLine("{0}, {1}, {2}", bitmap.GetPixel(ix, iy).R,
        //                                                bitmap.GetPixel(ix, iy).G,
        //                                                bitmap.GetPixel(ix, iy).B);
        //        }
        //    }
        //}

        return inten2D;
    }

    //=========================================================================
    //  bitmap => rgb 2D array. Format24bppRgb 포맷만
    //=========================================================================
    public static void RGBArrOfBitmap(Bitmap bitmap, out byte[,] red, out byte[,] green, out byte[,] blue)
    {
        int xsize = bitmap.Width;
        int ysize = bitmap.Height;
       
        red = new byte[xsize, ysize];
        green = new byte[xsize, ysize];
        blue = new byte[xsize, ysize];

        if (bitmap.PixelFormat == PixelFormat.Format24bppRgb)
        {
            //  이미지의 좌측 상단에서 시작하여 가로방향으로 먼저 스캔.
            //  b,g,r, b,g,r, b,g,r, .... 순서로 저장
            //  x 방향 끝에는 옵셋이 들어 있으므로 stride를 사용해서 인덱싱 해야 함

            BitmapData bmpdata = bitmap.LockBits(
                  new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                  ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int stride = bmpdata.Stride;
            int nbytes = stride * bitmap.Height;
            byte[] rgb1D = new byte[nbytes];
            System.Runtime.InteropServices.Marshal.Copy(bmpdata.Scan0, rgb1D, 0, nbytes);
            bitmap.UnlockBits(bmpdata);

            // 2차원 배열에 옮기기
            int idxBlue = 0;
            for (int ix = 0; ix < xsize; ix++)
            {
                for (int iy = 0; iy < ysize; iy++)
                {
                    idxBlue = iy * stride + 3 * ix;
                    blue[ix, iy] = rgb1D[idxBlue + 0];
                    green[ix, iy] = rgb1D[idxBlue + 1];
                    red[ix, iy] = rgb1D[idxBlue + 2];
                }
            }
        }
        else
        {
        }

        //~~~~  검증
        //for (int iy = 0; iy < ysize; iy++)
        //{
        //    for (int ix = 0; ix < xsize; ix++)
        //    {
        //        if ((bitmap.GetPixel(ix, iy).R != red[ix, iy]) ||
        //            (bitmap.GetPixel(ix, iy).G != green[ix, iy]) ||
        //            (bitmap.GetPixel(ix, iy).B != blue[ix, iy]))
        //        {
        //            Console.WriteLine("{0}, {1}, {2}", bitmap.GetPixel(ix, iy).R,
        //                                                bitmap.GetPixel(ix, iy).G,
        //                                                bitmap.GetPixel(ix, iy).B);
        //        }
        //    }
        //}
    }
}

 

Posted by 마스샘