这段时间我一直在研究如何用PIE创建带压缩的栅格数据集,由于我在比赛中使用的原始影像大小普遍都在300M以上,软件加载较慢,因此希望能对原始影像进行压缩,加快加载时间。
首先,该方法的关键是修改DataSource.DatasetFactory.CreateRasterDataset()方法中的一个参数。CreateRasterDataset()方法的参数说明请参考《PIESDK For Donet V5.0二次开发指南》。
由于《PIESDK For Donet V5.0二次开发指南》还没来得及更新,实际开发中CreateRasterDataset()方法最后还存在一个指南中未提及的参数mList,这个参数就是用来决定创建的栅格数据集是否是带压缩的。我们只需要将其设置为 "COMPRESS=PACKBITS"即可完成我们的需求。
经过对比,两幅影像不存在失真现象(左图为原始影像,右图为压缩后的影像)。
压缩后的大小仅为原影像的一半左右。
源代码如下:
1 /// <summary> 2 /// 创建带压缩的栅格数据集事件 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 private void toolStripButton1_Click(object sender, EventArgs e) 7 { 8 string pathA = @"D: onghe.tif"; 9 string[] options = new string[1]; 10 options[0] = "COMPRESS=PACKBITS"; 11 IRasterDataset rDataset = DatasetFactory.OpenRasterDataset(pathA, OpenMode.ReadOnly); 12 int xSize = rDataset.GetRasterXSize(); 13 int ySize = rDataset.GetRasterYSize(); 14 int bandCount = rDataset.GetBandCount(); 15 IRasterBand rasterband = rDataset.GetRasterBand(bandCount - 1); 16 PixelDataType type = rasterband.GetRasterDataType(); 17 18 int[] bandMap = new int[bandCount]; 19 for (int i = 0; i < bandCount; i++) 20 { 21 bandMap[i] = i + 1; 22 } 23 24 double[] geoTransA = rDataset.GetGeoTransform(); 25 26 UInt16[] buf = new UInt16[xSize * ySize * bandCount]; 27 28 bool ok = rDataset.Read(0,0, xSize, ySize, buf, xSize, ySize, type, bandCount, bandMap); 29 30 ISpatialReference spGLL = rDataset.SpatialReference; 31 string stGLL = spGLL.ExportToWkt(); 32 33 string rPathSaveGLL = @"D:CompressedImage.tiff"; 34 IRasterDataset rasterDatasetA = DatasetFactory.CreateRasterDataset(rPathSaveGLL, xSize, ySize, bandCount, type, "GTIFF", options); 35 36 rasterDatasetA.Write(0, 0, xSize, ySize, buf, xSize, ySize, type, bandCount, bandMap); 37 rasterDatasetA.SpatialReference = SpatialReferenceFactory.CreateSpatialReference(stGLL); 38 rasterDatasetA.SetGeoTransform(geoTransA); 39 (rasterDatasetA as IDisposable).Dispose(); 40 41 mapControlMain.AddLayerFromFile(pathA, 0); 42 mapControlMain.AddLayerFromFile(rPathSaveGLL, 1); 43 mapControlMain.PartialRefresh(ViewDrawPhaseType.ViewAll); 44 }