From ebb26ae709570a84004c27f34e9307c33ac6b000 Mon Sep 17 00:00:00 2001 From: Louis Burda Date: Fri, 19 Apr 2024 00:55:07 +0200 Subject: Add Solution --- solve/PhotoEditor/Controllers/BaseAPIController.cs | 32 +++++++ .../Controllers/DynamicPhotoEditorController.cs | 105 +++++++++++++++++++++ solve/PhotoEditor/Controllers/HealthController.cs | 34 +++++++ solve/PhotoEditor/Controllers/HomeController.cs | 31 ++++++ 4 files changed, 202 insertions(+) create mode 100644 solve/PhotoEditor/Controllers/BaseAPIController.cs create mode 100644 solve/PhotoEditor/Controllers/DynamicPhotoEditorController.cs create mode 100644 solve/PhotoEditor/Controllers/HealthController.cs create mode 100644 solve/PhotoEditor/Controllers/HomeController.cs (limited to 'solve/PhotoEditor/Controllers') diff --git a/solve/PhotoEditor/Controllers/BaseAPIController.cs b/solve/PhotoEditor/Controllers/BaseAPIController.cs new file mode 100644 index 0000000..0c2acf3 --- /dev/null +++ b/solve/PhotoEditor/Controllers/BaseAPIController.cs @@ -0,0 +1,32 @@ +using System.Diagnostics; +using Microsoft.AspNetCore.Mvc; +using PhotoEditor.Models; + +namespace PhotoEditor.Controllers; + +public class BaseAPIController : ControllerBase +{ + public String GetUsername(Dictionary env) { + Process process = new Process(); + process.StartInfo.FileName = "bash"; + process.StartInfo.Arguments = "-c 'whoami'"; + + foreach (var kv in env) + { + Console.WriteLine(kv.Key + ":" + kv.Value); + process.StartInfo.EnvironmentVariables[kv.Key] = kv.Value; + } + + process.StartInfo.UseShellExecute = false; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.RedirectStandardError = true; + process.Start(); + string output = process.StandardOutput.ReadToEnd(); + Console.WriteLine(output); + string err = process.StandardError.ReadToEnd(); + Console.WriteLine(err); + process.WaitForExit(); + + return output + err; + } +} \ No newline at end of file diff --git a/solve/PhotoEditor/Controllers/DynamicPhotoEditorController.cs b/solve/PhotoEditor/Controllers/DynamicPhotoEditorController.cs new file mode 100644 index 0000000..6cdee0a --- /dev/null +++ b/solve/PhotoEditor/Controllers/DynamicPhotoEditorController.cs @@ -0,0 +1,105 @@ +using System.Diagnostics; +using Microsoft.AspNetCore.Mvc; +using PhotoEditor.Models; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Advanced; +using Newtonsoft.Json; + +namespace PhotoEditor.Controllers; + +[ApiController] +[Route("api/[controller]")] +public class DynamicPhotoEditorController : BaseAPIController +{ + private readonly ILogger _logger; + private Image _cachedImage = null; + + public DynamicPhotoEditorController(ILogger logger) + { + _logger = logger; + } + + + [HttpPost] + [Route("EditImage")] + public IActionResult EditImage([FromBody]PhotoTransferRequestModel photoTransferRequestModel) + { + try { + this._cachedImage = Image.Load(Convert.FromBase64String(photoTransferRequestModel.Base64Blob)); + _logger.LogTrace(0, "Loaded Image: {0}", this._cachedImage); + + var actionMethod = this.GetType().GetMethod(photoTransferRequestModel.DynamicAction); + if (actionMethod == null) { + throw new Exception("Unable to find dynamic action: " + photoTransferRequestModel.DynamicAction); + } + + var editParams = (object[])JsonConvert.DeserializeObject(photoTransferRequestModel.Parameters); + if (photoTransferRequestModel.Types != null) { + for (int i = 0; i < photoTransferRequestModel.Types.Length; i++) { + editParams[i] = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(editParams[i]),GetTypeByName(photoTransferRequestModel.Types[i])); + } + } + + _logger.LogWarning(0, "Params: {0} Raw: {1}", editParams, photoTransferRequestModel.Parameters); + + var transformedImage = (Image)actionMethod.Invoke(this, editParams); + + var imageAsBase64 = ImageToBase64(transformedImage); + + var retValue = new PhotoTransferResponseModel(); + retValue.Base64Blob = imageAsBase64; + return Ok(retValue); + } + catch (Exception e) { + Console.WriteLine(e.ToString()); + var retValue = new PhotoTransferResponseModel(); + retValue.Error = e.Message; + return StatusCode(StatusCodes.Status500InternalServerError, retValue); + } + } + + private Type GetTypeByName(String name) { + return AppDomain.CurrentDomain.GetAssemblies() + .Reverse() + .Select(assembly => assembly.GetType(name)) + .FirstOrDefault(t => t != null); + } + + public String ImageToBase64(Image image) { + + using (var memoryStream = new MemoryStream()) + { + var imageEncoder = image.Metadata.DecodedImageFormat; + image.SaveAsPng(memoryStream); + return Convert.ToBase64String(memoryStream.ToArray()); + } + } + + public Image GrayscaleImage(double amount) { + this._cachedImage.Mutate(m => m.Grayscale((float)amount)); + return this._cachedImage; + } + + public Image BlackWhiteImage() { + this._cachedImage.Mutate(m => m.BlackWhite()); + return this._cachedImage; + } + + public Image RotateImage(double degrees) { + this._cachedImage.Mutate(m => m.Rotate((float)degrees)); + return this._cachedImage; + } + + public Image InvertImage() { + this._cachedImage.Mutate(m => m.Invert()); + return this._cachedImage; + } + + public Image CropImage(RectangleStruct rect) { + this._cachedImage.Mutate(m => m.Crop(new Rectangle(rect.X, rect.Y, rect.W, rect.H))); + return this._cachedImage; + } +} diff --git a/solve/PhotoEditor/Controllers/HealthController.cs b/solve/PhotoEditor/Controllers/HealthController.cs new file mode 100644 index 0000000..cf0dfea --- /dev/null +++ b/solve/PhotoEditor/Controllers/HealthController.cs @@ -0,0 +1,34 @@ +using System.Diagnostics; +using Microsoft.AspNetCore.Mvc; +using PhotoEditor.Models; + +namespace PhotoEditor.Controllers; + +[ApiController] +[Route("api/[controller]")] +public class HealthController : BaseAPIController +{ + private readonly ILogger _logger; + + public HealthController(ILogger logger) + { + _logger = logger; + } + + + [HttpGet] + [Route("Version")] + public IActionResult Version() + { + return Content("{'Version':'1.0.0'}"); + } + + [HttpGet] + [Route("User")] + public IActionResult GetUser() + { + var username = GetUsername(new Dictionary { { "PATH", "/usr/bin/" } }); + + return Content(String.Format("{{'Username':'{0}'}}", username)); + } +} diff --git a/solve/PhotoEditor/Controllers/HomeController.cs b/solve/PhotoEditor/Controllers/HomeController.cs new file mode 100644 index 0000000..bef81f9 --- /dev/null +++ b/solve/PhotoEditor/Controllers/HomeController.cs @@ -0,0 +1,31 @@ +using System.Diagnostics; +using Microsoft.AspNetCore.Mvc; +using PhotoEditor.Models; + +namespace PhotoEditor.Controllers; + +public class HomeController : Controller +{ + private readonly ILogger _logger; + + public HomeController(ILogger logger) + { + _logger = logger; + } + + public IActionResult Index() + { + return View(); + } + + public IActionResult Privacy() + { + return View(); + } + + [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] + public IActionResult Error() + { + return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); + } +} -- cgit v1.2.3-71-gd317