}//end method /// <summary> /// 画像出力 /// </summary> /// <param name="tileUtil"></param> /// <returns></returns> public ExportResult Export(Extent ext, int level) { var tileUtil = this._tileUtil; var infos = tileUtil.ExtentToTileInfo(level, ext); var size = tileUtil.CalcPxSize(level, ext); this._infos = infos; this._size = size; PixelFormat pxFormat = PixelFormat.Format32bppArgb; ColorPalette palette = null; //一旦最初の画像を取ってピクセルフォーマットを取得 using (WebClient client = new WebClient()) using (var mem = new MemoryStream(client.DownloadData(infos.FirstOrDefault().Url))) using (var tile = Bitmap.FromStream(mem)) { pxFormat = tile.PixelFormat; palette = tile.Palette; }//end io //インデックス系だとGraphicsが動作しないので仕方なし //インデックス系を扱う場合はExportIndexを使用 if (pxFormat == PixelFormat.Indexed || pxFormat == PixelFormat.Format8bppIndexed) { pxFormat = PixelFormat.Format32bppArgb; } var img = new Bitmap(size.Width, size.Height, pxFormat); using (var gra = Graphics.FromImage(img)) { var esriWorldFile = this.exportImage(ext, (tileParam) => { var tile = tileParam.Tile; var x = tileParam.X; var y = tileParam.Y; gra.DrawImageUnscaled(tile, x, y); }); return(new ExportResult(img, esriWorldFile)); } //end graphics } //end method
} //end method /// <summary> /// インデックスカラー画像の出力 /// </summary> /// <param name="ext"></param> /// <param name="level"></param> /// <returns></returns> public ExportResult Export8bppIndexed(Extent ext, int level) { var tileUtil = this._tileUtil; var infos = tileUtil.ExtentToTileInfo(level, ext); var size = tileUtil.CalcPxSize(level, ext); this._infos = infos; this._size = size; PixelFormat pxFormat = PixelFormat.Format8bppIndexed; ColorPalette palette = null; //一旦最初の画像を取ってピクセルフォーマットを取得 using (WebClient client = new WebClient()) using (var mem = new MemoryStream(client.DownloadData(infos.FirstOrDefault().Url))) using (var tile = Bitmap.FromStream(mem)) { pxFormat = tile.PixelFormat; palette = tile.Palette; }//end io //パレットにセットするための色のリストを準備 List <Color> colors = null; if (this.Colors == null) { colors = new List <Color>(palette.Entries); this.Colors = colors; } else { colors = new List <Color>(this.Colors); }//end if //返却画像の用意 var img = new Bitmap(size.Width, size.Height, PixelFormat.Format8bppIndexed); string esriWorldFile = null; try { //ロックする var data = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.WriteOnly, img.PixelFormat); //バイト配列の取得 var bytes = new byte[data.Height * data.Stride]; Marshal.Copy(data.Scan0, bytes, 0, bytes.Length); esriWorldFile = this.exportImage(ext, (tileParams) => { var tile = tileParams.Tile; var x = tileParams.X; var y = tileParams.Y; //全体サイズよりXYがでかい場合戻す if (size.Width < x)//(size.Height < y || size.Width < x) { return; } try { var pal = tile.Palette; Dictionary <int, int> colorMap = new Dictionary <int, int>(); //Debug.WriteLine("---------------------------------------------"); for (int i = 0; i < pal.Entries.Length; i++) { var c = pal.Entries[i]; //Debug.WriteLine($"{i}:RGB:{String.Format("#{0:X2}{1:X2}{2:X2}", c.R, c.G, c.B)}"); var colorIndex = colors.IndexOf(c); //ない場合 if (colorIndex < 0) { colorMap.Add(i, colors.Count); colors.Add(c); } else { colorMap.Add(i, colorIndex); } //end if } //end loop //Debug.WriteLine("---------------------------------------------"); var tw = tile.Width; var th = tile.Height; //はみ出た分を切るよう var tileX = x < 0 ? Math.Abs(x) : 0; var tileY = y < 0 ? Math.Abs(y) : 0; var tileW = size.Width < x + tw ? tw - ((x + tw) - size.Width) : tw; var tileH = size.Height < y + th ?th - ((y + th) - size.Height) : th; //はみ出ているばあいはけずる tileW = tileW - tileX; tileH = tileH - tileY; //ロックする try { //タイルデータの取得 var tileBytes = this.getTileData(tile, colorMap, colors); var tstride = tw; //幅単位で回る //for (int i = 0; i < tiledata.Width; i++) //タイルから転送先画像のインデックスを足すよう var cnt = 0; var setX = x < 0 ? 0 : x; var setY = y < 0 ? 0 : y; for (int i = tileY; i < tileY + tileH; i++) { var start = i * tstride + tileX; //var start = i * tiledata.Height; //var copyBytes = new byte[1 * tiledata.Height]; var copyBytes = new byte[1 * tileW]; var imgStart = (setY + cnt) * data.Stride + setX; cnt++; try { Array.Copy(tileBytes, start, copyBytes, 0, copyBytes.Length); Array.Copy(copyBytes, 0, bytes, imgStart, copyBytes.Length); } catch (Exception ex) { Console.Error.WriteLine(ex.Message); Console.Error.WriteLine(ex.StackTrace); Console.Error.WriteLine($"Start:{start} Length:{copyBytes.Length}"); Console.Error.WriteLine($"image:{imgStart}"); } } ////アンロック //tile.UnlockBits(tiledata); } catch (Exception ex) { Console.Error.WriteLine(ex.Message); Console.Error.WriteLine(ex.StackTrace); Console.Error.WriteLine($"TH:{tileH} TW:{tileW} X:{tileX} Y:{tileY}"); } }catch (Exception ex) { Console.Error.WriteLine(ex.Message); Console.Error.WriteLine(ex.StackTrace); } });//end tile action var newPalette = img.Palette; //色数が多い際は切り捨て var colorCount = colors.Count; if (newPalette.Entries.Length < colors.Count) { Console.WriteLine("color over"); colorCount = newPalette.Entries.Length; } Array.Copy(colors.ToArray(), newPalette.Entries, colorCount); img.Palette = newPalette; //バイト配列の書き込み Marshal.Copy(bytes, 0, data.Scan0, bytes.Length); img.UnlockBits(data); } catch (Exception ex) { Debug.Print(ex.Message); Debug.Print(ex.StackTrace); if (img != null) { img.Dispose(); img = null; } throw; } //end try return(new ExportResult(img, esriWorldFile)); } //end method