
前文已经提到的信息内容是经过压缩的,压缩的方法比较特殊,因
AIS
为要求压缩的结果是可见字符。本文针对压缩以及解压缩进行描述。
对于VDM消息中的压缩码,编码格式是根据以下对照表来进行的。
制定这种编码格式的目的一是为了压缩信息内容,二是要求压缩以后的
信息能够以ASCII码显示,以便使用文本方式传输(如果直接压缩,可
能会产生不可见字符,这就是一般压缩文件以二进制方式存储的原因)。
ASCIIValid Binary ASCIIValid Binary
HEX = binaryCharacterField HEX = binaryCharacterField
30=00110000000000050=01010000P100000
31=00110001100000151=01010001Q100001
32=00110010200001052=01010010R100010
33=00110011300001153=01010011S100011
34=00110100400010054=01010100T100100
35=00110101500010155=01010101U100101
36=00110110600011056=01010110V100110
37=00110111700011157=01010111W100111
38=00111000800100060=01100000‘101000
39=00111001900100161=01100001a101001
48=01001000H01100070=01110000p111000
49=01001001I01100171=01110001q111001
4A=01001010J01101072=01110010r111010
4B=01001011K01101173=01110011s111011
4C=01001100L01110074=01110100t111100
4D=01001101M01110175=01110101u111101
4E=01001110N01111076=01110110v111110
4F=01001111O01111177=01110111w111111
目前我们只需要考虑使用以上编码格式进行流
解码就可以了。以下是解码
程。
1.Convert ASCII-code to 6-bit binary field(将ASCII码转换成
6位二进制值)
算法图例:
第一个判断是因为经过编码的文本字符只可能为0x30到0x77间的可显示字
符。
第二个判断与第三个判断是由于在编码表中,我们可以看到,0x57以后并不
是0x58,而是0x60,所以在0x58到0x5F间的字符是无效字符。
以上三个判断是对需要解码的字符有效性的判断。
其下的流程是真正的解码流程。至于为什么用这样的流程,大家可以推敲,
目前我们只需安照该流程执行,即可将VDM消息中的压缩信息转为6比特的信息
了。
解码
算法代码:
//转换单个字符
bool EightByteToSix(BYTE inEight,BYTE &outSix)
{
//以下两个判断用于检测所输入的ASCII码是否有效
if(inEight < 0x30 || inEight > 0x77)
return fal;
if(inEight > 0x57 && inEight < 0x60)
return fal;
//检查结束
outSix = inEight + 0x28; //加上101000
if(outSix > 0x80) //如果SUM>10000000
outSix += 0x20; //加上100000
el
outSix += 0x28; //加上101000
outSix = outSix<<2; //右移两位,获取LSB
return true ;
}
//转换整个压缩信息
2. Convert ASCII-code String to 6-bit binary field Array(将ASCII码
字符串转换成6位二进制值表示的字符数组)
说明:将每个ASCII码转换成6bits码后,因为数据是以字节为单位保存的,因
此需要将这些6bits码放置到字节中去。比如ASCII码串”A2L9”,转换成6bits
二进制是这样的:010001 000010 011100 001001。用字节表示就是 01000100
00100111 00001001即0x44,0x27,0x09这三个ASCII码。
算法代码:
//返回参数用LPBYTE而不用CString,是因为转换的中可能出现0x00。这
数据
在字符串中会作为串结束符看待,因此将无法得到串的真实长度
bool EightStrToSix(CString inEight, LPBYTE outSix)
{
BYTE len = gth();
BYTE nowBt = 0x00;//用于记录当前未用完的记录6Bits码的字节
BYTE midBt;//中间转换记录字节
BYTE outLen = 0;
for(int i=0;i { BYTE bt = (i); BYTE six; If(EightByteToSix(bt,six)==fal)//将当前ASCII码转换成 6 bits码 return fal; int res = i%4;//因为4个ASCII码转换成3个字节的6bits 码,因此将是每4个ASCII码的转换成为一个循环过程 switch(res) { //当是第一个ASCII码时,不能直接完成一个6bits码的字节转换,因为还 有两个bits没有填入的字节 数据。用nowBt暂先保存6bits码正在记录数据 ca 0: nowBt = six; break; //当处理第二个ASCII码时,显然,加上第一个ASCII码的转换,2个6bits 码将是12bits,因此可以完成一个字节的,另外余下的4bits记录到nowBt 数据 中,等待下一个ASCII码的处理。 ca 1: midBt = six >>6; //将最高的两位移到末尾,以便将高 二位保存到nowBt的低二位中 nowBt = nowBt | midBt;//完成6bits码的第一个字节 outSix[outLen] = nowBt;//保存到输出的字节数组中 outLen ++; //以下两步移位是将当前6bits码的中间4位移动到高 四位中。并记录到nowBt中。 nowBt = six >>2; nowBt = nowBt <<4; break; //当处理第三个ASCII码时,nowBt中的有效位是高四位,因此需要将新的 6bits码的高四位放到nowBt的低四位中,然后保存nowBt到输出数组,再将新 的6bits码的第5,6位移到高二位后记录到nowBt中 ca 2: midBt = six >>4;//将高四位移到低四位 nowBt = nowBt | midBt;//完成6bits码的第二个字节 outSix[outLen] = nowBt;//保存到输出的字节数组 outLen ++; //将新的6bits码的第5,6位移到高二位后记录到nowBt中 nowBt = six >>2; nowBt = nowBt <<6; break; //当处理第四个ASCII码时,nowBt中的有效位是高二位,因此 将新的6bits码的高6位移到nowBt的低6位,正好完成一个循环 ca 3: midBt = six >>2;//将高六位移到低六位 nowBt = nowBt | midBt;//完成6bits码的第三个字节 outSix[outLen] = nowBt;//保存到输出的字节数组 outLen ++; nowBt = 0x00;//nowBt复位 break; } default: { break; } } return true; } 信息获取代码 压缩信息解码完成后,就可以从解码信息中读取指定的内容了。 根据读取的信息的比特长度不同,读取的方法也有所变化。 3.从解码数据中获取指定类型的数据内容 3.1获取1bits 到 8bits的整数 数据 //lpInfo—调用EightStrToSix获取的 解码数据 //dwBitStart –需要获取的的起始位. dwBitStart 从0开始 数据 //byLen –所占位数 数据 BYTE GetByteValFromInfo(const LPBYTE lpInfo,DWORD dwBitStart,BYTE byLen) { BYTE byStartByte = dwBitStart/8;//获取起始字节序号 BYTE byStartBit = dwBitStart%8;//获取起始字节中的起始位数 BYTE byInfo = 0x00; if(8-byStartBit < byLen)//要获取的跨两个字节 数据 { BYTE by1 = *(lpInfo + byStartByte);//获取第一个字节 数据 BYTE by2 = *(lpInfo + byStartByte + 1);//获取第二个字节 数据 //完成两个字节中位的拼接 by1 = by1 << byStartBit; by1 = by1 << 8 - byLen; //byLen - (8 - byStartBit) by2 = by2 >> 16 - byLen - byStartBit; //8 - (byLen - (8 - byStartBit)) byInfo = by1 | by2; } el { byInfo = *(lpInfo + byStartByte); byInfo = byInfo << byStartBit; byInfo = byInfo >> 8 - byLen; } return byInfo; } 3.2获取9bits 到 16bits的整数 数据 WORD GetWordValFromInfo(const LPBYTE lpInfo,DWORD dwBitStart,WORD wLen) { BYTE byStartByte = dwBitStart/8; BYTE byStartBit = dwBitStart%8; WORD wInfo = 0x0000; if(16 - byStartBit < wLen)//要获取的跨三个字节 数据 { wInfo = *(WORD*)(lpInfo + byStartByte); wInfo = wInfo << byStartBit; wInfo = wInfo >> 16 - wLen; BYTE by1 = *(lpInfo + byStartByte + 2); by1 = by1 >> 24- wLen - byStartBit; wInfo = wInfo | by1; } el { wInfo = *(WORD*)(lpInfo + byStartByte); wInfo = ntohs(wInfo); wInfo = wInfo << byStartBit; wInfo = wInfo >> 16 - wLen; } return wInfo; } 3.3获取17bits 到 32bits的整数数据 DWORD GetDWordValFromInfo(const LPBYTE lpInfo,DWORD dwBitStart,DWORD dwLen) { BYTE byStartByte = dwBitStart/8; BYTE byStartBit = dwBitStart%8; DWORD dwInfo = 0x00000000; if(dwLen <= 24)//占三个或者四个字节 { if(24 - byStartBit < dwLen)//占四字节 { dwInfo = *(DWORD*)(lpInfo + byStartByte); dwInfo = ntohl(dwInfo); dwInfo = dwInfo << byStartBit; dwInfo = dwInfo >> 32 - dwLen; BYTE by1 = *(lpInfo + byStartByte + 4); by1 = by1 >> 40 - dwLen - byStartBit; dwInfo = dwInfo | by1; } el//占四个字节 { byStartBit += 6; if(byStartBit == 8) { byStartBit = 0; byStartByte ++; } } //字符串解码,如果小于0x20,需要加上0x40 //具体规则参考ITU-R M-1371-1文件第41,42页 if(byChar < 0x20) byChar += 0x40; sRtnStr += byChar;

本文发布于:2023-11-25 08:16:06,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/zhishi/a/170087136634748.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:AIS解码算法.doc
本文 PDF 下载地址:AIS解码算法.pdf
| 留言与评论(共有 0 条评论) |