public async Task <State> FunctionHandler(State state, ILambdaContext context) { var tmpPath = Path.Combine(Path.GetTempPath(), Path.GetFileName(state.SourceKey)); try { context.Logger.LogLine("Saving image to tmp"); using (var response = await S3Client.GetObjectAsync(state.Bucket, state.SourceKey)) { await response.WriteResponseStreamToFileAsync(tmpPath, false, default(CancellationToken)); } var mosaicLayoutInfo = MosaicLayoutInfoManager.Create(); state.MosaicLayoutInfoKey = mosaicLayoutInfo.Key; context.Logger.LogLine($"Loading image {tmpPath}. File size {new FileInfo(tmpPath).Length}"); using (var sourceImage = Image.Load(tmpPath)) { state.OriginalImagePixelCount = sourceImage.Width * sourceImage.Height; if (state.OriginalImagePixelCount < State.SMALL_IMAGE_SIZE) { state.PixelBlock = 3; } else if (state.OriginalImagePixelCount < State.MEDIUM_IMAGE_SIZE) { state.PixelBlock = 5; } else if (state.OriginalImagePixelCount < State.MAX_IMAGE_SIZE) { state.PixelBlock = 10; } else { throw new Exception("Image too large to make a mosaic"); } mosaicLayoutInfo.ColorMap = CreateMap(state, sourceImage); } context.Logger.LogLine($"Color map created: {mosaicLayoutInfo.ColorMap.GetLength(0)}x{mosaicLayoutInfo.ColorMap.GetLength(1)}"); await MosaicLayoutInfoManager.Save(S3Client, state.Bucket, mosaicLayoutInfo); context.Logger.LogLine($"Saving mosaic layout info to {mosaicLayoutInfo.Key}"); return(state); } finally { if (File.Exists(tmpPath)) { File.Delete(tmpPath); } } }
public async Task <State> FunctionHandler(State state, ILambdaContext context) { if (Directory.Exists(this.TileImageCacheDirectory)) { Directory.Delete(this.TileImageCacheDirectory, true); } Directory.CreateDirectory(this.TileImageCacheDirectory); context.Logger.LogLine("Loading mosaic layout info"); var mosaicLayoutInfo = await MosaicLayoutInfoManager.Load(this.S3Client, state.Bucket, state.MosaicLayoutInfoKey); var width = mosaicLayoutInfo.ColorMap.GetLength(0) * state.TileSize; var height = mosaicLayoutInfo.ColorMap.GetLength(1) * state.TileSize; context.Logger.LogLine($"Creating pixel data array {width}x{height}"); var pixalData = new Rgba32[width * height]; for (int i = 0; i < pixalData.Length; i++) { pixalData[i] = Rgba32.Black; } context.Logger.LogLine($"Creating blank image"); using (var rawImage = Image.LoadPixelData(pixalData, width, height)) { context.Logger.LogLine($"Created blank image"); for (int x = 0; x < mosaicLayoutInfo.ColorMap.GetLength(0); x++) { int xoffset = x * state.TileSize; context.Logger.LogLine($"Processing row {x}"); for (int y = 0; y < mosaicLayoutInfo.ColorMap.GetLength(1); y++) { int yoffset = y * state.TileSize; var tileId = mosaicLayoutInfo.TileMap[x, y]; var tileKey = mosaicLayoutInfo.IdToTileKey[tileId]; using (var tileImage = await LoadTile(state.Bucket, tileKey, context)) { for (int x1 = 0; x1 < state.TileSize; x1++) { for (int y1 = 0; y1 < state.TileSize; y1++) { rawImage[x1 + xoffset, y1 + yoffset] = tileImage[x1, y1]; } } } } } // Write full mosaic to S3 { var finalOutputStream = new MemoryStream(); rawImage.Save(finalOutputStream, new SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder()); finalOutputStream.Position = 0; var destinationKey = S3KeyManager.DetermineS3Key(state.UserId, state.MosaicId, S3KeyManager.ImageType.FullMosaic); context.Logger.LogLine( $"Saving full mosaic to {destinationKey} with size {finalOutputStream.Length}"); await this.S3Client.PutObjectAsync(new PutObjectRequest { BucketName = state.Bucket, Key = destinationKey, InputStream = finalOutputStream }); } // Write web size mosaic to S3 await SaveResize(state, rawImage, Constants.IMAGE_WEB_WIDTH, Constants.IMAGE_WEB_HEIGHT, S3KeyManager.DetermineS3Key(state.UserId, state.MosaicId, S3KeyManager.ImageType.WebMosaic), context); // Write thumbnail mosaic to S3 await SaveResize(state, rawImage, Constants.IMAGE_THUMBNAIL_WIDTH, Constants.IMAGE_THUMBNAIL_HEIGHT, S3KeyManager.DetermineS3Key(state.UserId, state.MosaicId, S3KeyManager.ImageType.ThumbnailMosaic), context); return(state); } }