水平翻转一位位图线

发布于 2024-08-31 03:35:17 字数 259 浏览 3 评论 0原文

我正在寻找一种算法来水平翻转 1 位位图线。请记住这些行是 DWORD 对齐的!

我目前正在将 RLE 流取消编码为每像素 8 位缓冲区,然后重新编码为 1 位行,但是,我想尝试将其全部保留在 1 位空间中,以努力增加其速度。分析表明程序的这一部分与其余部分相比相对较慢。

示例行(翻转前):

FF FF FF FF 77 AE F0 00

示例行(翻转后):

F7 5E EF FF FF FF F0 00

I'm looking for an algorithm to flip a 1 Bit Bitmap line horizontally. Remember these lines are DWORD aligned!

I'm currently unencoding an RLE stream to an 8 bit-per-pixel buffer, then re-encoding to a 1 bit line, however, I would like to try and keep it all in the 1 bit space in an effort to increase its speed. Profiling indicates this portion of the program to be relatively slow compared to the rest.

Example line (Before Flip):

FF FF FF FF 77 AE F0 00

Example line (After Flip):

F7 5E EF FF FF FF F0 00

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风苍溪 2024-09-07 03:35:17

创建一个转换表来交换字节中的位:

byte[] convert = new byte[256];
for (int i = 0; i < 256; i++) {
  int value = 0;
  for (int bit = 1; bit <= 128; bit<<=1) {
    value <<= 1;
    if ((i & bit) != 0) value++;
  }
  convert[i] = (byte)value;
}

现在您可以使用该表来交换字节,然后只需将该字节存储在结果中的正确位置即可:

byte[] data = { 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0xAE, 0xF0, 0x00 };
int width = 52;

int shift = data.Length * 8 - width;
int shiftBytes = data.Length - 1 - shift / 8;
int shiftBits = shift % 8;

byte[] result = new byte[data.Length];
for (int i = 0; i < data.Length; i++) {
  byte swap = convert[data[i]];
  if (shiftBits == 0) {
    result[shiftBYtes - i] = swap;
  } else {
    if (shiftBytes - i >= 0) {
      result[shiftBytes - i] |= (byte)(swap << shiftBits);
    }
    if (shiftBytes - i - 1 >= 0) {
      result[shiftBytes - i - 1] |= (byte)(swap >> (8 - shiftBits));
    }
  }
}

Console.WriteLine(BitConverter.ToString(result));

输出:

F7-5E-EF-FF-FF-FF-F0-00

Create a conversion table to swap the bits in a byte:

byte[] convert = new byte[256];
for (int i = 0; i < 256; i++) {
  int value = 0;
  for (int bit = 1; bit <= 128; bit<<=1) {
    value <<= 1;
    if ((i & bit) != 0) value++;
  }
  convert[i] = (byte)value;
}

Now you can use the table to swap a byte, then you just have to store the byte in the right place in the result:

byte[] data = { 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0xAE, 0xF0, 0x00 };
int width = 52;

int shift = data.Length * 8 - width;
int shiftBytes = data.Length - 1 - shift / 8;
int shiftBits = shift % 8;

byte[] result = new byte[data.Length];
for (int i = 0; i < data.Length; i++) {
  byte swap = convert[data[i]];
  if (shiftBits == 0) {
    result[shiftBYtes - i] = swap;
  } else {
    if (shiftBytes - i >= 0) {
      result[shiftBytes - i] |= (byte)(swap << shiftBits);
    }
    if (shiftBytes - i - 1 >= 0) {
      result[shiftBytes - i - 1] |= (byte)(swap >> (8 - shiftBits));
    }
  }
}

Console.WriteLine(BitConverter.ToString(result));

Output:

F7-5E-EF-FF-FF-FF-F0-00
青衫负雪 2024-09-07 03:35:17

以下代码读取并反转 32 位块中的数据作为整数。用于反转位的代码被分为两部分,因为在小端机器上将四个字节读取为 32 位整数会反转字节顺序。

private static void Main()
{     
    var lineLength = 52;

    var input = new Byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0xAE, 0xF0, 0x00 };
    var output = new Byte[input.Length];

    UInt32 lastValue = 0x00000000;

    var numberBlocks = lineLength / 32 + ((lineLength % 32 == 0) ? 0 : 1);
    var numberBitsInLastBlock = lineLength % 32;

    for (Int32 block = 0; block < numberBlocks; block++)
    {
        var rawValue = BitConverter.ToUInt32(input, 4 * block);

        var reversedValue = (ReverseBitsA(rawValue) << (32 - numberBitsInLastBlock))  | (lastValue >> numberBitsInLastBlock);

        lastValue = rawValue;

        BitConverter.GetBytes(ReverseBitsB(reversedValue)).CopyTo(output, 4 * (numberBlocks - block - 1));
    }

    Console.WriteLine(BitConverter.ToString(input).Replace('-', ' '));
    Console.WriteLine(BitConverter.ToString(output).Replace('-', ' '));
}

private static UInt32 SwapBitGroups(UInt32 value, UInt32 mask, Int32 shift)
{
    return ((value & mask) << shift) | ((value & ~mask) >> shift);
}

private static UInt32 ReverseBitsA(UInt32 value)
{
   value = SwapBitGroups(value, 0x55555555, 1);
   value = SwapBitGroups(value, 0x33333333, 2);
   value = SwapBitGroups(value, 0x0F0F0F0F, 4);

   return value;
}

private static UInt32 ReverseBitsB(UInt32 value)
{
    value = SwapBitGroups(value, 0x00FF00FF, 8);
    value = SwapBitGroups(value, 0x0000FFFF, 16);

    return value;
}

它有点丑陋,而且对错误的鲁棒性不强……但它只是示例代码。它输出以下内容。

FF FF FF FF 77 AE F0 00
F7 5E EF FF FF FF F0 00

The following code reads and reverses the data in blocks of 32 bits as integers. The code to reverse the bits is split into two parts because on a little endian machine reading four bytes as an 32 bit integer reverses the byte order.

private static void Main()
{     
    var lineLength = 52;

    var input = new Byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0xAE, 0xF0, 0x00 };
    var output = new Byte[input.Length];

    UInt32 lastValue = 0x00000000;

    var numberBlocks = lineLength / 32 + ((lineLength % 32 == 0) ? 0 : 1);
    var numberBitsInLastBlock = lineLength % 32;

    for (Int32 block = 0; block < numberBlocks; block++)
    {
        var rawValue = BitConverter.ToUInt32(input, 4 * block);

        var reversedValue = (ReverseBitsA(rawValue) << (32 - numberBitsInLastBlock))  | (lastValue >> numberBitsInLastBlock);

        lastValue = rawValue;

        BitConverter.GetBytes(ReverseBitsB(reversedValue)).CopyTo(output, 4 * (numberBlocks - block - 1));
    }

    Console.WriteLine(BitConverter.ToString(input).Replace('-', ' '));
    Console.WriteLine(BitConverter.ToString(output).Replace('-', ' '));
}

private static UInt32 SwapBitGroups(UInt32 value, UInt32 mask, Int32 shift)
{
    return ((value & mask) << shift) | ((value & ~mask) >> shift);
}

private static UInt32 ReverseBitsA(UInt32 value)
{
   value = SwapBitGroups(value, 0x55555555, 1);
   value = SwapBitGroups(value, 0x33333333, 2);
   value = SwapBitGroups(value, 0x0F0F0F0F, 4);

   return value;
}

private static UInt32 ReverseBitsB(UInt32 value)
{
    value = SwapBitGroups(value, 0x00FF00FF, 8);
    value = SwapBitGroups(value, 0x0000FFFF, 16);

    return value;
}

It is a bit ugly and not robust against errors ... but it is just sample code. And it outputs the following.

FF FF FF FF 77 AE F0 00
F7 5E EF FF FF FF F0 00
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文