根据SegY的标准规范, 使用工作站格式记录的SegY数据要转换为float数值, 作者写了一些合适的方法, 感兴趣的童鞋可以一起讨论下
在400字节的二进制卷头中, 25-26 字节是格式编码
String strDataFormat;
switch (formatIndex)
{
case 1: //4-byte IBM float
strDataFormat = "4-byte IBM float";
break;
case 2: //4-byte integer
strDataFormat = "4 byte integer";
break;
case 3: //2-byte integer
strDataFormat = "2-byte integer";
break;
case 5: //4-byte IEEE float
strDataFormat = "4-byte IEEE float";
break;
case 8: //1-byte integer
strDataFormat = "1-byte integer";
break;
default: //others
strDataFormat = "Unknown Format";
break;
}
其实个人感觉8bit的就已经很够用了, 256个灰度级已经能够很清晰地表现地下反射特征
/** @brief 二进制数据转换为浮点型
*
* @details
* @param bufData 二进制数据
* @param traceData 浮点型道数据
* @param iSamples traceData 的采样点个数
* @param format bufData的数据编码格式
* @return
*/
static void data2float(const uchar* bufData, float* traceData, int iSamples, int format = 1);
/** @brief 从 ibm float 格式的二进制转换到float数组 */
static void ibmFloat2float(const uchar* bufData, float* traceData, int iSamples );
/** @brief 从 ieee float 格式的二进制转换到float数组 */
static void ieeeFloat2float(const uchar* bufData, float* traceData, int iSamples );
/** @brief 从 定长4字节 格式的二进制转换到float数组 */
static void byte4int_2float(const uchar* bufData, float* traceData, int iSamples );
/** @brief 从 定长2字节 格式的二进制转换到float数组 */
static void byte2int_2float(const uchar* bufData, float* traceData, int iSamples );
/** @brief 从 定长1字节 格式的二进制转换到float数组 */
static void byte1int_2float(const uchar* bufData, float* traceData, int iSamples );
/** @brief SegY数据转换静态方法声明
*
* @details SegY数据转换静态方法声明
* @param traceData float类型的道数据
* @param bufData 字节型的SegY数据,要保存进文件
* @param iSamples traceData的采样点数
* @param format bugData的数据格式类型
*/
void float2data(const float* traceData, uchar* bufData, int iSamples, int format /*= 1*/ );
/** @brief 从 ibm float 格式的二进制转换到float数组 */
static void float2ibmFloat(const float* traceData,uchar* bufData, int iSamples );
/** @brief 从 float数组转换到 ieee float 格式的二进制*/
static void float2ieeeFloat(const float* traceData,uchar* bufData, int iSamples );
/** @brief 从float数组 转换到 定长1字节 格式的二进制 */
static void float2_byte1int(const float* traceData, uchar* bufData, int iSamples);
/** @brief 从 float数组转换到 定长2字节 格式的二进制*/
static void float2_byte2int(const float* traceData,uchar* bufData,int iSamples );
/** @brief 从 float数组转换到定长4字节 格式的二进制 */
static void float2_byte4int(const float* traceData, uchar* bufData, int iSamples );
// 4字节int类型的高低位转换
static void swapBytes4(unsigned char*cp);
// 2字节short类型的高低位转换
static void swapBytes2(unsigned char*cp);
源码以最复杂的ibmfloat为例子吧
void SlSegYDataConvert::ibmFloat2float( const uchar* bufData, float* traceData, int iSamples )
{
// d24 = 1.0f/16777216.0f;
int byte1,byte2,byte3,byte4,bsign;
int exp,basep;
for(int i = 0; i < iSamples ; i++)
{
int index = i * 4;
byte1 = bufData[index++];
byte2 = bufData[index++];
byte3 = bufData[index++];
byte4 = bufData[index];
bsign = byte1 & 0x80;
exp = (byte1 & 0x7F) -64;
basep = byte2;
basep = (basep <<8) + byte3;
basep = (basep <<8) + byte4;
if (0 == bsign)
traceData[i] = pow(16.0,exp) * basep * d24;
else
traceData[i] = -1 * pow(16.0,exp) * basep * d24;
/*关于IBM Float 工作站编码, 可以自己查一下. 要从float 转回去,参照编码格式亦可完成, 此处不再缀述*/
}
}
个人感觉这样写的可能高低位转换效率比较好, 请大神斧正, 给不吝回复一下
void SlSegYDataConvert::swapBytes4(unsigned char *cp)
{
cp[0] ^= (cp[3]^=(cp[0]^=cp[3]));
cp[1] ^= (cp[2]^=(cp[1]^=cp[2]));
}
void SlSegYDataConvert::swapBytes2(unsigned char* cp)
{
cp[0] ^= (cp[1]^=(cp[0]^=cp[1]));
}