C # - reverse byte image fast?

I am trying to determine the best way to flip the image along the Y axis. There are 4 bytes for each pixel, and each set of 4 bytes should remain together in order, but shift. Here is the best I've come up with so far.

For a 1280x960 image, this takes only .1-.2s, but with video, crippling performance is such. Any suggestions?

Initial implementation

        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 < length; i++)
        {
            if (b % bytesPerPixel == 0)
            {
                b -= byteJump;
            }
            if (i > 0 && i % halfStride == 0)
            {
                i = a;
                a += stride;
                b = a - bytesPerPixel;
                if (i >= length)
                {
                    break;
                }
            }

            pix = framePixels[i];
            framePixels[i] = framePixels[b];
            framePixels[b++] = pix;
        }

        s.Stop();
        System.Console.WriteLine("ReverseFrameInPlace: {0}", s.Elapsed);
    }

Edition # 1

Revised with indexes and Buffer.BlockCopy on SLaks and Alexei. Parallel.For is also added as indexes allow this.

    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 < length; i++)
            {
                b -= bytesPerPixel;
                if (i > 0 && i % (width / 2 )== 0)
                {
                    //i = a;
                    i += width / 2;
                    a += stride;
                    b = a - bytesPerPixel;
                    if (index >= pixelIndexF.Length)
                    {
                        break;
                    }
                }
                pixelIndexF[index] = i * bytesPerPixel;
                pixelIndexB[index++] = b;
            }
        }

        Parallel.For(0, pixelIndexF.Length, new Action<int>(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);
    }

Version # 2

    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);
    }
+3
source share
6 answers

, , .avi. Array.Copy(), , , ( , ). , , 720 x 576 3 . 0,001 0,01 0,06 .

    private byte[] ReverseFrameInPlace2(int stride, byte[] framePixels)
    {
        System.Diagnostics.Stopwatch s = System.Diagnostics.Stopwatch.StartNew();
        var reversedFramePixels = new byte[framePixels.Length];
        var lines = framePixels.Length / stride;

        for (var line = 0; line < lines; line++)
        {
            Array.Copy(framePixels, framePixels.Length - ((line + 1) * stride), reversedFramePixels, line * stride, stride);
        }

        s.Stop();
        System.Console.WriteLine("ReverseFrameInPlace2: {0}", s.Elapsed);
        return reversedFramePixels;
    }
+4
+3

CPU . , DirectX GPU.

+2

, :

  • pre-build (, [12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3] ifs, .
  • .
+1

Another option would be to use the XNA infrastructure for image manipulation. There is a small example. How to resize and save Texture2D in XNA? . I have no idea how fast this is, but I could see how it should be pretty fast, given that the functions are supposed to be used in high fps games.

0
source

All Articles