using System; using System.Collections.Generic; using System.Text; using OSGeo.OGR; using OSGeo.GDAL; using System.Windows.Forms; using System.IO; using System.Drawing; using System.Runtime.InteropServices; using System.Drawing.Imaging; using ESRI.ArcGIS.Geometry; namespace Kingo.Plugin.MakeTaskPackage.Entity { public class GDALOperate { CustomEnvelope MaxEnvelope = null; private Dataset topRasterDs = null; private byte[] geometryStr = null; private string projection = null; private RasterInfo topRasterInfo = null; public void CreateLayer(CustomEnvelope envelope, byte[] jsonGeometry, string pro) { MaxEnvelope = envelope; geometryStr = jsonGeometry; projection = pro; CreateLayer(); } public void CreateLayer() { // 注册所有的驱动 Ogr.RegisterAll(); Gdal.AllRegister(); //消除中文路径无法识别的问题 OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); //解决shape文件字段中文内容读取问题 OSGeo.GDAL.Gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8"); //MessageBox.Show(this.Rasters[0].XSize + "," + this.Rasters[0].YSize); //获取transform CustomEnvelope maxEnvelope = MaxEnvelope; int[] rasterSize = GetRasterSize(maxEnvelope); double[] geoTransform = GetGeoTransform(maxEnvelope, rasterSize[0], rasterSize[1]); //DataSource dataSource = Ogr.Open(@"E:\内业核查软件相关是\核查软件测试数据\通州区监测图斑\110112jctb.shp", 0); //Layer layer = dataSource.GetLayerByIndex(0); Layer layer = CreateTopLayer(geometryStr); topRasterDs = null; string tempFile = Application.StartupPath + "\\temp.img"; if (File.Exists(tempFile)) File.Delete(tempFile); OSGeo.GDAL.Driver dirver = Gdal.GetDriverByName("HFA");//MEM HFA GTiff topRasterDs = dirver.Create(tempFile, rasterSize[0], rasterSize[1], 1, DataType.GDT_Byte, null); //topRasterDs.SetProjection(projection); topRasterDs.SetGeoTransform(geoTransform); Gdal.GDALProgressFuncDelegate callback = new Gdal.GDALProgressFuncDelegate(GDALProgressFuncDelegate); try { int rst = Gdal.RasterizeLayer(topRasterDs, 1, new int[] { 1 }, layer, IntPtr.Zero, IntPtr.Zero, 1, new double[] { 255 }, new string[] { "ALL_TOUCHED=TRUE" }, callback, "callback"); if (topRasterDs != null) topRasterInfo = RasterInfo.Create(topRasterDs); } catch (Exception ex) { MessageBox.Show(ex.Message); } //Feature f = layer.GetFeature(0); //f.GetGeometryRef().Union(); //f.GetGeometryRef().Buffer(100, 30);//100米 30度 //topRasterDs.Dispose(); } private double[] GetGeoTransform(CustomEnvelope envelope, int x, int y) { double[] geoTransform = new double[6]; geoTransform[0] = envelope.XMin; geoTransform[1] = envelope.Width / x; geoTransform[2] = 0; geoTransform[3] = envelope.YMax; geoTransform[4] = 0; geoTransform[5] = -envelope.Height / y; return geoTransform; } private int[] GetRasterSize(CustomEnvelope envelope) { int[] rasterSize = new int[2]; rasterSize[0] = (int)(envelope.Width / 5); rasterSize[1] = (int)(envelope.Height / 5); //for (int i = 1; i < this.Rasters.Count; i++) //{ // if (rasterSize[0] < this.Rasters[i].XSize) // rasterSize[0] = this.Rasters[i].XSize; // if (rasterSize[1] < this.Rasters[i].YSize) // rasterSize[1] = this.Rasters[i].YSize; //} return rasterSize; } public Layer CreateTopLayer(byte[] jsonGeometry) { Layer rstLayer = null; Geometry rstGeometry = OSGeo.OGR.Geometry.CreateFromWkb(jsonGeometry); //new OSGeo.OGR.Geometry(OSGeo.OGR.wkbGeometryType.wkbPolygon); //rstGeometry=rstGeometry.Simplify(0.00000001); OSGeo.OGR.Driver ogrDirver = Ogr.GetDriverByName("Memory"); DataSource dsLayers = ogrDirver.CreateDataSource("", null); rstLayer = dsLayers.CreateLayer("", null, OSGeo.OGR.wkbGeometryType.wkbPolygon, null); Feature f = new Feature(rstLayer.GetLayerDefn()); f.SetGeometry(rstGeometry); rstLayer.CreateFeature(f); return rstLayer; } bool isComplete = false; private int GDALProgressFuncDelegate(double Complete, IntPtr Message, IntPtr Data) { if (Complete >= 1) { isComplete = true; } return 1; } LockBitmap lockBitmap = null; public void UpdateBitMap(Bitmap source, byte[] readByte, int tileSize) { byte[] bgra = new byte[tileSize * tileSize * 4]; BitmapData bitmapData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb); try { Marshal.Copy(bitmapData.Scan0, bgra, 0, bgra.Length); for (int i = 0; i < tileSize; i++) { for (int j = 0; j < tileSize; j++) { byte rVal = readByte[j * tileSize + i]; if (rVal > 0) { continue; } int index = ((j * tileSize) + i) * 4; bgra[index + 3] = 0; } } Marshal.Copy(bgra, 0, bitmapData.Scan0, bgra.Length); } finally { source.UnlockBits(bitmapData); } //source.Save("E:\\" + Guid.NewGuid() + ".png"); } public byte[] ReadTileRgb(TileInfo tile, int tileSize) { CustomEnvelope tileBound = new CustomEnvelope() { XMax = tile.XMax, XMin = tile.XMin, YMax = tile.YMax, YMin = tile.YMin }; CustomEnvelope topEnvelope = tileBound.Intersection(topRasterInfo.Extent); double resolution = tileBound.Width / tileSize; byte[] rgb = null; byte[] rgba = new byte[tileSize * tileSize]; for (int i = 0; i < tileSize * tileSize; i++) { rgba[i] = 0; } if (topEnvelope != null) { Rectangle sTopRect = Envelope2Rect(topRasterInfo, topEnvelope); Rectangle dTopRect = Envelope2Rect(tileBound, topEnvelope, resolution); rgb = new byte[dTopRect.Width * dTopRect.Height]; CPLErr err = topRasterInfo.Dataset.GetRasterBand(1).ReadRaster(sTopRect.X, sTopRect.Y, sTopRect.Width, sTopRect.Height, rgb, dTopRect.Width, dTopRect.Height, 0, 0); if (err != CPLErr.CE_None) { throw new Exception(string.Format("读取Level:{0},Column:{1},Row:{2}的瓦片出错!", tile.Level, tile.Column, tile.Row)); } for (int i = 0; i < dTopRect.Width; i++) { for (int j = 0; j < dTopRect.Height; j++) { try { //int offset = i + j * dRect.Width; //byte rVal = r[offset]; //if (rVal < 5) // continue; //int pixelPos = (dRect.X + i) + (dRect.Y + j) * this.TiledSize; int offset = i + j * dTopRect.Width; byte rVal = rgb[offset]; if (rVal < 250) continue; int pixelPos = (dTopRect.X + i) + (dTopRect.Y + j) * tileSize; rgba[pixelPos] = 255; //source.SetPixel(i, j, tranColor); } catch (Exception ex) { } } } } return rgba; } public Rectangle GetTopRect(TileInfo tile, int tileSize) { CustomEnvelope tileBound = new CustomEnvelope() { XMax = tile.XMax, XMin = tile.XMin, YMax = tile.YMax, YMin = tile.YMin }; CustomEnvelope topEnvelope = tileBound.Intersection(topRasterInfo.Extent); double resolution = tileBound.Width / tileSize; Rectangle sTopRect = Envelope2Rect(topRasterInfo, topEnvelope); Rectangle dTopRect = Envelope2Rect(tileBound, topEnvelope, resolution); return dTopRect; } public Rectangle Envelope2Rect(RasterInfo rasterInfo, CustomEnvelope extent) { //int width = (int)((extent.XMax - extent.XMin) / rasterInfo.TransScale + 0.5); //int height = (int)((extent.YMax - extent.YMin) / rasterInfo.TransScale + 0.5); //int x = (int)((rasterInfo.Extent.XMax - extent.XMax) / rasterInfo.TransScale + 0.5); //int y = (int)((rasterInfo.Extent.YMax - extent.YMax) / rasterInfo.TransScale + 0.5); //return new Rectangle(x, y, width, height); Rectangle rect = Envelope2Rect(rasterInfo.Extent, extent, rasterInfo.TransScale); if (rect.Right > rasterInfo.XSize) { rect.Width -= rect.Right - rasterInfo.XSize; } if (rect.Bottom > rasterInfo.YSize) { rect.Height -= rect.Bottom - rasterInfo.YSize; } return rect; } public Rectangle Envelope2Rect(CustomEnvelope baseExtent, CustomEnvelope extent, double resolution) { int width = (int)((extent.XMax - extent.XMin) / resolution + 0.5); //width = width > baseExtent.Width ? baseExtent.Width : width; int height = (int)((extent.YMax - extent.YMin) / resolution + 0.5); int x = (int)((extent.XMin - baseExtent.XMin) / resolution + 0.5); int y = (int)((baseExtent.YMax - extent.YMax) / resolution + 0.5); return new Rectangle(x, y, width, height); } public void Dispose() { if (this.topRasterDs != null) { this.topRasterDs.Dispose(); this.topRasterDs = null; } if (this.topRasterInfo != null) { this.topRasterInfo.Dispose(); this.topRasterInfo = null; } } } public class CustomEnvelope { public double XMax { get; set; } public double YMax { get; set; } public double XMin { get; set; } public double YMin { get; set; } public double Width { get { return this.XMax - this.XMin; } } public double Height { get { return this.YMax - this.YMin; } } public CustomEnvelope() { } public CustomEnvelope(double x1, double y1, double x2, double y2) { //this.XMin = double.NaN; //this.XMax = double.NaN; //this.YMin = double.NaN; //this.YMax = double.NaN; //this.XMin = Math.Min(x1, x2); //this.YMin = Math.Min(y1, y2); //this.XMax = Math.Max(x1, x2); //this.YMax = Math.Max(y1, y2); this.XMin = double.NaN; this.XMax = double.NaN; this.YMin = double.NaN; this.YMax = double.NaN; this.XMin = Math.Min(x1, x2); this.YMin = Math.Min(y1, y2); this.XMax = Math.Max(x1, x2); this.YMax = Math.Max(y1, y2); } public CustomEnvelope Intersection(CustomEnvelope extent) { if (!this.Intersects(extent)) { return null; } //return new Envelope(Math.Max(this.XMin, extent.XMin), Math.Max(this.YMin, extent.YMin), Math.Min(this.XMax, extent.XMax), Math.Min(this.YMax, extent.YMax)); return new CustomEnvelope(Math.Max(this.XMin, extent.XMin), Math.Max(this.YMin, extent.YMin), Math.Min(this.XMax, extent.XMax), Math.Min(this.YMax, extent.YMax)); } public bool Intersects(CustomEnvelope other) { if (other == null) { return false; } return ((((other.XMin <= this.XMax) && (other.XMax >= this.XMin)) && (other.YMin <= this.YMax)) && (other.YMax >= this.YMin)); //return ((((other.XMin <= this.XMax) && (other.XMax >= this.XMax)) && (other.YMin <= this.YMin)) && (other.YMax >= this.YMax)); } public bool Within(CustomEnvelope other) { return ((((this.XMin >= other.XMin) && (this.XMax <= other.XMax)) && (this.YMin >= other.YMin)) && (this.YMax <= other.YMax)); } public CustomEnvelope Union(CustomEnvelope extent) { CustomEnvelope envelope = new CustomEnvelope(); if (extent == null) { extent = this; } if (double.IsNaN(this.XMin)) { envelope.XMin = extent.XMin; } else if (double.IsNaN(extent.XMin)) { envelope.XMin = this.XMin; } else { envelope.XMin = Math.Min(extent.XMin, this.XMin); } if (double.IsNaN(this.XMax)) { envelope.XMax = extent.XMax; } else if (double.IsNaN(extent.XMax)) { envelope.XMax = this.XMax; } else { envelope.XMax = Math.Max(extent.XMax, this.XMax); } if (double.IsNaN(this.YMin)) { envelope.YMin = extent.YMin; } else if (double.IsNaN(extent.YMin)) { envelope.YMin = this.YMin; } else { envelope.YMin = Math.Min(extent.YMin, this.YMin); } if (double.IsNaN(this.YMax)) { envelope.YMax = extent.YMax; return envelope; } if (double.IsNaN(extent.YMax)) { envelope.YMax = this.YMax; return envelope; } envelope.YMax = Math.Max(extent.YMax, this.YMax); return envelope; } } public class LockBitmap { Bitmap source = null; IntPtr Iptr = IntPtr.Zero; BitmapData bitmapData = null; public byte[] Pixels { get; set; } public int Depth { get; private set; } public int Width { get; private set; } public int Height { get; private set; } public LockBitmap(Bitmap source) { this.source = source; } /// /// Lock bitmap data /// public void LockBits() { try { // Get width and height of bitmap Width = source.Width; Height = source.Height; // get total locked pixels count int PixelCount = Width * Height; // Create rectangle to lock System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, Width, Height); // get source bitmap pixel format size Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat); // Check if bpp (Bits Per Pixel) is 8, 24, or 32 if (Depth != 8 && Depth != 24 && Depth != 32) { throw new ArgumentException("Only 8, 24 and 32 bpp images are supported."); } // Lock bitmap and return bitmap data bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite, source.PixelFormat); // create byte array to copy pixel values int step = Depth / 8; Pixels = new byte[PixelCount * step]; Iptr = bitmapData.Scan0; // Copy data from pointer to array Marshal.Copy(Iptr, Pixels, 0, Pixels.Length); } catch (Exception ex) { throw ex; } } /// /// Unlock bitmap data /// public void UnlockBits() { try { // Copy data from byte array to pointer Marshal.Copy(Pixels, 0, Iptr, Pixels.Length); // Unlock bitmap data source.UnlockBits(bitmapData); } catch (Exception ex) { throw ex; } } /// /// Get the color of the specified pixel /// /// /// /// public Color GetPixel(int x, int y) { Color clr = Color.Empty; // Get color components count int cCount = Depth / 8; // Get start index of the specified pixel int i = ((y * Width) + x) * cCount; if (i > Pixels.Length - cCount) throw new IndexOutOfRangeException(); if (Depth == 32) // For 32 bpp get Red, Green, Blue and Alpha { byte b = Pixels[i]; byte g = Pixels[i + 1]; byte r = Pixels[i + 2]; byte a = Pixels[i + 3]; // a clr = Color.FromArgb(a, r, g, b); } if (Depth == 24) // For 24 bpp get Red, Green and Blue { byte b = Pixels[i]; byte g = Pixels[i + 1]; byte r = Pixels[i + 2]; clr = Color.FromArgb(r, g, b); } if (Depth == 8) // For 8 bpp get color value (Red, Green and Blue values are the same) { byte c = Pixels[i]; clr = Color.FromArgb(c, c, c); } return clr; } /// /// Set the color of the specified pixel /// /// /// /// public void SetPixel(int x, int y, Color color) { // Get color components count int cCount = Depth / 8; // Get start index of the specified pixel int i = ((y * Width) + x) * cCount; if (Depth == 32) // For 32 bpp set Red, Green, Blue and Alpha { Pixels[i] = color.B; Pixels[i + 1] = color.G; Pixels[i + 2] = color.R; Pixels[i + 3] = color.A; } if (Depth == 24) // For 24 bpp set Red, Green and Blue { Pixels[i] = color.B; Pixels[i + 1] = color.G; Pixels[i + 2] = color.R; } if (Depth == 8) // For 8 bpp set color value (Red, Green and Blue values are the same) { Pixels[i] = color.B; } } public bool IsValidCoordinate(int x, int y) { return x >= 0 && x < this.Width && y > 0 && y < this.Height; } } public class RasterInfo : IDisposable { public string Projection { get; private set; } public Dataset Dataset { get; private set; } public int XSize { get; set; } public int YSize { get; set; } public double TransScale { get; set; } //public double ScaleY { get; set; } public CustomEnvelope Extent { get; set; } public double[] Geotransform { get; private set; } public int Bands { get; private set; } private RasterInfo() { } public static RasterInfo Create(string fileName) { //消除中文路径无法识别的问题 OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); Dataset dataset = Gdal.Open(fileName, Access.GA_ReadOnly); return Create(dataset); } public static RasterInfo Create(Dataset dataset) { RasterInfo pRasterInfo = new RasterInfo(); pRasterInfo.Dataset = dataset; pRasterInfo.XSize = pRasterInfo.Dataset.RasterXSize; pRasterInfo.YSize = pRasterInfo.Dataset.RasterYSize; pRasterInfo.Geotransform = new double[6]; pRasterInfo.Dataset.GetGeoTransform(pRasterInfo.Geotransform); double north = pRasterInfo.Geotransform[3]; double south = pRasterInfo.Geotransform[3] + pRasterInfo.Geotransform[5] * pRasterInfo.YSize; double east = pRasterInfo.Geotransform[0] + pRasterInfo.Geotransform[1] * pRasterInfo.XSize; double west = pRasterInfo.Geotransform[0]; if (Math.Round(pRasterInfo.Geotransform[1] + pRasterInfo.Geotransform[5], 1) != 0) throw new Exception("栅格对象被压缩"); pRasterInfo.TransScale = pRasterInfo.Geotransform[1]; pRasterInfo.Bands = pRasterInfo.Dataset.RasterCount; //this.ScaleY = geotransform[5]; pRasterInfo.Projection = pRasterInfo.Dataset.GetProjection(); pRasterInfo.Extent = new CustomEnvelope() { XMax = east, XMin = west, YMax = north, YMin = south }; return pRasterInfo; } public void Dispose() { Dataset.Dispose(); } } }