【问题标题】:Pack/Unpack 4 bytes into Integer [closed]将 4 个字节打包/解包为整数 [关闭]
【发布时间】:2021-11-08 06:12:22
【问题描述】:

正如标题所说,我一直在尝试使用 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 相当陌生,并且没有设法获得很多工作。

【问题讨论】:

  • 我没有看到任何“位移”代码。问题是什么?
  • “我一直在尝试使用 BitShifting 在 c# 中将 4 个完整的 0-255 字节打包成 1 个整数”-> 尝试发布代码,具体问题是什么 :)
  • 0000 0000 0000 0000 0000 0000 0000 0000 使用此布局向我们展示您希望它如何工作
  • 为什么要将浮点数转换为整数?您可能会丢失精度数据。
  • @kiner_shah 在我的情况下,我不需要非常接近浮点数的精度,我只需要 0-255 的值就可以得到几乎相同的结果。

标签: c# unity3d compression


【解决方案1】:

如果我理解正确,您需要将 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 &amp; 0x000000ff = 0x7d 的结果

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

zmatId 类似。

编辑

打包需要使用|操作符:

  • 将第四个值左移 24,例如 a
  • 将第三个值左移 16,例如 b
  • 将第二个值左移 8,例如 c
  • 没有第四个值,比如d
  • 对所有 4 进行二进制 OR 并将其存储在 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);
    }
}

【讨论】:

  • 把数据打包成pos怎么样?这些数据是动态生成的,所以我需要从 4 个字节创建 Pos。
  • @NuclearWolf,已编辑。请检查。
  • 谢谢!另外,感谢您对它的逐步分解,这对理解它在做什么很有帮助!
  • Unpack(Pack(0, 0, 0, 255)) 返回 int4(0, 0, 0, -1) Unpack(Pack(0, 0, 0, 200)) return int4(0 , 0, 0, -56) 知道这里有什么问题吗?
  • 使用无符号整数修复它!
猜你喜欢
  • 2014-03-03
  • 2014-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-02
  • 1970-01-01
  • 2020-07-17
  • 1970-01-01
相关资源
最近更新 更多