- 积分
- 13192
- 贡献
-
- 精华
- 在线时间
- 小时
- 注册时间
- 2012-11-15
- 最后登录
- 1970-1-1
|
登录后查看更多精彩内容~
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 luckycomcn 于 2014-12-10 19:32 编辑
之前已经把一个项目迁移到MeteoInfo上。由于项目需要,要读取读取GeoTiff的数据,如果调用GDAL的话是最方便的,但是引入的Dll比较多,于是自己写了一些代码实现这些功能。由于手头上的GeoTiff不多,而全部代码都是自己写的,不排除存在纰漏,而代码目前只针对某些GeoTiff有效(主要是存储的数据的类型的问题)。投影信息是已经可以读取出来的,不过投影转换这块暂时还没做。
其中GeoTiff格式参考了这篇文章tiff和geotiff格式分析。
因此这里的代码只是提供一种思路,想兼容自己的数据的话,还得自己修改一下。
原理说一下,主要是根据文件内部的描述,读取各个标签,从而获取各种值(宽度、高度、经纬度信息等等),不同的标签代码表示的意义后面的附件有。得到这些信息之后就能自己去创建一个GridData对象,从而实现MeteoInfo对GeoTiff的支持。现在还存在的问题就是不同的GeoTiff里面存储的数据到底是什么类型,同样是32位的数据有可能是浮点型也可能是长整型,这个还没处理好。而数据存储的方式本身也有两种,一种是线性的,一种是按块储存,而且这只是我手头上的这两种数据,不知道是不是还有第三种或者第N种。大家也可以把自己的数据贴上来,我有空可以测试支持一下。
废话不多说,上代码。里面带的标注应该足够多了。代码太长了,只放了部分出来,完整版在附件里面。
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.IO;
- namespace yzqx.MeteoInfo
- {
- class yzqxGeoTiff
- {
- #region 公开接口
- public interface IyzTiff
- {
- /// <summary>
- /// 256
- /// </summary>
- uint Width
- {
- get;
- }
- /// <summary>
- /// 257
- /// </summary>
- uint Hight
- {
- get;
- }
- /// <summary>
- /// 258
- /// </summary>
- uint BitPerSample
- {
- get;
- }
- /// <summary>
- /// 259
- /// </summary>
- uint Compression
- {
- get;
- }
- string CompressionDes
- {
- get;
- }
- /// <summary>
- /// 262
- /// </summary>
- uint PhotometricInterpretation
- {
- get;
- }
- string ColorDesc
- {
- get;
- }
- /// <summary>
- /// 273
- /// </summary>
- uint[] StripOffsets
- {
- get;
- }
- /// <summary>
- /// 274
- /// </summary>
- uint Orientation
- {
- get;
- }
- /// <summary>
- /// 277
- /// </summary>
- uint SamplesPerPixel
- {
- get;
- }
- /// <summary>
- /// 278
- /// </summary>
- uint RowsPerStrip
- {
- get;
- }
- /// <summary>
- /// 279
- /// </summary>
- uint[] StripByteCounts
- {
- get;
- }
- /// <summary>
- /// 282
- /// </summary>
- float[] XResolution
- {
- get;
- }
- /// <summary>
- /// 283
- /// </summary>
- float[] YResolution
- {
- get;
- }
- /// <summary>
- /// 284
- /// </summary>
- uint PlanarConfiguration
- {
- get;
- }
- /// <summary>
- /// 296
- /// </summary>
- uint ResolutionUnit
- {
- get;
- }
- /// <summary>
- /// 305
- /// </summary>
- string Software
- {
- get;
- }
- /// <summary>
- /// 322
- /// </summary>
- uint TileWidth
- {
- get;
- }
- /// <summary>
- /// 324
- /// </summary>
- uint TileLength
- {
- get;
- }
- /// <summary>
- /// 324
- /// </summary>
- uint[] TileOffsets
- {
- get;
- }
- /// <summary>
- /// 325
- /// </summary>
- uint[] TileByteCounts
- {
- get;
- }
- /// <summary>
- /// 339
- /// </summary>
- uint SampleFormat
- {
- get;
- }
- /// <summary>
- ///
- /// </summary>
- string PlanarCfgDesc
- {
- get;
- }
- /// <summary>
- /// 33550
- /// </summary>
- double[] ModelPixelScaleTag
- {
- get;
- }
- /// <summary>
- /// 33922
- /// </summary>
- double[] ModelTiepointTag
- {
- get;
- }
- /// <summary>
- /// 34735
- /// </summary>
- UInt16[] GeoKeyDirectoryTag
- {
- get;
- }
- /// <summary>
- /// 34736
- /// </summary>
- double[] GeoDoubleParamsTag
- {
- get;
- }
- /// <summary>
- /// 34737
- /// </summary>
- string GeoAsciiParamsTag
- {
- get;
- }
- object ImageData
- {
- get;
- }
- }
- #endregion
- public class yzTiff : IyzTiff
- {
- #region 私有变量声明
- private object imageData;
- private uint width; //256
- private uint hight; //257
- private uint bitPerSample; //258
- private uint compression; //259
- private uint photometricInterpretation; //262
- private uint[] stripOffsets; //273
- private uint orientation; //274
- private uint samplesPerPixel; //277
- private uint rowsPerStrip; //278
- private uint[] stripByteCounts; //279
- private float[] xResolution; //282
- private float[] yResolution; //283
- private uint planarConfiguration; //284
- private uint sesolutionUnit; //296
- private string software; //305
- private uint tileWidth; //322
- private uint tileLength; //323
- private uint[] tileOffsets; //324
- private uint[] tileByteCounts; //325
- private uint sampleFormat; //339
- double[] modelPixelScaleTag; //33550
- double[] modelTiepointTag; //33922
- UInt16[] geoKeyDirectoryTag; //34735
- double[] geoDoubleParamsTag; //34736
- string geoAsciiParamsTag; //34737
- private string compDesc, colorDesc, planarCfgDesc;
- int useDataOffSet;
- long lastUsePosition;
- #endregion
- /// <summary>
- /// 初始化Tiff文件
- /// </summary>
- /// <param name="fileName">Tiff文件名</param>
- public yzTiff(string fileName)
- {
- width = 0;
- hight = 0;
- if (!File.Exists(fileName))
- {
- throw new Exception("文件不存在!");
- }
- else
- {
- FileStream fs = new FileStream(fileName, FileMode.Open);
- BinaryReader br = new BinaryReader(fs);
- #region 临时使用变量
- string dataType; //数据存储类型,Intel还是Mortorola
- uint fileVer; //文件版本,一般为42
- uint IFD1Offset; //第一个IFD的偏移量
- uint IFD1Num; //第一个IFD的标签数
- uint tagID; //标签代码
- uint tagDataType; //标签数据类型
- uint valueCount; //数据的个数
- uint nextIFDOffSet; //下一个标签偏移量
- #endregion
- #region 文件头信息读取
- //读取数据存储类型
- dataType = br.ReadChar().ToString() + br.ReadChar().ToString();
- if (dataType != "II")
- {
- throw new Exception("目前暂时不支持大端储存的Tiff文件");
- }
- fileVer = br.ReadUInt16(); //读取文件版本
- IFD1Offset = br.ReadUInt32(); //读取第一个IFD偏移量
- br.BaseStream.Position = IFD1Offset; //转到第一个偏移标记
- IFD1Num = br.ReadUInt16(); //读取第一个IFD的标签数
- #endregion
- #region 循环读取第一个域,暂时不支持多个
- //略
- #endregion
- #region 读入图像数据
- if (nextIFDOffSet != 0)
- {
- throw new Exception("暂不支持多个域的GeoTiff文件");
- }
- else if (compression != 1)
- {
- throw new Exception("暂不支持数据经过压缩的GeoTiff文件");
- }
- else
- {
- if (tileOffsets != null)
- {
- if (bitPerSample == 16)
- {
- int[,] useData = new int[hight, width];
- int numtileLength = (int)(hight / tileLength +1);
- int numtileWidth = (int)(width / tileWidth + 1);
- for (int i = 0; i < numtileLength; i++)
- {
- for (int j = 0; j < numtileWidth; j++)
- {
- br.BaseStream.Position = tileOffsets[i * numtileWidth + j];
- for (int k = 0; k < tileLength; k++)
- {
- for (int l = 0; l < tileWidth; l++)
- {
- int onedata = br.ReadInt16();
- if (((i * tileLength + k) >= hight)||(j * tileWidth + l) >= width)
- {
- }
- else
- {
- if (onedata < -999)
- {
- useData[hight - (i * tileLength + k) - 1, j * tileWidth + l] = 9999;
- }
- else
- {
- useData[hight - (i * tileLength + k) - 1, j * tileWidth + l] = onedata;
- }
- }
- }
- }
- }
- }
- imageData = useData;
- }
- else if (bitPerSample == 32)
- {
- float[,] useData = new float[hight, width];
- int numtileLength = (int)(hight / tileLength + 1);
- int numtileWidth = (int)(width / tileWidth + 1);
- for (int i = 0; i < numtileLength; i++)
- {
- for (int j = 0; j < numtileWidth; j++)
- {
- br.BaseStream.Position = tileOffsets[i * numtileWidth + j];
- for (int k = 0; k < tileLength; k++)
- {
- for (int l = 0; l < tileWidth; l++)
- {
- float onedata = br.ReadSingle();
- if (((i * tileLength + k) >= hight) || (j * tileWidth + l) >= width)
- {
- }
- else
- {
- if (onedata < -999)
- {
- useData[hight - (i * tileLength + k) - 1, j * tileWidth + l] = 9999;
- }
- else
- {
- useData[hight - (i * tileLength + k) - 1, j * tileWidth + l] = onedata;
- }
- }
- }
- }
- }
- }
- imageData = useData;
- }
- else
- {
- }
- }
- else if (stripOffsets != null)
- {
- #region 32位浮点型
- if (bitPerSample == 32)
- {
- float[] tempdata = new float[hight * width];
- long imagePointNum = 0;
- //读取数据
- for (int i = 0; i < stripOffsets.Length; i++)
- {
- uint sbc = stripByteCounts * 8 / bitPerSample;
-
br.BaseStream.Position = stripOffsets;
- for (int j = 0; j < sbc; j++)
- {
- tempdata[imagePointNum] = br.ReadSingle();
- imagePointNum++;
- }
- }
- //转化成矩阵
- imagePointNum = 0;
- float[,] useData = new float[hight, width];
- for (int i = 0; i < hight; i++)
- {
- for (int j = 0; j < width; j++)
- {
- useData[hight - i - 1, j] = tempdata[imagePointNum];
- imagePointNum++;
- }
- }
- imageData = useData;
- }
- #endregion
- else if (bitPerSample == 16)
- {
- int[] tempdata = new int[hight * width];
- long imagePointNum = 0;
- //读取数据
- for (int i = 0; i < stripOffsets.Length; i++)
- {
- uint sbc = stripByteCounts * 8 / bitPerSample;
- br.BaseStream.Position = stripOffsets;
- for (int j = 0; j < sbc; j++)
- {
- tempdata[imagePointNum] = br.ReadInt16();
- imagePointNum++;
- }
- }
- //转化成矩阵
- imagePointNum = 0;
- int[,] useData = new int[hight, width];
- for (int i = 0; i < hight; i++)
- {
- for (int j = 0; j < width; j++)
- {
- useData[hight - i - 1, j] = tempdata[imagePointNum];
- imagePointNum++;
- }
- }
- imageData = useData;
- }
- else
- {
- }
- }
- else
- {
- throw new Exception("暂时不支持此类GeoTiff文档");
- }
- }
- #endregion
- br.Close();
- fs.Close();
- }
- }
- #region 标签处理函数
- private void dealOneTag(uint tagID, uint tagDataType, uint valueCount, uint valueOffiset)
- {
- //略
- }
- private void dealOneTag(uint tagID, uint tagDataType, uint valueCount, float valueOffiset)
- {
- //System.Windows.Forms.MessageBox.Show(tagID.ToString() + "尚未处理");
- }
- private void dealOffSetTag(uint tagID, uint tagDataType, uint valueCount, object value)
- {
- //略
- }
- private string CompDes(uint compression)
- {
- string descString = "";
- if (compression == 1)
- {
- descString = "No Compression";
- }
- else if (compression == 2)
- {
- descString = "CCITT Group 31";
- }
- else if (compression == 3)
- {
- descString = " CITT Group 3 Fax T4";
- }
- else if (compression == 4)
- {
- descString = " CITT Group 3 Fax T6";
- }
- else if (compression == 5)
- {
- descString = "LZW";
- }
- else if (compression == 6)
- {
- descString = "JPEG";
- }
- else if (compression == 32773)
- {
- descString = "PackBits";
- }
- else
- {
- }
- return descString;
- }
- private string ColorDes(uint colorID)
- {
- string descString = "";
- if (colorID == 0)
- {
- descString = "对黑白及灰度图像而言, 0 为白色";
- }
- else if (colorID == 1)
- {
- descString = "对黑白及灰度图像而言, 0 为黑色";
- }
- else if (colorID == 2)
- {
- descString = "图像数据以 R,G,B 的方式存储";
- }
- else if (colorID == 3)
- {
- descString = "图像数据采用调色板索引";
- }
- else if (colorID == 4)
- {
- descString = "单色的透明混迭图像";
- }
- else if (colorID == 5)
- {
- descString = "图像数据以 C,M,Y,K 的方式存储";
- }
- else if (colorID == 6)
- {
- descString = " 图像数据以 Y,Cb,Cr 的方式存储";
- }
- else if (colorID == 8)
- {
- descString = " 图像以 L*,a*,b* 的方式存储";
- }
- else
- {
- }
- return descString;
- }
- private string PlanarCfgDes(uint ID)
- {
- string descString = "";
- if (ID == 1)
- {
- descString = "单平面格式";
- }
- else if (ID == 2)
- {
- descString = "多平面格式";
- }
- else
- {
- }
- return descString;
- }
- private int dataTypeLenth(uint num)
- {
- /**************************************
- 1 = BYTE
- 2 = ASCII
- 3 = SHORT
- 4 = LONG
- 5 = RATIONAL
- 6 = SBYTE
- 7 = UNDEFINED
- 8 = SSHORT
- 9 = SLONG
- 10= SRATIONAL
- 11= FLOAT
- 12= DOUBLE
- /**************************************/
- int returnNum = 0;
- if ((num == 1) || (num == 2) || (num == 6))
- {
- returnNum = 1;
- }
- else if ((num == 3) || (num == 8))
- {
- returnNum = 2;
- }
- else if ((num == 4) || (num == 9) || (num == 11))
- {
- returnNum = 4;
- }
- else if ((num == 5) || (num == 12))
- {
- returnNum = 8;
- }
- else
- {
- }
- if (returnNum != 0)
- {
- return returnNum;
- }
- else
- {
- throw new Exception("暂不支持此类标签");
- }
- }
- #endregion
- #region 公共属性
- //略
- #endregion
- }
- }
- }
接下来就是将读取到的信息变成GridData:
- /// <summary>
- /// 返回GeoTiff文件的GridData
- /// </summary>
- /// <param name="inputFileName"></param>
- /// <returns></returns>
- internal static GridData tifGridData(string inputFileName)
- {
- double startX, xCell, startY, endY, yCell;
- int width, height;
- yzqxGeoTiff.yzTiff gTiff = new yzqxGeoTiff.yzTiff(inputFileName);
- xCell = gTiff.ModelPixelScaleTag[0];
- yCell = gTiff.ModelPixelScaleTag[1];
- startX = gTiff.ModelTiepointTag[3];
- endY = gTiff.ModelTiepointTag[4];
- width = (int)gTiff.Width;
- height = (int)gTiff.Hight;
- startY = endY - yCell * height;
- GridData gData = new GridData(startX, xCell, width, startY, yCell, height);
- if(gTiff.BitPerSample ==32)
- {
- float[,] datData;
- datData = new float[height, width];
- datData = (float[,])gTiff.ImageData;
- for (int i = 0; i < height; i++)
- {
- for (int j = 0; j < width; j++)
- {
- gData.Data[i, j] = datData[i, j];
- }
- }
- }
- else if (gTiff.BitPerSample == 16)
- {
- int[,] datData;
- datData = new int[height, width];
- datData = (int[,])gTiff.ImageData;
- for (int i = 0; i < height; i++)
- {
- for (int j = 0; j < width; j++)
- {
- gData.Data[i, j] = datData[i, j];
- }
- }
- }
- return gData;
- }
|
评分
-
查看全部评分
|