title: C# - reverse image bytes quickly?
body: <p>I'm trying to determine the optimal way to flip an image across the Y axis.  For every pixel, there are 4 bytes, and each set of 4 bytes needs to remain together in order but get shifted.  Here's the best I've come up with so far.</p>
  
  <p>This only takes .1-.2s for a 1280x960 image, but with video such performance is crippling.  Any suggestions?</p>
  
  <p><strong>Initial implementation</strong></p>
  
  <pre><code>        private void ReverseFrameInPlace(int width, int height, int bytesPerPixel, ref byte[] framePixels)
      {
          System.Diagnostics.Stopwatch s = System.Diagnostics.Stopwatch.StartNew();
  
          int stride = width * bytesPerPixel;
          int halfStride = stride / 2;
          int byteJump = bytesPerPixel * 2;
          int length = stride * height;
          byte pix;
  
          for (int i = 0, a = stride, b = stride - bytesPerPixel;
              i &lt; length; i++)
          {
              if (b % bytesPerPixel == 0)
              {
                  b -= byteJump;
              }
              if (i &gt; 0 &amp;&amp; i % halfStride == 0)
              {
                  i = a;
                  a += stride;
                  b = a - bytesPerPixel;
                  if (i &gt;= length)
                  {
                      break;
                  }
              }
  
              pix = framePixels[i];
              framePixels[i] = framePixels[b];
              framePixels[b++] = pix;
          }
  
          s.Stop();
          System.Console.WriteLine("ReverseFrameInPlace: {0}", s.Elapsed);
      }
  </code></pre>
  
  <p><strong>Revision #1</strong></p>
  
  <p>Revised with indexes and Buffer.BlockCopy per SLaks and Alexei.  Also added a Parallel.For since the indexes allow for it.</p>
  
  <pre><code>    int[] pixelIndexF = null;
      int[] pixelIndexB = null;
      private void ReverseFrameInPlace(int width, int height, int bytesPerPixel, byte[] framePixels)
      {
          System.Diagnostics.Stopwatch s = System.Diagnostics.Stopwatch.StartNew();
  
          if (pixelIndexF == null)// || pixelIndex.Length != (width * height))
          {
              int stride = width * bytesPerPixel;
              int length = stride * height;
  
              pixelIndexF = new int[width * height / 2];
              pixelIndexB = new int[width * height / 2];
              for (int i = 0, a = stride, b = stride, index = 0;
                  i &lt; length; i++)
              {
                  b -= bytesPerPixel;
                  if (i &gt; 0 &amp;&amp; i % (width / 2 )== 0)
                  {
                      //i = a;
                      i += width / 2;
                      a += stride;
                      b = a - bytesPerPixel;
                      if (index &gt;= pixelIndexF.Length)
                      {
                          break;
                      }
                  }
                  pixelIndexF[index] = i * bytesPerPixel;
                  pixelIndexB[index++] = b;
              }
          }
  
          Parallel.For(0, pixelIndexF.Length, new Action&lt;int&gt;(delegate(int i)
          {
              byte[] buffer = new byte[bytesPerPixel];
              Buffer.BlockCopy(framePixels, pixelIndexF[i], buffer, 0, bytesPerPixel);
              Buffer.BlockCopy(framePixels, pixelIndexB[i], framePixels, pixelIndexF[i], bytesPerPixel);
              Buffer.BlockCopy(buffer, 0, framePixels, pixelIndexB[i], bytesPerPixel);
          }));
  
          s.Stop();
          System.Console.WriteLine("ReverseFrameInPlace: {0}", s.Elapsed);
      }
  </code></pre>
  
  <p><strong>Revision #2</strong></p>
  
  <pre><code>    private void ReverseFrameInPlace(int width, int height, System.Drawing.Imaging.PixelFormat pixelFormat, byte[] framePixels)
      {
          System.Diagnostics.Stopwatch s = System.Diagnostics.Stopwatch.StartNew();
  
          System.Drawing.Rectangle imageBounds = new System.Drawing.Rectangle(0,0,width, height);
  
          //create destination bitmap, get handle
          System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(width, height, pixelFormat);
          System.Drawing.Imaging.BitmapData bitmapData = bitmap.LockBits(imageBounds, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
          IntPtr ptr = bitmapData.Scan0;
  
          //byte[] to bmap
          System.Runtime.InteropServices.Marshal.Copy(framePixels, 0, ptr, framePixels.Length);
          bitmap.UnlockBits(bitmapData);
  
          //flip
          bitmap.RotateFlip(System.Drawing.RotateFlipType.RotateNoneFlipX);
  
          //get handle for bitmap to byte[]
          bitmapData = bitmap.LockBits(imageBounds, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
          ptr = bitmapData.Scan0;
          System.Runtime.InteropServices.Marshal.Copy(ptr, framePixels, 0, framePixels.Length);
          bitmap.UnlockBits(bitmapData);
  
          s.Stop();
          System.Console.WriteLine("ReverseFrameInPlace: {0}", s.Elapsed);
      }
  </code></pre>