C # /. Net побитовое смещение влево на короткую операцию [] - PullRequest
0 голосов
/ 16 мая 2011

Есть ли метод (в c # /. Net), который бы сдвигал влево (поразрядно) каждое короткое замыкание [], что было бы быстрее, чем делать это в цикле?

Я говорю о данных, поступающих с цифровой камеры (16-битная серая), камера использует только младшие 12 бит. Таким образом, чтобы увидеть что-то при рендеринге данных, его нужно сместить влево на 4.

Это то, что я делаю до сих пор:

byte[] RawData; // from camera along with the other info

if (pf == PixelFormats.Gray16)
{
    fixed (byte* ptr = RawData)
    {
        short* wptr = (short*)ptr;
        short temp;

        for (int line = 0; line < ImageHeight; line++)
        {
            for (int pix = 0; pix < ImageWidth; pix++)
            {
                temp = *(wptr + (pix + line * ImageWidth));
                *(wptr + (pix + line * ImageWidth)) = (short)(temp << 4);
            }
        }
    }
}

Есть идеи?

1 Ответ

2 голосов
/ 16 мая 2011

Я не знаю библиотечного метода, который это сделает, но у меня есть несколько советов, которые могут помочь. Это будет работать, только если вы знаете, что верхние четыре бита пикселя определенно равны нулю (а не мусору). (Если они являются мусором, вам нужно добавить битовые маски ниже). В основном я бы предложил:

  • Использование оператора сдвига для большего типа данных (int или long), так что вы перемещаете больше данных одновременно
  • Избавление от операций умножения внутри вашего цикла
  • Развертывание маленькой петли

Вот мой код:

using System.Diagnostics;

namespace ConsoleApplication9 {
  class Program {
    public static void Main() {
      Crazy();
    }

    private static unsafe void Crazy() {
      short[] RawData={
        0x000, 0x111, 0x222, 0x333, 0x444, 0x555, 0x666, 0x777, 0x888,
        0x999, 0xaaa, 0xbbb, 0xccc, 0xddd, 0xeee, 0xfff, 0x123, 0x456,

        //extra sentinel value which is just here to demonstrate that the algorithm
        //doesn't go too far
        0xbad 
      };

      const int ImageHeight=2;
      const int ImageWidth=9;

      var numShorts=ImageHeight*ImageWidth;

      fixed(short* rawDataAsShortPtr=RawData) {
        var nextLong=(long*)rawDataAsShortPtr;

        //1 chunk of 4 longs
        // ==8 ints
        // ==16 shorts
        while(numShorts>=16) {
          *nextLong=*nextLong<<4;
          nextLong++;
          *nextLong=*nextLong<<4;
          nextLong++;
          *nextLong=*nextLong<<4;
          nextLong++;
          *nextLong=*nextLong<<4;
          nextLong++;

          numShorts-=16;
        }

        var nextShort=(short*)nextLong;
        while(numShorts>0) {
          *nextShort=(short)(*nextShort<<4);
          nextShort++;
          numShorts--;
        }
      }

      foreach(var item in RawData) {
        Debug.Print("{0:X4}", item);
      }
    }
  }
}
...