using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Amazon.Lambda.Core;
using Amazon.Lambda.RuntimeSupport;
using Amazon.Lambda.Serialization.SystemTextJson;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.XRay.Recorder.Handlers.AwsSdk;
using Common;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Processing;
namespace thumbnail
{
public class Function
{
private const int MAX_WIDTH = 250;
private const int MAX_HEIGHT = 250;
private static IAmazonS3 S3Client { get; }
static Function()
{
AWSSDKHandler.RegisterXRayForAllServices();
S3Client = new AmazonS3Client();
}
///
/// The main entry point for the custom runtime.
///
///
private static async Task Main()
{
Func> handler = FunctionHandler;
await LambdaBootstrapBuilder.Create(handler, new SourceGeneratorLambdaJsonSerializer(options => {
options.PropertyNameCaseInsensitive = true;
}))
.Build()
.RunAsync();
}
///
/// A simple function that takes a string and returns both the upper and lower case version of the string.
///
///
///
///
private static async Task FunctionHandler(Input input, ILambdaContext context)
{
var logger = new ImageRecognitionLogger(input, context);
var size = input.ExtractedMetadata.Dimensions;
var scalingFactor = Math.Min(
MAX_WIDTH / size.Width,
MAX_HEIGHT / size.Height
);
var width = Convert.ToInt32(scalingFactor * size.Width);
var height = Convert.ToInt32(scalingFactor * size.Height);
var image = await GenerateThumbnail(input.Bucket, input.SourceKey, width, height);
var destinationKey = input.SourceKey.Replace("uploads", "resized");
using (var stream = new MemoryStream())
{
await image.thumbnailImage.SaveAsync(stream, image.format);
stream.Position = 0;
context.Logger.LogLine($"Saving thumbnail to {destinationKey} with size {stream.Length}");
await S3Client.PutObjectAsync(new PutObjectRequest
{
BucketName = input.Bucket,
Key = destinationKey,
InputStream = stream
});
await logger.WriteMessageAsync(new MessageEvent {Message = "Photo thumbnail created"},
ImageRecognitionLogger.Target.All);
return new ThumbnailInfo(width, height, destinationKey, input.Bucket);
}
}
private static async Task GenerateThumbnail(string s3Bucket, string srcKey, int width, int height)
{
srcKey = WebUtility.UrlDecode(srcKey.Replace("+", " "));
using (var response = await S3Client.GetObjectAsync(s3Bucket, srcKey))
{
var image = Image.Load(response.ResponseStream, out var format);
image.Mutate(x => x.Resize(new ResizeOptions
{
Size = new Size {Width = width, Height = height},
Mode = ResizeMode.Stretch
}));
return new ThumbnailImage(image, format);
}
}
}
public record ThumbnailImage(Image thumbnailImage, IImageFormat format);
public record ThumbnailInfo(int width, int height, string s3key, string s3Bucket);
}