using System; using System.Collections.Generic; using System.Text; using ESRI.ArcGIS.Output; using ESRI.ArcGIS.Display; using ESRI.ArcGIS.Geometry; using System.IO; using System.Threading; using System.Drawing.Imaging; using System.Windows.Forms; using System.Drawing; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.esriSystem; using KGIS.Framework.Utils; using Kingo.Plugin.MakeTaskPackage.View; namespace Kingo.Plugin.MakeTaskPackage.Entity { /// /// 获取 /// public class ReadTilesData : IDisposable { public System.Windows.Forms.GroupBox groupBox { get; set; } /// /// 图片类型 /// public ImageFormat ImgFormat { get; set; } /// /// 层级 /// public int Level { get; set; } public IGeometry CustomGeometry { get; set; } private int tileSize = 256; private int blankImageSize = 0; /// /// 瓦片大小 /// public int TileSize { get { return tileSize; } set { tileSize = value; exportRECT = new tagRECT() { top = 0, left = 0, right = value, bottom = value }; pixelBounds = new EnvelopeClass(); pixelBounds.PutCoords(exportRECT.left, exportRECT.top, exportRECT.right, exportRECT.bottom); pExport = new ExportPNGClass() { BackgroundColor = new RgbColorClass() { Red = 10, Green = 10, Blue = 10, Transparency = 123 }, //TransparentColor = new RgbColorClass() { Red =10, Green = 10, Blue = 10, Transparency = 123 }, ImageType = esriExportImageType.esriExportImageTypeTrueColor }; pExport.Resolution = 96; pExport.PixelBounds = pixelBounds; Bitmap image = new Bitmap(Math.Abs(this.TileSize), Math.Abs(this.TileSize), System.Drawing.Imaging.PixelFormat.Format32bppArgb); //, System.Drawing.Imaging.PixelFormat.Format24bppRgb); using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(image)) { // 填充背景色(白色) g.FillRectangle(Brushes.Transparent, 0, 0, this.TileSize, this.TileSize); } using (MemoryStream me = new MemoryStream()) { image.Save(me, System.Drawing.Imaging.ImageFormat.Png); blankImageSize = (int)me.Length; } image.Dispose(); image = null; } } /// /// mxd路径 /// public string MxdPath { get; set; } public string LayerName { get; set; } /// /// 瓦片文件保存路径 /// public string TilesDBPath { get; set; } public ESRI.ArcGIS.Controls.AxMapControl axMap1 { get; set; } public ESRI.ArcGIS.Controls.IMapControl3 axMap { get; set; } /// /// 瓦片大小 /// private tagRECT exportRECT = new tagRECT(); /// /// 导出格式 /// private IExport pExport = new ExportPNGClass() { BackgroundColor = new RgbColorClass() { Red = 10, Green = 10, Blue = 10, Transparency = 123 }, //TransparentColor = new RgbColorClass() { Red =10, Green = 10, Blue = 10, Transparency = 123 }, ImageType = esriExportImageType.esriExportImageTypeTrueColor }; private int hdc; private IEnvelope pixelBounds = new EnvelopeClass(); public List TileInfos { get; set; } public List TilesParams { get; set; } private List doneList = new List(); private IActiveView activeView = null; private string tempDir = Guid.NewGuid().ToString().Replace("-", ""); public WriteTilesToDataBase writeDb = null; Bitmap image = null; System.Drawing.Graphics g = null; /// /// 创建单个瓦片 /// /// int imgIndex = 0; int countCut = 0; private void ExportPNG(IActiveView activeView, string pathFileName, IColor bg, string depth) { IExport export = new ExportPNGClass(); export.ExportFileName = pathFileName; IExportPNG png = export as IExportPNG; png.TransparentColor = bg; IExportImage img = export as IExportImage; if (depth == "8bit") { img.ImageType = esriExportImageType.esriExportImageTypeIndexed; } else if (depth == "32bit") { img.ImageType = esriExportImageType.esriExportImageTypeTrueColor; } // Microsoft Windows default DPI resolution export.Resolution = 96; tagRECT exportRECT = activeView.ExportFrame; ESRI.ArcGIS.Geometry.IEnvelope envelope = new ESRI.ArcGIS.Geometry.EnvelopeClass(); envelope.PutCoords(exportRECT.left, exportRECT.top, exportRECT.right, exportRECT.bottom); export.PixelBounds = envelope; System.Int32 hDC = export.StartExporting(); activeView.Output(hDC, (System.Int16)export.Resolution, ref exportRECT, null, null); // Finish writing the export file and cleanup any intermediate files export.FinishExporting(); export.Cleanup(); } private List CreateKOTiles(TileInfo tileInfo) { byte[] readByte = null; bool isExist = false; //Rectangle dTopRect = new Rectangle(); List lstTileInfos = new List(); //Bitmap bitmap = null; if (gdalOperate != null) { readByte = gdalOperate.ReadTileRgb(tileInfo, this.TileSize); for (int i = 0; i < this.TileSize * this.TileSize; i++) { if (readByte[i] > 250) { isExist = true; break; } } if (!isExist) { for (int i = 0; i < tileInfo.CutMultiple; i++) { for (int j = 0; j < tileInfo.CutMultiple; j++) { lstTileInfos.Add(new TileInfo(tileInfo.Bound, tileInfo.Level, 0, 0)); } } return lstTileInfos; } } #region try { //// 创建图像,为32位色 image = new Bitmap(this.TileSize, this.TileSize, System.Drawing.Imaging.PixelFormat.Format32bppArgb); //, System.Drawing.Imaging.PixelFormat.Format24bppRgb); g = System.Drawing.Graphics.FromImage(image); // 填充背景色(白色) g.FillRectangle(Brushes.Transparent, 0, 0, this.TileSize, this.TileSize); } catch (Exception ex) { LogAPI.Debug(ex + " TileSize:" + this.TileSize); return null; } int dpi = 96; IEnvelope bound = new EnvelopeClass() { XMax = tileInfo.XMax, XMin = tileInfo.XMin, YMax = tileInfo.YMax, YMin = tileInfo.YMin }; activeView.Output(g.GetHdc().ToInt32(), dpi, ref exportRECT, bound, null); g.ReleaseHdc(); if (readByte != null) { gdalOperate.UpdateBitMap(image, readByte, tileSize); //Color tranColor = Color.FromArgb(0, 255, 255, 255); // for (int i = 0; i < tileSize; i++) // { // for (int j = 0; j < tileSize; j++) // { // if (bitmap.GetPixel(i, j).R == 0) // { // image.SetPixel(i, j, tranColor); // } // } // } } TileInfo tileInfoNow = null; int left = 0, top = 0; int oneTileSize = TileSize / tileInfo.CutMultiple; for (int i = 0; i < tileInfo.CutMultiple; i++) { left = i * oneTileSize; for (int j = 0; j < tileInfo.CutMultiple; j++) { top = j * oneTileSize; Bitmap bimap = image.Clone(new Rectangle(left, top, oneTileSize, oneTileSize), System.Drawing.Imaging.PixelFormat.Format32bppArgb); using (MemoryStream me = new MemoryStream()) { bimap.Save(me, System.Drawing.Imaging.ImageFormat.Png); //bimap.Save(@"d:\"+Guid.NewGuid().ToString() + ".png", System.Drawing.Imaging.ImageFormat.Png); //压缩 //using (MagickImage magickImage = new MagickImage(me.ToArray())) //{ // magickImage.Format = MagickFormat.Jpeg; // magickImage.Quality = 60; // var dstbyte = magickImage.ToByteArray(); // tileInfoNow = new TileInfo(tileInfo.Bound, tileInfo.Level, tileInfo.Row * tileInfo.CutMultiple + j, tileInfo.Column * tileInfo.CutMultiple + i); // tileInfoNow.Data = dstbyte;// outme.ToArray();// bytes; //} tileInfoNow = new TileInfo(tileInfo.Bound, tileInfo.Level, tileInfo.Row * tileInfo.CutMultiple + j, tileInfo.Column * tileInfo.CutMultiple + i); tileInfoNow.Data = me.ToArray();// outme.ToArray();// bytes; //if (tileInfoNow.Data.Length > this.blankImageSize) //{ // Console.WriteLine("列:" + tileInfoNow.Column.ToString() + "行:" + tileInfoNow.Row.ToString() + "层:" + tileInfoNow.Level + " " + tileInfoNow.Data.Length); //} //ISupportedImageFormat format = new PngFormat();// { Quality = 90 }; //using (MemoryStream inStream = new MemoryStream(me.ToArray())) //{ // // 使用重载初始化ImageFactory以保留EXIF元数据。 // using (ImageFactory imageFactory = new ImageFactory(true)) // { // imageFactory.Load(inStream).Format(format).Quality(90).Save(outme); // } //} } bimap.Dispose(); if (tileInfoNow != null) lstTileInfos.Add(tileInfoNow); } } if (image != null) image.Dispose(); #endregion //hdc = pExport.StartExporting(); //axMap.ActiveView.Output(hdc, (int)pExport.Resolution, ref exportRECT, tileInfo.Bound, null); //activeView.Output(hdc, (int)pExport.Resolution, ref exportRECT, bound, null); //pExport.FinishExporting(); //pExport.Cleanup(); //byte[] bytes = File.ReadAllBytes(pExport.ExportFileName); countCut += lstTileInfos.Count; return lstTileInfos; //File.Delete(pExport.ExportFileName); } public static bool CompressImage(string sFile, string dFile, int flag = 90, int size = 300, bool sfsc = true) { //如果是第一次调用,原始图像的大小小于要压缩的大小,则直接复制文件,并且返回true FileInfo firstFileInfo = new FileInfo(sFile); if (sfsc == true && firstFileInfo.Length < size * 1024) { firstFileInfo.CopyTo(dFile); return true; } Image iSource = Image.FromFile(sFile); ImageFormat tFormat = iSource.RawFormat; int dHeight = iSource.Height / 2; int dWidth = iSource.Width / 2; int sW = 0, sH = 0; //按比例缩放 Size tem_size = new Size(iSource.Width, iSource.Height); if (tem_size.Width > dHeight || tem_size.Width > dWidth) { if ((tem_size.Width * dHeight) > (tem_size.Width * dWidth)) { sW = dWidth; sH = (dWidth * tem_size.Height) / tem_size.Width; } else { sH = dHeight; sW = (tem_size.Width * dHeight) / tem_size.Height; } } else { sW = tem_size.Width; sH = tem_size.Height; } Bitmap ob = new Bitmap(dWidth, dHeight); Graphics g = Graphics.FromImage(ob); g.Clear(Color.WhiteSmoke); g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.DrawImage(iSource, new Rectangle((dWidth - sW) / 2, (dHeight - sH) / 2, sW, sH), 0, 0, iSource.Width, iSource.Height, GraphicsUnit.Pixel); g.Dispose(); //以下代码为保存图片时,设置压缩质量 EncoderParameters ep = new EncoderParameters(); long[] qy = new long[1]; qy[0] = flag;//设置压缩的比例1-100 EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy); ep.Param[0] = eParam; try { ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders(); ImageCodecInfo jpegICIinfo = null; for (int x = 0; x < arrayICI.Length; x++) { if (arrayICI[x].FormatDescription.Equals("JPEG")) { jpegICIinfo = arrayICI[x]; break; } } if (jpegICIinfo != null) { ob.Save(dFile, jpegICIinfo, ep);//dFile是压缩后的新路径 FileInfo fi = new FileInfo(dFile); if (fi.Length > 1024 * size) { flag = flag - 10; CompressImage(sFile, dFile, flag, size, false); } } else { ob.Save(dFile, tFormat); } return true; } catch { return false; } finally { iSource.Dispose(); ob.Dispose(); } } public void DoworkNoThread() { if (ImgFormat == ImageFormat.Jpeg) { pExport = new ExportJPEGClass(); } ReadTiles(); } GDALOperate gdalOperate = null; private void ReadTiles() { IMapDocument pMapDocument = null; try { if (!File.Exists(MxdPath)) return; //FrmMapVis frm = new FrmMapVis(); //(CustomGeometry as IXMLSerialize).Serialize //frm.LoadMxd(MxdPath, null); //activeView = frm.Map; //frm.Show(); pMapDocument = new MapDocumentClass(); pMapDocument.Open(MxdPath); ProcessMXDClass proMxd = new ProcessMXDClass(); if (System.IO.Path.GetExtension(MxdPath).ToUpper() != ".MXD")//mxd图层全部切片 不设置隐藏属性 proMxd.SetMapLayerVisble(pMapDocument.get_Map(0), LayerName); if (CustomGeometry != null) { PolygonClass polygon = new PolygonClass(); byte[] xml = xmlSerializer(CustomGeometry); XmlDeSerializer(xml, polygon); //pMapDocument.get_Map(0).ClipGeometry = polygon; gdalOperate = new GDALOperate(); CustomEnvelope customEnvelope = new CustomEnvelope() { XMax = polygon.Envelope.XMax, XMin = polygon.Envelope.XMin, YMax = polygon.Envelope.YMax, YMin = polygon.Envelope.YMin }; double del = (customEnvelope.Width - customEnvelope.Height) / 2; if (del > 0) { customEnvelope.YMax += del; customEnvelope.YMin -= del; } else { customEnvelope.XMax -= del; customEnvelope.XMin += del; } gdalOperate.CreateLayer(customEnvelope, ConvertGeometryToWKB(polygon), Kingo.Mobile.Shape2KOTool.SpatialRefrenceStruct.GetAllData()[2].WKT); } activeView = pMapDocument.ActiveView; //IColor pColor = new RgbColorClass(); //pColor.RGB = 255 * 65536 + 255 * 256 + 255; //ExportPNG(activeView, @"d:\av3.png", pColor, "32bit"); //activeView.Refresh(); //return; } catch (Exception ex) { LogAPI.Debug(ex); } finally { //if (pMapDocument != null) //{ // pMapDocument.Close(); //} } //this.groupBox.Invoke(new MethodInvoker(() => //{ writeDb.BlankImageSize = this.blankImageSize; foreach (TilesParam item in TilesParams) { TileSize = item.TileSize; for (int col = item.StartCol; col < item.EndCol; col++) { for (int row = 0; row < item.RowCount; row++) { double minx = item.OriginX + col * item.Distance * item.CutMultiple; double maxy = item.OriginY - row * item.Distance * item.CutMultiple; IEnvelope e = new EnvelopeClass() { XMin = minx, YMin = maxy - item.Distance * item.CutMultiple, XMax = minx + item.Distance * item.CutMultiple, YMax = maxy }; TileInfo tileInfo = new TileInfo(e, item.Level, row, col, item.CutMultiple); List tileInfos = null; try { tileInfos = CreateKOTiles(tileInfo); } catch (Exception ex) { LogAPI.Debug(ex); } finally { if (tileInfos != null) { doneList.AddRange(tileInfos); } //doneList.Add(tileInfo); if (doneList.Count > 20) { writeDb.InsertDataRange(doneList.ToArray()); doneList.Clear(); } } //tiles.Add(new TileInfo(null, MaxLevel, row, col) { XMax = minx + distanceNow, XMin = minx, YMax = maxy, YMin = maxy - distanceNow }); } } } //foreach (TileInfo item in TileInfos) //{ // try // { // CreateKOTiles(item); // } // catch (Exception ex) // { // Kingo.Mobile.Common.LogAPI.Debug(ex); // } // finally // { // doneList.Add(item); // if (doneList.Count > 20) // { // writeDb.InsertDataRange(doneList.ToArray()); // doneList.Clear(); // } // } //} if (gdalOperate != null) { gdalOperate.Dispose(); gdalOperate = null; string tempFile = Application.StartupPath + "\\temp.img"; if (File.Exists(tempFile)) File.Delete(tempFile); } GC.Collect(); if (doneList.Count > 0) { writeDb.InsertDataRange(doneList.ToArray()); doneList.Clear(); } //})); //this.groupBox.Invoke(new MethodInvoker(() => //{ // if (this.groupBox.Controls != null) // this.groupBox.Controls.Remove(axMap1); //})); } /// /// 序列化(将对象序列化成xml文件) /// /// 序列化文件路径 /// 序列化对象 /// public static byte[] xmlSerializer(object obj) { try { //判断是否支持IPersistStream接口,只有支持该接口的对象才能进行序列化 if (obj is ESRI.ArcGIS.esriSystem.IPersistStream) { ESRI.ArcGIS.esriSystem.IPersistStream pStream = obj as ESRI.ArcGIS.esriSystem.IPersistStream; ESRI.ArcGIS.esriSystem.IXMLStream xmlStream = new ESRI.ArcGIS.esriSystem.XMLStreamClass(); pStream.Save(xmlStream as ESRI.ArcGIS.esriSystem.IStream, 0); return xmlStream.SaveToBytes(); //return true; } //return false; } catch (System.Exception e) { //return false; } return null; } private string GetGeometryJson(IGeometry pPolygon) { IGeometryCollection pGeoetryCollection1 = pPolygon as IGeometryCollection; StringBuilder strb = new StringBuilder();// Geometry.CreateFromWkt POLYGON ((0 0,20 0,10 15,0 0)) if (pGeoetryCollection1.GeometryCount >= 1) { strb.Append("POLYGON ("); double x = 0, y = 0; for (int i = 0; i < pGeoetryCollection1.GeometryCount; i++) { if (pGeoetryCollection1.get_Geometry(i) is IRing) { strb.Append("("); IPointCollection pPoints = pGeoetryCollection1.get_Geometry(i) as IPointCollection; for (int j = 0; j < pPoints.PointCount; j++) { IPoint pPoint = pPoints.get_Point(j); pPoint.QueryCoords(out x, out y); strb.Append(x + " " + y + ","); } strb.Remove(strb.Length - 1, 1); strb.Append("),"); } } strb.Remove(strb.Length - 1, 1); strb.Append(")"); } return strb.ToString(); } /// /// 反序列化(将xml反序列化成指定的对象) /// /// 序列化文件 /// 序列化对象 /// public static void XmlDeSerializer(byte[] xml, ESRI.ArcGIS.esriSystem.IPersistStream pStream) { try { //判断文件是否存在 if (xml != null) { //ESRI.ArcGIS.esriSystem.IPersistStream pStream = obj as ESRI.ArcGIS.esriSystem.IPersistStream; ESRI.ArcGIS.esriSystem.IXMLStream xmlStream = new ESRI.ArcGIS.esriSystem.XMLStreamClass(); xmlStream.LoadFromBytes(xml); pStream.Load(xmlStream as ESRI.ArcGIS.esriSystem.IStream); //return true; } //return false; } catch (Exception ex) { //return false; } } Thread doThread = null; public void Dowork() { if (ImgFormat == ImageFormat.Jpeg) { pExport = new ExportJPEGClass(); } doThread = new Thread(new ThreadStart(ReadTiles)); doThread.SetApartmentState(ApartmentState.STA); doThread.IsBackground = true; doThread.Name = "读取图片线程" + Guid.NewGuid().ToString(); doThread.Priority = ThreadPriority.Highest; doThread.Start(); } public void Stop() { this.Dispose(); } public void Dispose() { if (this.doThread != null) { try { this.doThread.Abort(); } catch { } finally { this.doThread = null; } } } public static byte[] ConvertGeometryToWKB(IGeometry geometry) { IWkb wkb = geometry as IWkb; ITopologicalOperator oper = geometry as ITopologicalOperator; oper.Simplify(); IGeometryFactory3 factory = new GeometryEnvironment() as IGeometryFactory3; byte[] b = factory.CreateWkbVariantFromGeometry(geometry) as byte[]; return b; } #region public void DoworkLevel() { if (ImgFormat == ImageFormat.Jpeg) { pExport = new ExportJPEGClass(); } doThread = new Thread(new ThreadStart(ReadTilesLevel)); doThread.SetApartmentState(ApartmentState.STA); doThread.IsBackground = true; doThread.Name = "读取图片线程" + Guid.NewGuid().ToString(); doThread.Priority = ThreadPriority.Highest; doThread.Start(); } private void ReadTilesLevel() { IMapDocument pMapDocument = null; try { if (!File.Exists(MxdPath)) return; pMapDocument = new MapDocumentClass(); pMapDocument.Open(MxdPath); ProcessMXDClass proMxd = new ProcessMXDClass(); if (System.IO.Path.GetExtension(MxdPath).ToUpper() != ".MXD")//mxd图层全部切片 不设置隐藏属性 proMxd.SetMapLayerVisble(pMapDocument.get_Map(0), LayerName); if (CustomGeometry != null) { PolygonClass polygon = new PolygonClass(); byte[] xml = xmlSerializer(CustomGeometry); XmlDeSerializer(xml, polygon); gdalOperate = new GDALOperate(); CustomEnvelope customEnvelope = new CustomEnvelope() { XMax = polygon.Envelope.XMax, XMin = polygon.Envelope.XMin, YMax = polygon.Envelope.YMax, YMin = polygon.Envelope.YMin }; double del = (customEnvelope.Width - customEnvelope.Height) / 2; if (del > 0) { customEnvelope.YMax += del; customEnvelope.YMin -= del; } else { customEnvelope.XMax -= del; customEnvelope.XMin += del; } gdalOperate.CreateLayer(customEnvelope, ConvertGeometryToWKB(polygon), Kingo.Mobile.Shape2KOTool.SpatialRefrenceStruct.GetAllData()[2].WKT); } activeView = pMapDocument.ActiveView; } catch (Exception ex) { LogAPI.Debug(ex); } finally { } foreach (TileInfo item in TileInfos) { try { //double resolution = WriteTilesToDataBase.GetDistance(item.Bound.YMax,item.Bound.XMax,item.YMin,item.XMax) / TileSize; if (item.Level < 8) continue; double resolution = item.Bound.Width / TileSize; item.Resolution = resolution; CreateKOTilesLevel(item); } catch (Exception ex) { LogAPI.Debug(ex); } finally { if (item != null) { doneList.Add(item); } //doneList.Add(tileInfo); if (doneList.Count > 20) { writeDb.InsertDataRange(doneList.ToArray()); doneList.Clear(); } } } if (gdalOperate != null) { gdalOperate.Dispose(); gdalOperate = null; string tempFile = Application.StartupPath + "\\temp.img"; if (File.Exists(tempFile)) File.Delete(tempFile); } GC.Collect(); if (doneList.Count > 0) { writeDb.InsertDataRange(doneList.ToArray()); doneList.Clear(); } } private void CreateKOTilesLevel(TileInfo tileInfo) { byte[] readByte = null; bool isExist = false; Rectangle dTopRect = new Rectangle(); if (gdalOperate != null) { readByte = gdalOperate.ReadTileRgb(tileInfo, this.TileSize); for (int i = 0; i < this.TileSize * this.TileSize; i++) { if (readByte[i] > 250) { isExist = true; break; } } if (!isExist) { return; } } #region try { //// 创建图像,为24位色 image = new Bitmap(this.TileSize, this.TileSize, System.Drawing.Imaging.PixelFormat.Format32bppArgb); //, System.Drawing.Imaging.PixelFormat.Format24bppRgb); g = System.Drawing.Graphics.FromImage(image); // 填充背景色(白色) g.FillRectangle(Brushes.Transparent, 0, 0, this.TileSize, this.TileSize); } catch (Exception ex) { LogAPI.Debug(ex); return; } int dpi = 96; //IEnvelope bound = new EnvelopeClass() //{ // XMax = tileInfo.XMax, // XMin = tileInfo.XMin, // YMax = tileInfo.YMax, // YMin = tileInfo.YMin //}; activeView.Output(g.GetHdc().ToInt32(), dpi, ref exportRECT, tileInfo.Bound, null); g.ReleaseHdc(); if (readByte != null) { gdalOperate.UpdateBitMap(image, readByte, tileSize); } using (MemoryStream me = new MemoryStream()) { image.Save(me, System.Drawing.Imaging.ImageFormat.Png); byte[] bytes = me.ToArray(); tileInfo.Data = bytes; } if (image != null) image.Dispose(); #endregion } #endregion } }