using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace ToGrayscale
{
    public class Bitmap32
    {
        // Provide public access to the picture's byte data.
        public byte[] ImageBytes;
        public int RowSizeBytes;
        public const int PixelDataSize = 32;

        // A reference to the Bitmap.
        private Bitmap TheBitmap;

        // Save a reference to the bitmap.
        public Bitmap32(Bitmap bm)
        {
            TheBitmap = bm;
        }

        // Bitmap data.
        private BitmapData TheBitmapData;

        // Return the image's dimensions.
        public int Width
        {
            get
            {
                return TheBitmap.Width;
            }
        }
        public int Height
        {
            get
            {
                return TheBitmap.Height;
            }
        }

        // Provide easy access to the color values.
        public void GetPixel(int x, int y, out byte red, out byte green, out byte blue, out byte alpha)
        {
            int i = y * TheBitmapData.Stride + x * 4;
            blue = ImageBytes[i++];
            green = ImageBytes[i++];
            red = ImageBytes[i++];
            alpha = ImageBytes[i];
        }
        public void SetPixel(int x, int y, byte red, byte green, byte blue, byte alpha)
        {
            int i = y * TheBitmapData.Stride + x * 4;
            ImageBytes[i++] = blue;
            ImageBytes[i++] = green;
            ImageBytes[i++] = red;
            ImageBytes[i] = alpha;
        }
        public byte GetBlue(int x, int y)
        {
            int i = y * TheBitmapData.Stride + x * 4;
            return ImageBytes[i];
        }
        public void SetBlue(int x, int y, byte blue)
        {
            int i = y * TheBitmapData.Stride + x * 4;
            ImageBytes[i] = blue;
        }
        public byte GetGreen(int x, int y)
        {
            int i = y * TheBitmapData.Stride + x * 4;
            return ImageBytes[i + 1];
        }
        public void SetGreen(int x, int y, byte green)
        {
            int i = y * TheBitmapData.Stride + x * 4;
            ImageBytes[i + 1] = green;
        }
        public byte GetRed(int x, int y)
        {
            int i = y * TheBitmapData.Stride + x * 4;
            return ImageBytes[i + 2];
        }
        public void SetRed(int x, int y, byte red)
        {
            int i = y * TheBitmapData.Stride + x * 4;
            ImageBytes[i + 2] = red;
        }
        public byte GetAlpha(int x, int y)
        {
            int i = y * TheBitmapData.Stride + x * 4;
            return ImageBytes[i + 3];
        }
        public void SetAlpha(int x, int y, byte alpha)
        {
            int i = y * TheBitmapData.Stride + x * 4;
            ImageBytes[i + 3] = alpha;
        }

        // Lock the bitmap's data.
        public void LockBitmap()
        {
            // Lock the bitmap data.
            Rectangle bounds = new Rectangle(
                0, 0, TheBitmap.Width, TheBitmap.Height);
            TheBitmapData = TheBitmap.LockBits(bounds,
                ImageLockMode.ReadWrite,
                PixelFormat.Format32bppArgb);
            RowSizeBytes = TheBitmapData.Stride;

            // Allocate room for the data.
            int totalSize = TheBitmapData.Stride * TheBitmapData.Height;
            ImageBytes = new byte[totalSize];

            // Copy the data into the ImageBytes array.
            Marshal.Copy(TheBitmapData.Scan0, ImageBytes, 0, totalSize);
        }

        // Copy the data back into the Bitmap
        // and release resources.
        public void UnlockBitmap()
        {
            // Copy the data back into the bitmap.
            int totalSize = TheBitmapData.Stride * TheBitmapData.Height;
            Marshal.Copy(ImageBytes, 0, TheBitmapData.Scan0, totalSize);

            // Unlock the bitmap.
            TheBitmap.UnlockBits(TheBitmapData);

            // Release resources.
            ImageBytes = null;
            TheBitmapData = null;
        }
    }
}
