Created
January 10, 2013 09:57
-
-
Save eldewall/4500879 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using System.Web; | |
| using NovusDataLayer.Classes; | |
| using data = NovusDataLayer.DataClasses; | |
| using System.Drawing; | |
| using System.Diagnostics; | |
| using System.IO; | |
| using System.Drawing.Imaging; | |
| namespace Api.Classes.Images.refactor { | |
| public class ImageSpecification { | |
| public static int DefaultQuality = 85; | |
| public static int DefaultSharpen = 70; | |
| public int Sharpen { get; private set; } | |
| public int Quality { get; private set; } | |
| public int Height { get; private set; } | |
| public int Width { get; private set; } | |
| public ImageSpecification(string forSize) { | |
| Set(forSize); | |
| } | |
| private void Set(string size) { | |
| Quality = DefaultQuality; | |
| Sharpen = DefaultSharpen; | |
| switch (size.ToLower()) { | |
| case "adminthumb": | |
| Height = 0; | |
| Width = 180; | |
| break; | |
| case "adminaccount": | |
| Height = 100; | |
| Width = 100; | |
| break; | |
| case "adminlogo": | |
| Height = 80; | |
| Width = 180; | |
| break; | |
| default: | |
| throw new NotImplementedException("No spec defined for size: " + size); | |
| } | |
| } | |
| public void NormalizeHeight(double ratio) { | |
| Height = (int)Math.Round(Width * ratio); | |
| } | |
| } | |
| public class Timings { | |
| public double Load { get; private set; } | |
| public double Resize { get; private set; } | |
| public double Rotate { get; private set; } | |
| public double Create { get; private set; } | |
| public double Sharpen {get; private set;} | |
| public Timings(double load, double resize, double rotate, double create, double sharpen) { | |
| Load = load; | |
| Resize = resize; | |
| Rotate = rotate; | |
| Create = create; | |
| Sharpen = sharpen; | |
| } | |
| } | |
| public class ImageCreationResult { | |
| public byte[] ImageBytes { get; private set; } | |
| public Timings Timings { get; private set; } | |
| public ImageCreationResult(byte[] imageBytes, Timings timings) { | |
| ImageBytes = imageBytes; | |
| Timings = timings; | |
| } | |
| } | |
| public class ImageCreator { | |
| public data.Image Original { get; private set; } | |
| public ImageSpecification Spec { get; private set; } | |
| public ImageCreator(data.Image original, ImageSpecification spec) { | |
| Original = original; | |
| Spec = spec; | |
| } | |
| private Bitmap Load() { | |
| return (Bitmap)Image.FromFile(Original.FullPath); | |
| } | |
| private Bitmap Resize(Bitmap source) { | |
| return (Bitmap)ImageTools.Resize(source, Color.White, Spec.Width, Spec.Height, 1.0); | |
| } | |
| private void Rotate(Bitmap image) { | |
| if (Original.Angle.Value != 0) { | |
| RotateFlipType type; | |
| switch (Original.Angle.Value) { | |
| case 1: | |
| type = RotateFlipType.Rotate90FlipNone; | |
| break; | |
| case 2: | |
| type = RotateFlipType.Rotate180FlipNone; | |
| break; | |
| case 3: | |
| type = RotateFlipType.Rotate270FlipNone; | |
| break; | |
| default: | |
| throw new NotImplementedException(); | |
| } | |
| image.RotateFlip(type); | |
| } | |
| } | |
| public ImageCreationResult Create() { | |
| double load, resize, rotate = 0, create, sharpen; | |
| byte[] imageBytes = null; | |
| using (Bitmap source = Time(() => { return Load(); }, out load)) { | |
| using (Bitmap result = Time(() => { return Resize(source); }, out resize)) { | |
| Time(() => { | |
| Rotate(result); | |
| }, out rotate); | |
| Time(() => { | |
| ImageTools.Sharpen(result, Spec.Sharpen, false); | |
| }, out sharpen); | |
| Time(() => { | |
| imageBytes = ImageTools.CreateJpeg(result, Spec.Quality); | |
| }, out create); | |
| } | |
| } | |
| Timings t = new Timings(load, resize, rotate, create, sharpen); | |
| return new ImageCreationResult(imageBytes, t); | |
| } | |
| public static byte[] ImageMessage(string message) { | |
| using (Bitmap image = new Bitmap(500, 200)) { | |
| using (Graphics g = Graphics.FromImage(image)) { | |
| g.Clear(Color.White); | |
| using (Font font = new Font("Arial", 10)) { | |
| g.DrawString(message, font, Brushes.Black, 5, 5); | |
| } | |
| } | |
| using (MemoryStream m = new MemoryStream()) { | |
| image.Save(m, ImageFormat.Jpeg); | |
| return m.ToArray(); | |
| } | |
| } | |
| } | |
| private T Time<T>(Func<T> func, out double timing) { | |
| Stopwatch sw = Stopwatch.StartNew(); | |
| T r = func(); | |
| sw.Stop(); | |
| timing = Math.Round(1000.0 * (double)sw.ElapsedTicks / (double)Stopwatch.Frequency, 3); | |
| return r; | |
| } | |
| private void Time(Action action, out double timing) { | |
| Stopwatch sw = Stopwatch.StartNew(); | |
| action(); | |
| sw.Stop(); | |
| timing = Math.Round(1000.0 * (double)sw.ElapsedTicks / (double)Stopwatch.Frequency, 3); | |
| } | |
| } | |
| public class ImageStore { | |
| public byte[] Get(UserIdentity user, int imageId, string size) { | |
| ImageCreator creator = null; | |
| ImageCreationResult result = null; | |
| using (ConnectionProvider db = new ConnectionProvider()) { | |
| Result<data.Image> imageResult = data.Image.Get(user, db, imageId); | |
| if (imageResult.Ok) { | |
| data.Image img = imageResult.Value; | |
| var spec = new ImageSpecification(size); | |
| if (spec.Height == 0) { | |
| spec.NormalizeHeight(img.Height / img.Width); | |
| } | |
| creator = new ImageCreator(img, spec); | |
| result = creator.Create(); | |
| return result.ImageBytes; | |
| } else { | |
| return ImageCreator.ImageMessage(imageResult.GetErrors()); | |
| } | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment