Pack/Unpack 4个字节转化为整数

Pack/Unpack 4 bytes into Integer

正如标题所说,我一直在尝试使用 BitShifting 在 c# 中将 4 个完整的 0-255 字节打包成 1 个整数。我正在尝试压缩一些数据,目前使用 40 字节的数据。但实际上理论上我只需要 12 个字节,但为此我需要将所有数据压缩为 3 个整数。

目前我的数据是:

        float3 pos; // Position Relative to Object
        float4 color; // RGB is Compressed into X, Y is MatID, Z and W are unused
        float3 normal; // A simple Normal -1 to 1 range

但理论上我可以压缩到:

        int pos; // X, Y, Z, MatID - These are never > 200 nor negative
        int color; // R, G, B, Unused Fourth Byte
        int normal; // X, Y, Z, [0, 255] = [-1, 1] with 128 being 0, Unused Fourth Byte Should be plenty accurate for my needs

所以我的问题是我该怎么做?我对 Bit Shifting 相当陌生,还没有设法完成很多工作。

如果我没理解错的话,你需要在 4 个字节中存储 4 个值(每个字节一个值),然后通过执行位移操作来使用各个值。

你可以这样做:

using System;
                    
public class Program
{
    public static void Main()
    {
        uint pos = 0x4a5b6c7d;
        // x is first byte, y is second byte, z is third byte, matId is fourth byte
        uint x = (pos & 0xff);
        uint y = (pos & 0xff00) >> 8;
        uint z = (pos & 0xff0000) >> 16;
        uint matId = (pos & (0xff << 24)) >> 24;
        Console.WriteLine(x + " " + y + " " + z + " " + matId);
        Console.WriteLine((0x7d) + " " + (0x6c) + " " + (0x5b) + " " + (0x4a));
    }
}

x 将等于 0x4a5b6c7d & 0x000000ff = 0x7d

的结果

y 将等于 0x4a5b6c7d & 0x0000ff00 右移 8 位的结果 = 0x6c

zmatId 相似。

编辑

打包需要使用|运算符:

  • 将第四个值左移 24,比如 a
  • 将第三个值左移 16,比如 b
  • 将第二个值左移 8,比如 c
  • 没有第四个值,比如 d
  • 对所有 4 个进行二进制或运算并将其存储在 int 中:int packed = a | b | c | d
using System;
                    
public class Program
{
    static void Unpack(uint p)
    {
        uint pos = p;
        // x is first byte, y is second byte, z is third byte, matId is fourth byte
        uint x = (pos & 0xff);
        uint y = (pos & 0xff00) >> 8;
        uint z = (pos & 0xff0000) >> 16;
        uint matId = (pos & (0xff << 24)) >> 24;
        Console.WriteLine(x + " " + y + " " + z + " " + matId);
    }
    
    static uint Pack(int x, int y, int z, int matId)
    {
        uint newx = x, newy = y, newz = z, newMaxId = matId;
        uint pos2 = (newMaxId << 24) | (newz << 16) | (newy << 8) | newx;
        Console.WriteLine(pos2);
        return pos2;
    }
    
    public static void Main()
    {
        uint packedInt = Pack(10, 20, 30, 40);
        Unpack(packedInt);
    }
}