andrew4582

MultiThumbnailGenerator

Feb 10th, 2013
196
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.82 KB | None | 0 0
  1. using System;
  2. using System.Drawing;
  3. using System.Drawing.Drawing2D;
  4. using System.IO;
  5.  
  6. public class MultiThumbnailGenerator : IDisposable {
  7.     /* common variables */
  8.     private static int imageDimension = 200;
  9.     private static float maxMultiplier = 0.7f;
  10.     private static float maxDimension = (float)imageDimension * maxMultiplier;
  11.     private static float thinLineWidth = 0.6f;
  12.     private static float thickLineWidth = 2.0f;
  13.     private static float maxAngle = 25f;
  14.  
  15.     /* instance variables */
  16.     private Random random = new Random();
  17.     private Bitmap surfaceBitmap = new Bitmap(imageDimension, imageDimension);
  18.     private Graphics surfaceGraphics;
  19.     private RectangleF? surfaceBounds;
  20.  
  21.     public MultiThumbnailGenerator() {
  22.         surfaceGraphics = Graphics.FromImage(surfaceBitmap);
  23.         surfaceGraphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
  24.         surfaceGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
  25.     }
  26.  
  27.     public void AddImage(Image image) {
  28.         // scale image
  29.         float widthMultiplier = maxDimension / (float)image.Width;
  30.         float heightMultiplier = maxDimension / (float)image.Height;
  31.         float minMultiplier = Math.Min(Math.Min(widthMultiplier, heightMultiplier), 1f);
  32.         float newWidth = minMultiplier * (float)image.Width;
  33.         float newHeight = minMultiplier * (float)image.Height;
  34.  
  35.         // choose a random translation & rotation
  36.         float angle = GetRandomAngle();
  37.         PointF newDimensions = RotateAndFindNewDimensions(new PointF(newWidth, newHeight), angle);
  38.         PointF offset = GetRandomOffset(newDimensions);
  39.         surfaceGraphics.TranslateTransform(offset.X, offset.Y);
  40.         surfaceGraphics.RotateTransform(angle);
  41.  
  42.         // draw borders + image
  43.         DrawRectangle(Brushes.White, newWidth, newHeight, thickLineWidth);
  44.         DrawRectangle(Brushes.Black, newWidth, newHeight, thinLineWidth);
  45.         surfaceGraphics.DrawImage(image, -newWidth / 2f, -newHeight / 2f, newWidth, newHeight);
  46.  
  47.         // calculate new image boundaries
  48.         RectangleF newBounds = new RectangleF(
  49.             offset.X - newDimensions.X / 2f,
  50.             offset.Y - newDimensions.Y / 2f,
  51.             newDimensions.X,
  52.             newDimensions.Y);
  53.  
  54.         if (surfaceBounds.HasValue) {
  55.             surfaceBounds = Union(surfaceBounds.Value, newBounds);
  56.         } else {
  57.             surfaceBounds = newBounds;
  58.         }
  59.  
  60.         surfaceGraphics.ResetTransform();
  61.     }
  62.  
  63.     private void DrawRectangle(Brush brush, float width, float height, float lineWidth) {
  64.         surfaceGraphics.FillRectangle(brush,
  65.             -width / 2f - lineWidth,
  66.             -height / 2f - lineWidth,
  67.             width + 2f * lineWidth,
  68.             height + 2f * lineWidth);
  69.     }
  70.  
  71.     private static PointF RotateAndFindNewDimensions(PointF point, float angle) {
  72.         using (Matrix matrix = new Matrix()) {
  73.             PointF[] points = new PointF[] {
  74.                     new PointF(0f, 0f),
  75.                     new PointF(0f, point.Y),
  76.                     new PointF(point.X, 0f),
  77.                     new PointF(point.X, point.Y)
  78.                 };
  79.  
  80.             matrix.Rotate(angle);
  81.             matrix.TransformPoints(points);
  82.             float minX = points[0].X;
  83.             float maxX = minX;
  84.             float minY = points[0].Y;
  85.             float maxY = minY;
  86.             for (int i = 1; i < 4; i++) {
  87.                 minX = Math.Min(minX, points[i].X);
  88.                 maxX = Math.Max(maxX, points[i].X);
  89.                 minY = Math.Min(minY, points[i].Y);
  90.                 maxY = Math.Max(maxY, points[i].Y);
  91.             }
  92.  
  93.             return new PointF(maxX - minX, maxY - minY);
  94.         }
  95.     }
  96.  
  97.     private static RectangleF Union(RectangleF oldBounds, RectangleF newBounds) {
  98.         float left = Math.Min(oldBounds.Left, newBounds.Left);
  99.         float top = Math.Min(oldBounds.Top, newBounds.Top);
  100.         float right = Math.Max(oldBounds.Right, newBounds.Right);
  101.         float bottom = Math.Max(oldBounds.Bottom, newBounds.Bottom);
  102.         return new RectangleF(left, top, right - left, bottom - top);
  103.     }
  104.  
  105.     private float GetRandomAngle() {
  106.         float r = (float)random.NextDouble();
  107.         return (r * 2f - 1f) * maxAngle;
  108.     }
  109.  
  110.     private PointF GetRandomOffset(PointF dimensions) {
  111.         float deltaX = (float)imageDimension - dimensions.X - 2f * (thinLineWidth + 1f);
  112.         float deltaY = (float)imageDimension - dimensions.Y - 2f * (thinLineWidth + 1f);
  113.  
  114.         float rX = (float)random.NextDouble();
  115.         float rY = (float)random.NextDouble();
  116.  
  117.         float newX = (deltaX * rX) + (dimensions.X / 2f) + thinLineWidth + 1f;
  118.         float newY = (deltaY * rY) + (dimensions.Y / 2f) + thinLineWidth + 1f;
  119.  
  120.         return new PointF(newX, newY);
  121.     }
  122.  
  123.     public void Dispose() {
  124.         surfaceGraphics.Dispose();
  125.         surfaceBitmap.Dispose();
  126.     }
  127.  
  128.     public void WritePngToStream(Stream outStream) {
  129.         using (Bitmap outBitmap = new Bitmap(imageDimension, imageDimension)) {
  130.             using (Graphics outGraphics = Graphics.FromImage(outBitmap)) {
  131.  
  132.                 outGraphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
  133.                 outGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
  134.  
  135.                 // center the image
  136.                 RectangleF bounds = surfaceBounds ?? new RectangleF();
  137.                 float deltaX = (imageDimension - bounds.Width) / 2f - bounds.Left;
  138.                 float deltaY = (imageDimension - bounds.Height) / 2f - bounds.Top;
  139.                 outGraphics.DrawImage(surfaceBitmap, new PointF(deltaX, deltaY));
  140.  
  141.                 outBitmap.Save(outStream, System.Drawing.Imaging.ImageFormat.Png);
  142.             }
  143.         }
  144.     }
  145.  
  146. }
Add Comment
Please, Sign In to add comment