public async virtual Task <MemoryImage> LoadThumbnailImageAsync(HttpClient http, CancellationToken cancellationToken) { MemoryImage?image = null; try { using var response = await http.GetAsync(this.ThumbnailImageUrl, cancellationToken) .ConfigureAwait(false); response.EnsureSuccessStatusCode(); using var imageStream = await response.Content.ReadAsStreamAsync() .ConfigureAwait(false); image = await MemoryImage.CopyFromStreamAsync(imageStream) .ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); return(image); } catch (OperationCanceledException) { image?.Dispose(); throw; } }
/// <summary> /// Release all resources used by this <see cref="DoubleBufferedGraphics"/>. /// </summary> public void Dispose() { if (MemoryImage != null) { MemoryImage.Dispose(); MemoryImage = null; } if (Graphics != null) { Graphics.Dispose(); Graphics = null; } }
/// <summary>指定されたタイル番号のタイル画像を読み込むメソッド</summary> private async Task <MemoryImage> LoadTileImageAsync(HttpClient http, Point pos) { var tileUrl = TileServerBase + $"/{this.Zoom}/{pos.X}/{pos.Y}.png"; using (var stream = await http.GetStreamAsync(tileUrl).ConfigureAwait(false)) { MemoryImage result = null; try { result = await MemoryImage.CopyFromStreamAsync(stream).ConfigureAwait(false); return(result); } catch { result?.Dispose(); throw; } } }
/// <summary> /// Reset this <see cref="DoubleBufferedGraphics"/>. /// </summary> public void Reset() { if (MemoryImage != null) { MemoryImage.Dispose(); MemoryImage = null; } if (Graphics != null) { Graphics.Dispose(); Graphics = null; } MemoryImage = new Bitmap(Size.Width, Size.Height); Graphics = Graphics.FromImage(MemoryImage); }
/// <summary> /// This method is the preferred method of drawing a background image. /// It is *MUCH* faster than any of the Graphics.DrawImage() methods. /// Warning: The memory image and the <see cref="System.Drawing.Graphics"/> object /// will be reset after calling this method. This should be your first /// drawing operation. /// </summary> /// <param name="image">The image to draw.</param> public void SetBackgroundImage(Image image) { if (MemoryImage != null) { MemoryImage.Dispose(); MemoryImage = null; } if (Graphics != null) { Graphics.Dispose(); Graphics = null; } MemoryImage = image.Clone() as Image; if (MemoryImage != null) { Graphics = Graphics.FromImage(MemoryImage); } }
public override async Task <MemoryImage> LoadThumbnailImageAsync(HttpClient http, CancellationToken cancellationToken) { // 画像中央に描画されるタイル (ピクセル単位ではなくタイル番号を表す) // タイル番号に小数部が含まれているが、これはタイル内の相対的な位置を表すためこのまま保持する var centerTileNum = this.WorldToTilePos(this.Longitude, this.Latitude, this.Zoom); // 画像左上に描画されるタイル var topLeftTileNum = PointF.Add(centerTileNum, new SizeF(-this.ThumbnailSize.Width / 2.0f / TileSize.Width, -this.ThumbnailSize.Height / 2.0f / TileSize.Height)); // タイル番号の小数部をもとに、タイル画像を描画する際のピクセル単位のオフセットを算出する var tileOffset = Size.Round(new SizeF(-TileSize.Width * (topLeftTileNum.X - (int)topLeftTileNum.X), -TileSize.Height * (topLeftTileNum.Y - (int)topLeftTileNum.Y))); // 縦横のタイル枚数 var tileCountX = (int)Math.Ceiling((double)(this.ThumbnailSize.Width + Math.Abs(tileOffset.Width)) / TileSize.Width); var tileCountY = (int)Math.Ceiling((double)(this.ThumbnailSize.Height + Math.Abs(tileOffset.Height)) / TileSize.Height); // 読み込む対象となるタイル画像が 10 枚を越えていたら中断 // ex. 一辺が 512px 以内のサムネイル画像を生成する場合、必要なタイル画像は最大で 9 枚 if (tileCountX * tileCountY > 10) { throw new OperationCanceledException(); } // タイル画像を読み込む var tilesTask = new Task <MemoryImage> [tileCountX, tileCountY]; foreach (var x in Enumerable.Range(0, tileCountX)) { foreach (var y in Enumerable.Range(0, tileCountY)) { var tilePos = Point.Add(Point.Truncate(topLeftTileNum), new Size(x, y)); tilesTask[x, y] = this.LoadTileImageAsync(http, tilePos); } } await Task.WhenAll(tilesTask.Cast <Task <MemoryImage> >()) .ConfigureAwait(false); using (var bitmap = new Bitmap(this.ThumbnailSize.Width, this.ThumbnailSize.Height)) { using (var g = Graphics.FromImage(bitmap)) { g.TranslateTransform(tileOffset.Width, tileOffset.Height); foreach (var x in Enumerable.Range(0, tileCountX)) { foreach (var y in Enumerable.Range(0, tileCountY)) { using (var image = tilesTask[x, y].Result) { g.DrawImage(image.Image, TileSize.Width * x, TileSize.Height * y); } } } } MemoryImage result = null; try { result = MemoryImage.CopyFromImage(bitmap); return(result); } catch { result?.Dispose(); throw; } } }