BitmapLocker Test

CSharp · Console

/Program.cs

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TestTestTest
{
    public partial class PictureBoxForm : Form
    {
        public PictureBoxForm()
        {
            InitializeComponent();
        }

        public PictureBoxForm(Bitmap image)
        {
            InitializeComponent();
            this.pictureBox1.Image = image as System.Drawing.Image;
        }

        public PictureBoxForm(Bitmap image1, Bitmap image2)
        {
            InitializeComponent();
            this.pictureBox1.Image = image1 as System.Drawing.Image;
            this.pictureBox2.Image = image2 as System.Drawing.Image;
        }
    }

    partial class PictureBoxForm
    {
        private System.ComponentModel.IContainer components = null;
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }

            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code
        private void InitializeComponent()
        {
            this.pictureBox1 = new System.Windows.Forms.PictureBox();
            this.pictureBox2 = new System.Windows.Forms.PictureBox();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit();
            this.SuspendLayout();
            // 
            // pictureBox1
            // 
            this.pictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            this.pictureBox1.Location = new System.Drawing.Point(12, 12);
            this.pictureBox1.Name = "pictureBox1";
            this.pictureBox1.Size = new System.Drawing.Size(600, 600);
            this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
            this.pictureBox1.TabIndex = 0;
            this.pictureBox1.TabStop = false;
            // 
            // pictureBox2
            // 
            this.pictureBox2.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            this.pictureBox2.Location = new System.Drawing.Point(618, 12);
            this.pictureBox2.Name = "pictureBox2";
            this.pictureBox2.Size = new System.Drawing.Size(250, 250);
            this.pictureBox2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
            this.pictureBox2.TabIndex = 1;
            this.pictureBox2.TabStop = false;
            // 
            // PictureBoxForm
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(882, 625);
            this.Controls.Add(this.pictureBox2);
            this.Controls.Add(this.pictureBox1);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.MaximizeBox = false;
            this.Name = "PictureBoxForm";
            this.Text = "PictureBoxForm";
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit();
            this.ResumeLayout(false);
        }

        #endregion
        private System.Windows.Forms.PictureBox pictureBox1;
        private System.Windows.Forms.PictureBox pictureBox2;
    }

    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            //Application.Run(new FourierForm());
            //Application.Run(new ConvolutionForm());
            //Application.Run(new KassWitkinForm());
            //KassWitkinImageOperation.Run();
            BitmapLockerTest.Run();
        }
    }

    public partial class Grayscale
    {
        public static unsafe Bitmap ToGrayscale(Bitmap bmColor)
        {
            int Width = bmColor.Width;
            int Height = bmColor.Height;
            Bitmap bmMono = new Bitmap(Width, Height, PixelFormat.Format8bppIndexed);
            bmMono.SetResolution(bmColor.HorizontalResolution, bmColor.VerticalResolution);
            ///////////////////////////////////////
            // Set grayscale palette
            ///////////////////////////////////////
            ColorPalette colorPalette = bmMono.Palette;
            for (int i = 0; i < colorPalette.Entries.Length; i++)
            {
                colorPalette.Entries[i] = Color.FromArgb(i, i, i);
            }

            bmMono.Palette = colorPalette;
            BitmapData bmd = bmMono.LockBits(new Rectangle(Point.Empty, bmMono.Size), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
            Byte* pPixel = (Byte*)bmd.Scan0;
            for (int y = 0; y < Height; y++)
            {
                for (int x = 0; x < Width; x++)
                {
                    Color clr = bmColor.GetPixel(x, y);
                    Byte byPixel = (byte)((30 * clr.R + 59 * clr.G + 11 * clr.B) / 100);
                    pPixel[x] = byPixel;
                }

                pPixel += bmd.Stride;
            }

            bmMono.UnlockBits(bmd);
            return bmMono;
        }

        public static void SetGrayscalePalette(Bitmap image)
        {
            // check pixel format
            if (image.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                // get palette
                ColorPalette cp = image.Palette;
                // init palette
                for (int i = 0; i < 256; i++)
                {
                    cp.Entries[i] = Color.FromArgb(i, i, i);
                }

                // set palette back
                image.Palette = cp;
            }
            else
            {
                throw new Exception("8 bit grayscaleImage required");
            }
        }

        public static Bitmap CreateGrayscaleImage(int width, int height)
        {
            // create new image
            Bitmap image = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
            // set palette to grayscale
            SetGrayscalePalette(image);
            // return new image
            return image;
        }

        public static bool IsGrayscale(Bitmap bitmap)
        {
            return bitmap.PixelFormat == PixelFormat.Format8bppIndexed ? true : false;
        }
    }

    //http://www.codeproject.com/Tips/240428/Work-with-Bitmaps-Faster-in-Csharp
    public class BitmapLocker
    {
        //private properties
        Bitmap _bitmap = null;
        bool _isLocked = false;
        BitmapData _bitmapData = null;
        private byte[] _imageData = null;
        //public properties
        public IntPtr IntegerPointer
        {
            get;
            private set;
        }

        public int Width
        {
            get
            {
                return _bitmap.Width;
            }
        }

        public int Height
        {
            get
            {
                return _bitmap.Height;
            }
        }

        public int Stride
        {
            get
            {
                return _bitmapData.Stride;
            }
        }

        public int ColorDepth
        {
            get
            {
                return Bitmap.GetPixelFormatSize(_bitmap.PixelFormat);
            }
        }

        public int PaddingOffset
        {
            get
            {
                return _bitmapData.Stride - (_bitmap.Width * ColorDepth / 8);
            }
        }

        public PixelFormat ImagePixelFormat
        {
            get
            {
                return _bitmap.PixelFormat;
            }
        }

        public bool IsGrayscale
        {
            get
            {
                return Grayscale.IsGrayscale(_bitmap);
            }
        }

        //Constructor
        public BitmapLocker(Bitmap source)
        {
            IntegerPointer = IntPtr.Zero;
            this._bitmap = source;
        }

        /// <summary>
        /// Get the color of the specified pixel
        /// </summary>
        /// <param name = "x"></param>
        /// <param name = "y"></param>
        /// <returns></returns>
        public Color GetPixel(int x, int y)
        {
            Color clr = Color.Empty;
            // Get color components count
            int cCount = ColorDepth / 8;
            // Get start index of the specified pixel
            int i = ((y * Width) + x) * cCount;
            //int i = ((x * Width) + y) * cCount;
            if (i > _imageData.Length - cCount)
                throw new IndexOutOfRangeException();
            if (ColorDepth == 32) // For 32 bpp get Red, Green, Blue and Alpha
            {
                byte b = _imageData[i];
                byte g = _imageData[i + 1];
                byte r = _imageData[i + 2];
                byte a = _imageData[i + 3]; // a
                clr = Color.FromArgb(a, r, g, b);
            }

            if (ColorDepth == 24) // For 24 bpp get Red, Green and Blue
            {
                byte b = _imageData[i];
                byte g = _imageData[i + 1];
                byte r = _imageData[i + 2];
                clr = Color.FromArgb(r, g, b);
            }

            if (ColorDepth == 8)
            // For 8 bpp get color value (Red, Green and Blue values are the same)
            {
                byte c = _imageData[i];
                clr = Color.FromArgb(c, c, c);
            }

            return clr;
        }

        /// <summary>
        /// Set the color of the specified pixel
        /// </summary>
        /// <param name = "x"></param>
        /// <param name = "y"></param>
        /// <param name = "color"></param>
        public void SetPixel(int x, int y, Color color)
        {
            // Get color components count
            int cCount = ColorDepth / 8;
            // Get start index of the specified pixel
            int i = ((y * Width) + x) * cCount;
            //int i = ((x * Width) + y) * cCount;
            if (ColorDepth == 32) // For 32 bpp set Red, Green, Blue and Alpha
            {
                _imageData[i] = color.B;
                _imageData[i + 1] = color.G;
                _imageData[i + 2] = color.R;
                _imageData[i + 3] = color.A;
            }

            if (ColorDepth == 24) // For 24 bpp set Red, Green and Blue
            {
                _imageData[i] = color.B;
                _imageData[i + 1] = color.G;
                _imageData[i + 2] = color.R;
            }

            if (ColorDepth == 8)
            {
                // For 8 bpp set color value (Red, Green and Blue values are the same)
                _imageData[i] = color.B;

                string str = string.Empty;
            }
        }

        /// Lock bitmap
        public void Lock()
        {
            if (_isLocked == false)
            {
                try
                {
                    // Lock bitmap (so that no movement of data by .NET framework) and return bitmap data
                    _bitmapData = _bitmap.LockBits(new Rectangle(0, 0, _bitmap.Width, _bitmap.Height), ImageLockMode.ReadWrite, _bitmap.PixelFormat);
                    // Create byte array to copy pixel values
                    int noOfBitsNeededForStorage = _bitmap.Width * _bitmap.Height;
                    _imageData = new byte[noOfBitsNeededForStorage * ColorDepth / 8]; //# of bytes needed for storage
                    IntegerPointer = _bitmapData.Scan0;
                    // Copy data from __IntegerPointer to PixelArray
                    Marshal.Copy(IntegerPointer, _imageData, 0, _imageData.Length);
                    _isLocked = true;
                }
                catch (Exception)
                {
                    throw;
                }
            }
            else
            {
                throw new Exception("Bitmap is already locked.");
            }
        }

        /// Unlock bitmap
        public void Unlock()
        {
            if (_isLocked == true)
            {
                try
                {
                    // Copy data from PixelArray to __IntegerPointer
                    Marshal.Copy(_imageData, 0, IntegerPointer, _imageData.Length);
                    // Unlock bitmap data
                    _bitmap.UnlockBits(_bitmapData);
                    _isLocked = false;
                }
                catch (Exception)
                {
                    throw;
                }
            }
            else
            {
                throw new Exception("Bitmap is not locked.");
            }
        }
    }

    public class BitmapLockerTest
    {
        private static string path = @"locker.png";
        
        public static void Run()
        {
            Bitmap image = Grayscale.ToGrayscale(Bitmap.FromFile(path) as Bitmap);
            Bitmap canvas = Grayscale.CreateGrayscaleImage(1024, 256);
            BitmapLocker imageLocker = new BitmapLocker(image);
            BitmapLocker canvasLocker = new BitmapLocker(canvas);
            imageLocker.Lock();
            canvasLocker.Lock();
            int startX = (Math.Abs(canvas.Width - image.Width) / 2);
            int startY = (Math.Abs(canvas.Height - image.Height) / 2);
            for (int y = startY; y < (startY + image.Height); y++)
            {
                for (int x = startX; x < (startX + image.Width); x++)
                {
                    int xxx = x - startX;
                    int yyy = y - startY;
                    canvasLocker.SetPixel(x, y, imageLocker.GetPixel(xxx, yyy));
                }
            }

            canvasLocker.Unlock();
            imageLocker.Unlock();
            new PictureBoxForm(canvas, image).ShowDialog();
        }
    }
}
;