private void SwapCacheAndClear() { ImageCache temp; temp = _verticalCache; _verticalCache = _backupVerticalCache; _backupVerticalCache = temp; temp.Clear(); temp = _horizontalCache; _horizontalCache = _backupHorizontalCache; _backupHorizontalCache = temp; temp.Clear(); }
public async Task FillRegionAsync(int x, int y, Image <Rgb24> region, CancellationToken cancellationToken) { int layer = _ripper._layers.Length - 1; int tileYIndex = y / _deepZoomTileSize; int tileYOffset = tileYIndex * _deepZoomTileSize; int tileYCount = (y - tileYOffset + region.Height + _deepZoomTileSize - 1) / _deepZoomTileSize; tileYCount = Math.Min(tileYCount, _deepZoomTileRowCount - tileYIndex); int tileXIndex = x / _deepZoomTileSize; int tileXOffset = tileXIndex * _deepZoomTileSize; int tileXCount = (x - tileXOffset + region.Width + _deepZoomTileSize - 1) / _deepZoomTileSize; tileXCount = Math.Min(tileXCount, _deepZoomTileColCount - tileXIndex); ImageCache nextVerticalCache = _backupVerticalCache; ImageCache nextHorizontalCache = _backupHorizontalCache; for (int i = 0; i < tileXCount; i++) { int tileCol = tileXIndex + i; for (int j = 0; j < tileYCount; j++) { int tileRow = tileYIndex + j; int tilePointX = tileXOffset + i * _deepZoomTileSize; int tilePointY = tileYOffset + j * _deepZoomTileSize; int drawPointX = tilePointX - x - _deepZoomTileOverlap; int drawPointY = tilePointY - y - _deepZoomTileOverlap; cancellationToken.ThrowIfCancellationRequested(); Image <Rgb24> tile = null; bool cachedOnce = false; try { // First column if (i == 0) { if (_verticalCache.TryFind(tilePointX, tilePointY, out Image <Rgb24> cachedImage)) { _verticalCache.RemoveEntry(tilePointX, tilePointY); tile = cachedImage; } } // First row if (tile == null && j == 0) { if (_horizontalCache.TryFind(tilePointX, tilePointY, out Image <Rgb24> cachedImage)) { _horizontalCache.RemoveEntry(tilePointX, tilePointY); tile = cachedImage; } } // Not found in the cache if (tile == null) { tile = await _ripper.ReadTileImageAsync(layer, tileCol, tileRow, cancellationToken).ConfigureAwait(false); } // Draw on the canvas region.Mutate(ctx => { ctx.DrawImage(tile, new Point(drawPointX, drawPointY), GraphicsOptions.Default); }); // Last column if (tilePointX + _deepZoomTileSize > x + region.Width) { nextVerticalCache.SetEntry(tilePointX, tilePointY, tile); cachedOnce = true; } // Lat row if (tilePointY + _deepZoomTileSize > y + region.Height) { nextHorizontalCache.SetEntry(tilePointX, tilePointY, cachedOnce ? tile.Clone() : tile); cachedOnce = true; } if (cachedOnce) { tile = null; } } finally { tile?.Dispose(); } } } SwapCacheAndClear(); }