根据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])); }