title: cropping an area from BitmapData with C#
body: <p>I have a bitmap <strong>sourceImage.bmp</strong></p>
  
  <p>locking it's bits:</p>
  
  <pre><code>BitmapData dataOriginal = sourceImage.LockBits(new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
  </code></pre>
  
  <p>Do analysis, <strong>get a clone</strong>:</p>
  
  <pre><code>Bitmap originalClone = AForge.Imaging.Image.Clone(dataOriginal);
  </code></pre>
  
  <p>unlocking bits:</p>
  
  <pre><code>sourceImage.UnlockBits(dataOriginal);
  </code></pre>
  
  <p><strong>is it possible to specify which part of "dataOriginal" to copy (x,y,w,h)? or to create new data from the dataOriginal, specifying X and Y coordinates as well as H and W?</strong> </p>
  
  <p>The aim is to copy a small area from this image. This method might be faster than DrawImage, that's why I don't use the latter.</p>
  
  <p><strong>Edit:</strong></p>
  
  <p>So I took <strong>29 Mb</strong> bitmap and did some hardcore testing! Full-size crop (basically a copy) + 100 iterations.</p>
  
  <p><img src="https://i.stack.imgur.com/gTpOZ.png" alt="http://i.minus.com/ibmcUsT1qUGw6f.png"></p>
  
  <p>Code:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Windows.Forms;
  using AForge;
  using AForge.Imaging;
  using System.Diagnostics;
  using System.Drawing.Imaging;
  using System.IO;
  using System.Runtime.InteropServices;
  
  
  namespace testCropClone
  {
      public partial class Form1 : Form
      {
          public Form1()
          {
              InitializeComponent();
          }
  
          private unsafe Bitmap Clone(Bitmap bmp, int startX, int startY, int width, int height)
          {
          Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
          BitmapData rawOriginal = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
  
          int origByteCount = rawOriginal.Stride * rawOriginal.Height;
          byte[] origBytes = new Byte[origByteCount];
          Marshal.Copy(rawOriginal.Scan0, origBytes, 0, origByteCount);
  
          int BPP = 4;        //4 Bpp = 32 bits, 3 = 24, etc.
  
          byte[] croppedBytes = new Byte[width * height * BPP];
  
          //Iterate the selected area of the original image, and the full area of the new image
          for (int i = 0; i &lt; height; i++)
          {
              for (int j = 0; j &lt; width * BPP; j += BPP)
              {
                  int origIndex = (startX * rawOriginal.Stride) + (i * rawOriginal.Stride) + (startY * BPP) + (j);
                  int croppedIndex = (i * width * BPP) + (j);
  
                  //copy data: once for each channel
                  for (int k = 0; k &lt; BPP; k++)
                  {
                      croppedBytes[croppedIndex + k] = origBytes[origIndex + k];
                  }
              }
          }
  
          //copy new data into a bitmap
          Bitmap croppedBitmap = new Bitmap(width, height);
          BitmapData croppedData = croppedBitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
          Marshal.Copy(croppedBytes, 0, croppedData.Scan0, croppedBytes.Length);
  
          bmp.UnlockBits(rawOriginal);
          croppedBitmap.UnlockBits(croppedData);
  
          return croppedBitmap;
          }
  
          private Bitmap cloneBitmap(Bitmap bmp, int startX, int startY, int width, int height)
          {
              Rectangle srcRect = Rectangle.FromLTRB(startX, startY, width, height);
              Bitmap cloneBitmap = bmp.Clone(srcRect, bmp.PixelFormat);
              return cloneBitmap;
          }
  
  
          private Bitmap cloneRectangle(Bitmap bmp, int startX, int startY, int width, int height)
          {
              Rectangle srcRect = Rectangle.FromLTRB(startX, startY, width, height);
              Bitmap dest = new Bitmap(srcRect.Width, srcRect.Height);
              Rectangle destRect = new Rectangle(0, 0, srcRect.Width, srcRect.Height);
              using (Graphics graphics = Graphics.FromImage(dest))
              {
                  graphics.DrawImage(bmp, destRect, srcRect, GraphicsUnit.Pixel);
              }
              return dest;
          }
  
  
          private Bitmap cloneAforge(Bitmap bmp, int startX, int startY, int width, int height)
          {
              BitmapData rawOriginal = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
              Bitmap cloneBitmap = AForge.Imaging.Image.Clone(rawOriginal);
              bmp.UnlockBits(rawOriginal);
              return cloneBitmap;
          }
  
  
  
          private void button1_Click(object sender, EventArgs e)
          {
              Bitmap source = new Bitmap(@"C:\9\01.bmp");
  
              Stopwatch s1 = Stopwatch.StartNew();
              for (int i = 0; i &lt; 100; i++)
              {
                  Bitmap Clone1 = cloneAforge(source, 0, 0, source.Width, source.Height);
                  Clone1.Dispose();
  
              }
  
              /*Bitmap Clone1 = cloneAforge(source, 0, 0, source.Width, source.Height);
              Clone1.Save(@"C:\9\01_aforge.bmp");
              Clone1.Dispose();*/
  
              s1.Stop();
              source.Dispose();
              textBox1.Text = ("" + s1.ElapsedMilliseconds / 100 + " ms");
          }
  
          private void button2_Click(object sender, EventArgs e)
          {
              Bitmap source = new Bitmap(@"C:\9\01.bmp");
  
              Stopwatch s1 = Stopwatch.StartNew();
              for (int i = 0; i &lt; 100; i++)
              {
                  Bitmap Clone1 = cloneBitmap(source, 0, 0, source.Width, source.Height);
                  Clone1.Dispose();
  
              }
  
              /*Bitmap Clone1 = cloneBitmap(source, 0, 0, source.Width, source.Height);
              Clone1.Save(@"C:\9\01_bitmap.bmp");
              Clone1.Dispose();*/
  
              s1.Stop();
  
  
              source.Dispose();
              textBox2.Text = ("" + s1.ElapsedMilliseconds / 100 + " ms");
          }
  
          private void button3_Click(object sender, EventArgs e)
          {
              Bitmap source = new Bitmap(@"C:\9\01.bmp");
  
              Stopwatch s1 = Stopwatch.StartNew();
              for (int i = 0; i &lt; 100; i++)
              {
                  Bitmap Clone1 = Clone(source, 0, 0, source.Width, source.Height);
                  Clone1.Dispose();
  
              }
  
              /*Bitmap Clone1 = Clone(source, 0, 0, source.Width, source.Height);
              Clone1.Save(@"C:\9\01_bits.bmp");
              Clone1.Dispose();*/
  
              s1.Stop();
              source.Dispose();
              textBox3.Text = ("" + s1.ElapsedMilliseconds / 100 + " ms");
          }
  
          private void button4_Click(object sender, EventArgs e)
          {
              Bitmap source = new Bitmap(@"C:\9\01.bmp");
  
              Stopwatch s1 = Stopwatch.StartNew();
              for (int i = 0; i &lt; 100; i++)
              {
                  Bitmap Clone1 = cloneRectangle(source, 0, 0, source.Width, source.Height);
                  Clone1.Dispose();
  
              }
  
  
              /*Bitmap Clone1 = cloneRectangle(source, 0, 0, source.Width, source.Height);
              Clone1.Save(@"C:\9\01_rect.bmp");
              Clone1.Dispose();*/
  
  
              s1.Stop();
              source.Dispose();
              textBox4.Text = ("" + s1.ElapsedMilliseconds / 100 + " ms");
          }
      }
  }
  </code></pre>
  
  <p><strong>Edit2:</strong> (Aforge full-size Crop..) method Nr. 2</p>
  
  <pre><code>        for (int i = 0; i &lt; 100; i++)
          {
              Crop crop = new Crop(new Rectangle(0, 0, source.Width, source.Height));
              var source2 = crop.Apply(source);
              source2.Dispose();
  
          }
  </code></pre>
  
  <p>Average = 62ms (40ms less that 1st Aforge approach)</p>
  
  <p><strong>Results:</strong></p>
  
  <ol>
  <li>BitmapClone (0 ms) ?? (cheating, isn't it?)</li>
  <li>Aforge #2 (65 ms)</li>
  <li>Aforge #1 (105 ms)</li>
  <li>Rectangle (170 ms)</li>
  <li>Lock Bits (803 ms) (waiting for fixes/new test results..)</li>
  </ol>