使用 aws lambda c# 裁剪图像(使用 Java 解决)
crop image using using aws lambda c# (Solved using Java)
我正在尝试使用 C# 创建一个 AWS Lambda 函数来裁剪存储在 S3 存储桶中的图像。裁剪后,需要将新图像推送到另一个存储桶。并且必须使用 AWS Lambda 客户端手动调用此函数。由于我是初学者,网上没有太多教程,请帮助我。
这就是我的代码的样子
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[]));
//}
}
}
这是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"
]
}
}
}
而且,这是堆栈跟踪
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
用于裁剪和旋转图像的代码
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;
}
}
}
您需要学习如何 read an S3 object using the .NET SDK。
您需要 learn how to upload an image to S3 using the .NET SDK。
您可以在没有 AWS Lambda 集成的情况下在测试或 main 方法中练习这两个操作,让您的脚湿润。
接下来你会想知道how to crop an image in C#。同样,您可以在不需要 AWS Lambda 的情况下进行测试。
最后,您应该阅读 AWS Lambda C# documentation 并尝试一些创建函数的简单示例。获得一个完全可用的非常基本的示例,然后在其基础上添加您在上面开发的代码。
发现现在用 C# 很难做到,我必须学习 java。请参阅下面的 Java 代码,从 s3 下载图像、调整大小(不丢失纵横比)、裁剪、旋转并上传回 s3(到不同的存储桶)。它完美运行。
package imageprocessor;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.UUID;
import javax.imageio.ImageIO;
import javax.swing.UIManager;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.PutObjectRequest;
public class LambdaImageProcessor implements RequestHandler<String, String> {
private static final String filePath = "/tmp/";
private static File localFile, outputfileCropped, outputfileRotated, outputfileSized;
private static final float xsize = 500; //max width for resize
private static final float ysize = 500; //max height for resize
@Override
public String handleRequest(String input, Context context) {
AmazonS3Client s3Client = new AmazonS3Client(
new DefaultAWSCredentialsProviderChain());
context.getLogger().log("Input: " + input + "\n");
try
{
String[] arr = input.split(",");
String sourceBucket = arr[0];
String key = arr[1];
String destBucket = arr[2];
String permission = arr[3];
//download
context.getLogger().log("AWS S3 downloading image\n");
GetObjectRequest downloadReq = new GetObjectRequest(sourceBucket, key);
String uniqueID = UUID.randomUUID().toString().replaceAll("-", "");
localFile = new File(filePath + uniqueID + "_" + key);
outputfileCropped = new File(filePath + uniqueID + "_" + "c_" + key);
outputfileRotated = new File(filePath + uniqueID + "_" + "r_" + key);
outputfileSized = new File(filePath + uniqueID + "_" + "s_" + key);
if(localFile.exists())
{
localFile.delete();
}
if(outputfileCropped.exists())
{
outputfileCropped.delete();
}
if(outputfileRotated.exists())
{
outputfileRotated.delete();
}
context.getLogger().log("File name - " + localFile.toString() + "\n");
s3Client.getObject(downloadReq, localFile);
context.getLogger().log("AWS S3 download - Done\n");
//upload
if(localFile.exists())
{
//context.getLogger().log("AWS S3 cropping image\n");
BufferedImage bufferedImage = ImageIO.read(localFile);
BufferedImage resizeBuffered = resizeImage(bufferedImage, xsize, ysize);
//ImageIO.write(resizeBuffered, "jpg", outputfileSized);
context.getLogger().log("AWS S3 Resize - Done\n");
Rectangle rect = new Rectangle(100, 100, 300, 150);
BufferedImage cropBuffered = cropImage(resizeBuffered, rect);
context.getLogger().log("AWS S3 Crop - Done\n");
ImageIO.write(rotateImage(cropBuffered, 90), "jpg", outputfileRotated);
context.getLogger().log("AWS S3 Rotate - Done\n");
context.getLogger().log("AWS S3 uploading image\n");
PutObjectRequest uploadReq = new PutObjectRequest(destBucket, key, outputfileRotated);
if(permission.toUpperCase().equals("PUBLIC"))
{
uploadReq.setCannedAcl(CannedAccessControlList.PublicRead);
}
else if(permission.toUpperCase().equals("PRIVATE"))
{
uploadReq.setCannedAcl(CannedAccessControlList.Private);
}
s3Client.putObject(uploadReq);
context.getLogger().log("AWS S3 upload - Done\n");
}
else
{
context.getLogger().log("Downloaded file not found\n");
}
return context.getAwsRequestId();
}
catch (Exception ex)
{
context.getLogger().log("Exception - " + ex.getMessage().toString() + " " + ex.getStackTrace().toString() + "\n");
return "Exception - " + ex.getMessage().toString() + " " + ex.getStackTrace().toString();
}
finally
{
if(localFile.exists())
{
localFile.delete();
context.getLogger().log("Temp Local File Deleted\n");
}
if(outputfileCropped.exists())
{
outputfileCropped.delete();
context.getLogger().log("Temp Cropped File Deleted\n");
}
if(outputfileRotated.exists())
{
outputfileRotated.delete();
context.getLogger().log("Temp Rotated File Deleted\n");
}
if(outputfileSized.exists())
{
outputfileSized.delete();
context.getLogger().log("Temp ReSized File Deleted\n");
}
}
}
private static BufferedImage cropImage(BufferedImage src, Rectangle rect) {
BufferedImage dest = src.getSubimage(rect.x, rect.y, rect.width, rect.height);
return dest;
}
private static BufferedImage rotateImage(BufferedImage bufferedImage, int angle) {
double theta = Math.toRadians(angle);
double cos = Math.abs(Math.cos(theta));
double sin = Math.abs(Math.sin(theta));
double width = bufferedImage.getWidth();
double height = bufferedImage.getHeight();
int w = (int)(width * cos + height * sin);
int h = (int)(width * sin + height * cos);
BufferedImage out = new BufferedImage(w, h, bufferedImage.getType());
Graphics2D g2 = out.createGraphics();
g2.setPaint(UIManager.getColor("Panel.background"));
g2.fillRect(0,0,w,h);
double x = w/2;
double y = h/2;
AffineTransform at = AffineTransform.getRotateInstance(theta, x, y);
x = (w - width)/2;
y = (h - height)/2;
at.translate(x, y);
g2.drawRenderedImage(bufferedImage, at);
g2.dispose();
return out;
}
private static BufferedImage resizeImage(BufferedImage bufferedImage, float sizeX, float sizeY)
{
float ratioX = sizeX / bufferedImage.getWidth();
float ratioY = sizeY / bufferedImage.getHeight();
float ratio = Math.min(ratioX, ratioY);
float newX = bufferedImage.getWidth() * ratio;
float newY = bufferedImage.getHeight() * ratio;
BufferedImage resizedImage = new BufferedImage((int)newX, (int)newY, bufferedImage.getType());
Graphics2D g = resizedImage.createGraphics();
g.drawImage(bufferedImage, 0, 0, (int)newX, (int)newY, null);
g.dispose();
return resizedImage;
}
}
我正在尝试使用 C# 创建一个 AWS Lambda 函数来裁剪存储在 S3 存储桶中的图像。裁剪后,需要将新图像推送到另一个存储桶。并且必须使用 AWS Lambda 客户端手动调用此函数。由于我是初学者,网上没有太多教程,请帮助我。
这就是我的代码的样子
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[]));
//}
}
}
这是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"
]
}
}
}
而且,这是堆栈跟踪
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
用于裁剪和旋转图像的代码
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;
}
}
}
您需要学习如何 read an S3 object using the .NET SDK。
您需要 learn how to upload an image to S3 using the .NET SDK。
您可以在没有 AWS Lambda 集成的情况下在测试或 main 方法中练习这两个操作,让您的脚湿润。
接下来你会想知道how to crop an image in C#。同样,您可以在不需要 AWS Lambda 的情况下进行测试。
最后,您应该阅读 AWS Lambda C# documentation 并尝试一些创建函数的简单示例。获得一个完全可用的非常基本的示例,然后在其基础上添加您在上面开发的代码。
发现现在用 C# 很难做到,我必须学习 java。请参阅下面的 Java 代码,从 s3 下载图像、调整大小(不丢失纵横比)、裁剪、旋转并上传回 s3(到不同的存储桶)。它完美运行。
package imageprocessor;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.UUID;
import javax.imageio.ImageIO;
import javax.swing.UIManager;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.PutObjectRequest;
public class LambdaImageProcessor implements RequestHandler<String, String> {
private static final String filePath = "/tmp/";
private static File localFile, outputfileCropped, outputfileRotated, outputfileSized;
private static final float xsize = 500; //max width for resize
private static final float ysize = 500; //max height for resize
@Override
public String handleRequest(String input, Context context) {
AmazonS3Client s3Client = new AmazonS3Client(
new DefaultAWSCredentialsProviderChain());
context.getLogger().log("Input: " + input + "\n");
try
{
String[] arr = input.split(",");
String sourceBucket = arr[0];
String key = arr[1];
String destBucket = arr[2];
String permission = arr[3];
//download
context.getLogger().log("AWS S3 downloading image\n");
GetObjectRequest downloadReq = new GetObjectRequest(sourceBucket, key);
String uniqueID = UUID.randomUUID().toString().replaceAll("-", "");
localFile = new File(filePath + uniqueID + "_" + key);
outputfileCropped = new File(filePath + uniqueID + "_" + "c_" + key);
outputfileRotated = new File(filePath + uniqueID + "_" + "r_" + key);
outputfileSized = new File(filePath + uniqueID + "_" + "s_" + key);
if(localFile.exists())
{
localFile.delete();
}
if(outputfileCropped.exists())
{
outputfileCropped.delete();
}
if(outputfileRotated.exists())
{
outputfileRotated.delete();
}
context.getLogger().log("File name - " + localFile.toString() + "\n");
s3Client.getObject(downloadReq, localFile);
context.getLogger().log("AWS S3 download - Done\n");
//upload
if(localFile.exists())
{
//context.getLogger().log("AWS S3 cropping image\n");
BufferedImage bufferedImage = ImageIO.read(localFile);
BufferedImage resizeBuffered = resizeImage(bufferedImage, xsize, ysize);
//ImageIO.write(resizeBuffered, "jpg", outputfileSized);
context.getLogger().log("AWS S3 Resize - Done\n");
Rectangle rect = new Rectangle(100, 100, 300, 150);
BufferedImage cropBuffered = cropImage(resizeBuffered, rect);
context.getLogger().log("AWS S3 Crop - Done\n");
ImageIO.write(rotateImage(cropBuffered, 90), "jpg", outputfileRotated);
context.getLogger().log("AWS S3 Rotate - Done\n");
context.getLogger().log("AWS S3 uploading image\n");
PutObjectRequest uploadReq = new PutObjectRequest(destBucket, key, outputfileRotated);
if(permission.toUpperCase().equals("PUBLIC"))
{
uploadReq.setCannedAcl(CannedAccessControlList.PublicRead);
}
else if(permission.toUpperCase().equals("PRIVATE"))
{
uploadReq.setCannedAcl(CannedAccessControlList.Private);
}
s3Client.putObject(uploadReq);
context.getLogger().log("AWS S3 upload - Done\n");
}
else
{
context.getLogger().log("Downloaded file not found\n");
}
return context.getAwsRequestId();
}
catch (Exception ex)
{
context.getLogger().log("Exception - " + ex.getMessage().toString() + " " + ex.getStackTrace().toString() + "\n");
return "Exception - " + ex.getMessage().toString() + " " + ex.getStackTrace().toString();
}
finally
{
if(localFile.exists())
{
localFile.delete();
context.getLogger().log("Temp Local File Deleted\n");
}
if(outputfileCropped.exists())
{
outputfileCropped.delete();
context.getLogger().log("Temp Cropped File Deleted\n");
}
if(outputfileRotated.exists())
{
outputfileRotated.delete();
context.getLogger().log("Temp Rotated File Deleted\n");
}
if(outputfileSized.exists())
{
outputfileSized.delete();
context.getLogger().log("Temp ReSized File Deleted\n");
}
}
}
private static BufferedImage cropImage(BufferedImage src, Rectangle rect) {
BufferedImage dest = src.getSubimage(rect.x, rect.y, rect.width, rect.height);
return dest;
}
private static BufferedImage rotateImage(BufferedImage bufferedImage, int angle) {
double theta = Math.toRadians(angle);
double cos = Math.abs(Math.cos(theta));
double sin = Math.abs(Math.sin(theta));
double width = bufferedImage.getWidth();
double height = bufferedImage.getHeight();
int w = (int)(width * cos + height * sin);
int h = (int)(width * sin + height * cos);
BufferedImage out = new BufferedImage(w, h, bufferedImage.getType());
Graphics2D g2 = out.createGraphics();
g2.setPaint(UIManager.getColor("Panel.background"));
g2.fillRect(0,0,w,h);
double x = w/2;
double y = h/2;
AffineTransform at = AffineTransform.getRotateInstance(theta, x, y);
x = (w - width)/2;
y = (h - height)/2;
at.translate(x, y);
g2.drawRenderedImage(bufferedImage, at);
g2.dispose();
return out;
}
private static BufferedImage resizeImage(BufferedImage bufferedImage, float sizeX, float sizeY)
{
float ratioX = sizeX / bufferedImage.getWidth();
float ratioY = sizeY / bufferedImage.getHeight();
float ratio = Math.min(ratioX, ratioY);
float newX = bufferedImage.getWidth() * ratio;
float newY = bufferedImage.getHeight() * ratio;
BufferedImage resizedImage = new BufferedImage((int)newX, (int)newY, bufferedImage.getType());
Graphics2D g = resizedImage.createGraphics();
g.drawImage(bufferedImage, 0, 0, (int)newX, (int)newY, null);
g.dispose();
return resizedImage;
}
}