Im trying to create an AWS Lambda Function in C# to crop an image which is stored in the S3 bucket. Once cropped, the new image need to be pushed to another bucket. And this function has to be invoked manually using the AWS Lambda Client. As im a beginner and there is not much tutorials available on the web, please help me on this.
This is how my code looks like
using System;
using System.Threading.Tasks;
using System.IO;
using Amazon.Lambda.Core;
using Amazon.Lambda.Serialization;
using Amazon.S3;
using Amazon;
using Amazon.S3.Model;
using Pomelo.Data.MySql;
using System.Drawing;
using Amazon.S3.Transfer;
//using ImageNet;
//using ImageResizer;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializerAttribute(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
namespace Cropper
{
public class Crop
{
IAmazonS3 s3Client { get; set; }
private Image orgImg;
private MySqlConnection dbConn = new MySqlConnection();
private MySqlCommand cmd = new MySqlCommand();
public Crop()
{
s3Client = new AmazonS3Client();
}
/*private static string s3AccessKey = Environment.GetEnvironmentVariable("S3AccessKey");
private static string s3SecretKey = Environment.GetEnvironmentVariable("S3SecretKey");
private static string s3Region = Environment.GetEnvironmentVariable("S3Region");
private AmazonS3Client s3Client = new AmazonS3Client(s3AccessKey,s3SecretKey, RegionEndpoint.GetBySystemName(s3Region));
*/
// public async Task<string> CropImage(string sourceBucket, string key, string destBucket, string permission)
//public async void CropImage(string sourceBucket, string key, string destBucket, string permission)
public async Task<string> CropImage(string input, ILambdaContext context)
{
s3Client = new AmazonS3Client();
string[] arr = input.Split(',');
string sourceBucket = arr[0].Trim();
string key = arr[1].Trim();
string destBucket = arr[2].Trim();
//string size = arr[3].Trim();
//string crop = arr[3].Trim();
string permission = arr[3].Trim();
string path = Path.Combine("/tmp", key);
try
{
Console.WriteLine("Checkpoint - 0");
TransferUtility fileTransferUtility = new TransferUtility(s3Client);
TransferUtilityDownloadRequest downloadRequest = new TransferUtilityDownloadRequest();
Console.WriteLine("path - " + path);
if (File.Exists(path))
{
File.Delete(path);
}
downloadRequest.FilePath = path;
downloadRequest.BucketName = sourceBucket;
downloadRequest.Key = key;
fileTransferUtility.Download(downloadRequest);
Console.WriteLine("Checkpoint - file transfer");
orgImg = Image.FromFile(path);
orgImg.RotateFlip(RotateFlipType.Rotate90FlipNone);
//FluentImage.FromFile(path)
// .Resize.Width(200)
// .Save("/tmp/test_file.png", OutputFormat.Png);
Console.WriteLine("Checkpoint - Img creation");
TransferUtilityUploadRequest uploadRequest = new TransferUtilityUploadRequest();
//uploadRequest.FilePath = "/tmp/test_file.png";
uploadRequest.FilePath = path;
uploadRequest.BucketName = destBucket;
uploadRequest.Key = key;
if (permission.ToUpper() == "PUBLIC")
{
uploadRequest.CannedACL = S3CannedACL.PublicRead;
}
else if (permission.ToUpper() == "PRIVATE")
{
uploadRequest.CannedACL = S3CannedACL.Private;
}
else if (permission.ToUpper() == "NONE")
{
uploadRequest.CannedACL = S3CannedACL.NoACL;
}
fileTransferUtility.Upload(uploadRequest);
Console.WriteLine("Checkpoint - Done");
return context.AwsRequestId.ToString();
}
catch (Exception ex)
{
Console.WriteLine("ex message - " + ex.Message);
Console.WriteLine("ex stack - " + ex.StackTrace);
return ex.Message;
//context.Logger.LogLine(ex.Message);
}
finally
{
if (File.Exists(path))
{
File.Delete(path);
}
if (orgImg != null)
{
orgImg.Dispose();
}
}
}
//private byte[] ToArrayBytes(Stream input)
//{
// byte[] buffer = new byte[16 * 1024];
// using (MemoryStream ms = new MemoryStream())
// {
// int read;
// while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
// {
// ms.Write(buffer, 0, read);
// }
// return ms.ToArray();
// }
//}
//private byte[] ImageToByte(Image img)
//{
// ImageConverter converter = new ImageConverter();
// return (byte[])converter.ConvertTo(img, typeof(byte[]));
//}
}
}
This is the project.json
{
"version": "1.0.0-*",
"buildOptions": {
},
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"Amazon.Lambda.Core": "1.0.0*",
"Amazon.Lambda.Serialization.Json": "1.0.1",
"Amazon.Lambda.Tools": {
"type": "build",
"version": "1.0.4-preview1"
},
"AWSSDK.S3": "3.3.4.1",
"Pomelo.Data.MySql": "1.0.0",
"Microsoft.NETCore.Portable.Compatibility": "1.0.1",
//"System.Drawing-dotnet-core": "1.0.2",
//"Shaman.System.Drawing": "1.0.1.1",
//"ZKWeb.System.Drawing": "2.0.1"
//"System.Drawing.Primitives": "4.3.0"
//"ImageProcessor-strong-name": "2.3.0",
//"Microsoft.NETCore.Runtime.CoreCLR": "1.1.0",
//"Sitecore.ImageProcessor": "1.1.0",
//"DynamicImage": "3.1.1",
//"ImageLibrary": "3.0.0",
//"FluentImage": "1.1.0",
"CoreCompat.System.Drawing": "1.0.0-beta006",
"ImageResizer.Mvc": "4.0.5"
//"NETStandard.Library": "1.6.1"
//"omu.drawing": "1.0.0"
},
"tools": {
"Amazon.Lambda.Tools": "1.0.4-preview1"
},
"frameworks": {
"netcoreapp1.0": {
"imports": [
"dnxcore50",
"dotnet5.6",
"net46"
]
}
}
}
And, this is the stack trace
2017-11-03 23:11:43: START RequestId: e3975f78-d1db-11e6-9923-974cd0941dbb Version: $LATEST
2017-11-03 23:11:44: Checkpoint - 0
2017-11-03 23:11:44: path - /tmp/r3_small.jpg
2017-11-03 23:11:47: Checkpoint - file transfer
2017-11-03 23:11:47: ex message - The type initializer for 'System.Drawing.GDIPlus' threw an exception.
2017-11-03 23:11:48: ex stack - at System.Drawing.GDIPlus.GdipLoadImageFromFile(String filename, IntPtr& image)
2017-11-03 23:11:48: at System.Drawing.Image.FromFile(String filename, Boolean useEmbeddedColorManagement)
2017-11-03 23:11:48: at System.Drawing.Image.FromFile(String filename)
2017-11-03 23:11:48: at Cropper.Crop.<CropImage>d__8.MoveNext()
2017-11-03 23:11:48: END RequestId: e3975f78-d1db-11e6-9923-974cd0941dbb
2017-11-03 23:11:48: REPORT RequestId: e3975f78-d1db-11e6-9923-974cd0941dbb Duration: 4970.70 ms Billed Duration: 5000 ms Memory Size: 256 MB Max Memory Used: 63 MB
Code used to crop and rotate the image
public void cropLocal( string url, int x, int y, int w, int h, int a)
{
try
{
if (x != 0 && y != 0 && w != 0 && h != 0)
{
if (File.Exists(url))
{
orgImg = Image.FromFile(url);
switch (a)
{
case 90:
case -270:
orgImg.RotateFlip(RotateFlipType.Rotate90FlipNone);
break;
case 180:
case -180:
orgImg.RotateFlip(RotateFlipType.Rotate180FlipNone);
break;
case 270:
case -90:
orgImg.RotateFlip(RotateFlipType.Rotate270FlipNone);
break;
}
if (x < 0) { x = 0; }
if (y < 0) { y = 0; }
if (w > orgImg.Width) { w = orgImg.Width; }
if (h > orgImg.Height) { h = orgImg.Height; }
bitmap = new Bitmap(orgImg);
orgImg.Dispose();
orgImg = null;
rect = new Rectangle(x, y, w, h);
cropped = bitmap.Clone(rect, bitmap.PixelFormat);
bitmap.Dispose();
bitmap = null;
//delete original file
File.Delete(url);
//Save new file
cropped.Save(url);
cropped.Dispose();
cropped = null;
}
}
}
catch(Exception ex)
{
string excep = ex.Message;
}
finally
{
if (orgImg != null)
{
orgImg.Dispose();
orgImg = null;
}
if (bitmap != null)
{
bitmap.Dispose();
bitmap = null;
}
if (cropped != null)
{
cropped.Dispose();
cropped = null;
}
}
}