/// <summary> /// Returns image from visible tiles with scale factor > 1 /// </summary> /// <param name="tiles"></param> /// <param name="leftTopPointOfView"></param> /// <param name="screenSize"></param> /// <returns></returns> private IEnumerable<TileRawWrapper> ScaleUp(Tile[] tiles, Point leftTopPointOfView, Size screenSize) { int scaledScreenX = (int)Math.Ceiling(screenSize.Width / Scaler.ScaleFactor); int scaledScreenY = (int)Math.Ceiling(screenSize.Height / Scaler.ScaleFactor); var visibleTiles = tiles.Where(x => x.CheckVisibility(leftTopPointOfView, scaledScreenX, scaledScreenY)).ToArray(); BlockingCollection<TileRawWrapper> tileImgWrappers = new BlockingCollection<TileRawWrapper>(); Size cropS = new Size(); Tile leftTopTile = default(Tile); foreach(var tile in visibleTiles) { //stores relative offset by X for visible part from the beginning of the current tile int shiftTileX = (int)(leftTopPointOfView.X - tile.LeftTopCoord.X); shiftTileX = shiftTileX < 0 ? 0 : shiftTileX; //stores relative offset by Y for visible part from the beginning of the current tile int shiftTileY = (int)(leftTopPointOfView.Y - tile.LeftTopCoord.Y); shiftTileY = shiftTileY < 0 ? 0 : shiftTileY; //if not all scaled tile is visible we only take the visible part. int croppedWidth = tile.Size.Width - shiftTileX >= scaledScreenX ? scaledScreenX : tile.Size.Width - shiftTileX; int croppedHeight = tile.Size.Height - shiftTileY >= scaledScreenY ? scaledScreenY : tile.Size.Height - shiftTileY; var resizedW = (int)(croppedWidth * Scaler.ScaleFactor); var resizedH = (int)(croppedHeight * Scaler.ScaleFactor); var padding = (resizedW % 4); resizedW = resizedW + (padding == 0 ? 0 : 4 - padding);//bmp stride should be multiple of 4 //determines resized canvas size Size resizedCanvasSize = new Size((int)(croppedWidth * Scaler.ScaleFactor), (int)(croppedHeight * Scaler.ScaleFactor)); //take lefttop visible tile to measure offset for other tiles if (tile.Equals(visibleTiles.First())) { leftTopTile = tile; cropS = resizedCanvasSize; } //see pointToDraw description int x = tile.LeftTopCoord.X <= leftTopPointOfView.X ? 0 : cropS.Width + ((tile.LeftTopCoord.X - leftTopTile.LeftTopCoord.X) / tile.Size.Width - 1) * tile.Size.Width * (int)Scaler.ScaleFactor; int y = tile.LeftTopCoord.Y <= leftTopPointOfView.Y ? 0 : cropS.Height + ((tile.LeftTopCoord.Y - leftTopTile.LeftTopCoord.Y) / tile.Size.Height - 1) * tile.Size.Height * (int)Scaler.ScaleFactor; byte[] imgData = tile.ReadData(); byte[] cropped = DrawingHelper.Crop(imgData, tile.Size.Width, shiftTileX, shiftTileY, croppedWidth, croppedHeight); byte[] resized = DrawingHelper.Resize(cropped, croppedWidth, resizedW, resizedH, Scaler.ScaleFactor); tileImgWrappers.Add(new TileRawWrapper(resized, x, y, resizedCanvasSize.Width, resizedCanvasSize.Height)); } return tileImgWrappers; }
/// <summary> /// Returns image from visible tiles with 1:1 scale /// </summary> /// <param name="tiles"></param> /// <param name="leftTopPointOfView"></param> /// <param name="screenSize"></param> /// <returns></returns> private IEnumerable<TileRawWrapper> ScaleNormal(Tile[] tiles, Point leftTopPointOfView, Size screenSize) { var visibleTiles = tiles.Where(x => x.CheckVisibility(leftTopPointOfView, screenSize.Width, screenSize.Height)); var tileImgWrappers = new List<TileRawWrapper>(); foreach(var tile in visibleTiles) { var tileBytes = tile.ReadData(); int xToScreen = tile.LeftTopCoord.X - leftTopPointOfView.X; int yToScreen = tile.LeftTopCoord.Y - leftTopPointOfView.Y; tileImgWrappers.Add(new TileRawWrapper(tileBytes, xToScreen, yToScreen, tile.Size.Width, tile.Size.Height)); } return tileImgWrappers; }
/// <summary> /// Returns image from visible tiles with scale factor < 1 /// </summary> /// <param name="tiles"></param> /// <param name="leftTopPointOfView"></param> /// <param name="screenSize"></param> /// <param name="highRes">Determines if algorithm uses averaging to get downscaled image (true if it uses)</param> /// <returns></returns> private IEnumerable<TileRawWrapper> ScaleDown(Tile[] tiles, Point leftTopPointOfView, Size screenSize, bool highRes) { int scaledScreenX = (int)Math.Ceiling(screenSize.Width / Scaler.ScaleFactor); int scaledScreenY = (int)Math.Ceiling(screenSize.Height / Scaler.ScaleFactor); var visibleTiles = tiles.Where(x => x.CheckVisibility(leftTopPointOfView, scaledScreenX, scaledScreenY)); int scale = (int)(1 / Scaler.ScaleFactor); int scalePower = (int)Math.Log(scale, 2); BlockingCollection<TileRawWrapper> tileImgWrappers = new BlockingCollection<TileRawWrapper>(); //var tileImgWrappers = new List<TileImageWrapper>(visibleTiles.Count()); Parallel.ForEach(visibleTiles, tile => { byte[] imgData = tile.ReadData(); byte[] sievedImage = new byte[imgData.Length >> scalePower >> scalePower]; //scale by averaging nearby pixels int index = 0; for (int i = 0; i < tile.Size.Height * tile.Size.Width - tile.Size.Width; i += scale * tile.Size.Width) { for (int j = i; j < i + tile.Size.Width; j += scale) { if (highRes) { int cumulative = 0; for (int k = j; k < j + scale; k++) { cumulative += imgData[k]; } sievedImage[index] = (byte)(cumulative >> scalePower); } else { sievedImage[index] = imgData[j]; } index++; } } var tw = new TileRawWrapper(sievedImage, (int)((tile.LeftTopCoord.X - leftTopPointOfView.X) >> scalePower), (int)((tile.LeftTopCoord.Y - leftTopPointOfView.Y) >> scalePower), tile.Size.Width >> scalePower, tile.Size.Height >> scalePower); tileImgWrappers.Add(tw); }); return tileImgWrappers; }