標題說得很清楚了,大概就是這樣。需要注意的是本範例使用指針,所以有些地方會出現 unsafe 的區塊。
廢話不多說,直接貼代碼:
C #:
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
public class GolombEncoder : MonoBehaviour
{
void Start ()
{
// 碼流 : 哥倫布編碼 0~9 的 16進制編碼資料
byte [] strArray = new byte[] { 0xA6, 0x42, 0x98, 0xE2, 0x04, 0x8A };
int bytePosition = 0, bitPosition = 0;
int dataLengthInBits = strArray.Length * 8;
int codeNum = 0;
while ((bytePosition * 8 + bitPosition) < dataLengthInBits)
{
unsafe{
codeNum = get_uev_code_num (strArray, &bytePosition, &bitPosition);
print ("ExpoColumb codeNum = " + codeNum);
}
}
}
// 取得 byte 陣列中,指定的陣列位子,的二進制位子的值
// 已知 (0xFF = 1111 1111),所以 bitPosition 會在 0~7 之間
// 所以 return 值只有 0 或 1,不會有其他數字
unsafe int get_bit_at_position (byte[] buf, int *bytePotion, int *bitPosition)
{
int mask = 0, val = 0;
mask = 1 << (7 - *bitPosition);
val = ((buf [*bytePotion] & mask) != 0) ? 1 : 0;
if (++*bitPosition > 7) {
*bytePotion = *bytePotion + 1;
*bitPosition = 0;
}
return val;
}
// 指數哥倫布編碼
unsafe int get_uev_code_num (byte[] buf, int *bytePotion, int *bitPosition)
{
int val = 0, prefixZeroCount = 0;
int prefix = 0, surfix = 0;
while (true) {
val = get_bit_at_position (buf, bytePotion, bitPosition);
if (val == 0) {
prefixZeroCount++;
} else {
break;
}
}
prefix = (1 << prefixZeroCount) - 1;
for (int i = 0; i < prefixZeroCount; i++) {
val = get_bit_at_position (buf, bytePotion, bitPosition);
surfix += val * (1 << (prefixZeroCount - i - 1));
}
prefix += surfix;
return prefix;
}
}