andrew4582

MultiThumbnailGenerator Version 2.0

Mar 17th, 2013
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.62 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Drawing;
  6. using System.Drawing.Drawing2D;
  7. using System.IO;
  8. using System.Diagnostics;
  9.  
  10. namespace ThumbNailAttrSpike
  11. {
  12.     public class MultiThumbnailGenerator : IDisposable
  13.     {
  14.         /* common variables */
  15.         readonly static int imageDimensionDefault = 600;
  16.         readonly static float maxMultiplier = 0.7f;
  17.         readonly static float thinLineWidth = 0.0f; //0.6f
  18.         readonly static float thickLineWidth = 0.0f;//2.0f;
  19.         readonly static float maxAngle = 5f;
  20.         readonly static float offsetRatio = 2.5f;
  21.         readonly static Brush thinBrush = Brushes.Black;
  22.         readonly static Brush thickBrush = Brushes.White;
  23.         readonly static float sequenceOffsetRatio = 20f;
  24.  
  25.         /* instance variables */
  26.         readonly bool randomizeOffset;
  27.         readonly bool adjustImageAngles;
  28.         readonly int imageDimension;
  29.         readonly float maxDimension;
  30.  
  31.         readonly Random random = new Random();
  32.         readonly Bitmap surfaceBitmap;
  33.         readonly Graphics surfaceGraphics;
  34.         private RectangleF? surfaceBounds;
  35.         private int imagesCount;
  36.  
  37.         public MultiThumbnailGenerator(bool randomizeImageOffset = false, bool angleImages = false)
  38.             : this(imageDimensionDefault, randomizeImageOffset, angleImages)
  39.         {
  40.         }
  41.  
  42.         public MultiThumbnailGenerator(int imageDimensions, bool randomizeImageOffset, bool angleImages)
  43.         {
  44.             imageDimension = imageDimensions;
  45.             maxDimension = (float)imageDimension * maxMultiplier;
  46.             randomizeOffset = randomizeImageOffset;
  47.             adjustImageAngles = angleImages;
  48.             surfaceBitmap = new Bitmap(imageDimension, imageDimension);
  49.             surfaceGraphics = Graphics.FromImage(surfaceBitmap);
  50.             surfaceGraphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
  51.             surfaceGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
  52.         }
  53.  
  54.         public void AddImage(Image image)
  55.         {
  56.             imagesCount++;
  57.             // scale image
  58.             float widthMultiplier = maxDimension / (float)image.Width;
  59.             float heightMultiplier = maxDimension / (float)image.Height;
  60.             float minMultiplier = Math.Min(Math.Min(widthMultiplier, heightMultiplier), 1f);
  61.             float newWidth = minMultiplier * (float)image.Width;
  62.             float newHeight = minMultiplier * (float)image.Height;
  63.  
  64.             // choose a random translation & rotation
  65.             float angle = 0f;
  66.             if (adjustImageAngles)
  67.                 angle = GetRandomAngle();
  68.  
  69.             PointF newDimensions = RotateAndFindNewDimensions(new PointF(newWidth, newHeight), angle);
  70.             PointF offset = GetOffset(newDimensions);
  71.  
  72.             surfaceGraphics.TranslateTransform(offset.X, offset.Y);
  73.             surfaceGraphics.RotateTransform(angle);
  74.  
  75.             // draw borders + image
  76.             if (thickLineWidth > 0f || thinLineWidth > 0f)
  77.             {
  78.                 DrawRectangle(thickBrush, newWidth, newHeight, thickLineWidth);
  79.                 DrawRectangle(thinBrush, newWidth, newHeight, thinLineWidth);
  80.             }
  81.             else
  82.             {
  83.                 DrawRectangle(Brushes.Transparent, newWidth, newHeight, 0.6f);
  84.             }
  85.             surfaceGraphics.DrawImage(image, -newWidth / 2f, -newHeight / 2f, newWidth, newHeight);
  86.  
  87.             // calculate new image boundaries
  88.             RectangleF newBounds = new RectangleF(
  89.                 offset.X - newDimensions.X / 2f,
  90.                 offset.Y - newDimensions.Y / 2f,
  91.                 newDimensions.X,
  92.                 newDimensions.Y);
  93.  
  94.             if (surfaceBounds.HasValue)
  95.             {
  96.                 surfaceBounds = Union(surfaceBounds.Value, newBounds);
  97.             }
  98.             else
  99.             {
  100.                 surfaceBounds = newBounds;
  101.             }
  102.  
  103.             surfaceGraphics.ResetTransform();
  104.         }
  105.  
  106.         private void DrawRectangle(Brush brush, float width, float height, float lineWidth)
  107.         {
  108.             surfaceGraphics.FillRectangle(brush,
  109.                 -width / 2f - lineWidth,
  110.                 -height / 2f - lineWidth,
  111.                 width + 2f * lineWidth,
  112.                 height + 2f * lineWidth);
  113.         }
  114.  
  115.         private static PointF RotateAndFindNewDimensions(PointF point, float angle)
  116.         {
  117.             using (Matrix matrix = new Matrix())
  118.             {
  119.                 PointF[] points = new PointF[] {
  120.                     new PointF(0f, 0f),
  121.                     new PointF(0f, point.Y),
  122.                     new PointF(point.X, 0f),
  123.                     new PointF(point.X, point.Y)
  124.                 };
  125.                 if (angle > 0f)
  126.                     matrix.Rotate(angle);
  127.  
  128.                 matrix.TransformPoints(points);
  129.  
  130.                 float minX = points[0].X;
  131.                 float maxX = minX;
  132.                 float minY = points[0].Y;
  133.                 float maxY = minY;
  134.                 for (int i = 1; i < 4; i++)
  135.                 {
  136.                     minX = Math.Min(minX, points[i].X);
  137.                     maxX = Math.Max(maxX, points[i].X);
  138.                     minY = Math.Min(minY, points[i].Y);
  139.                     maxY = Math.Max(maxY, points[i].Y);
  140.                 }
  141.  
  142.                 return new PointF(maxX - minX, maxY - minY);
  143.             }
  144.         }
  145.  
  146.         private static RectangleF Union(RectangleF oldBounds, RectangleF newBounds)
  147.         {
  148.             float left = Math.Min(oldBounds.Left, newBounds.Left);
  149.             float top = Math.Min(oldBounds.Top, newBounds.Top);
  150.             float right = Math.Max(oldBounds.Right, newBounds.Right);
  151.             float bottom = Math.Max(oldBounds.Bottom, newBounds.Bottom);
  152.             return new RectangleF(left, top, right - left, bottom - top);
  153.         }
  154.  
  155.         private float GetRandomAngle()
  156.         {
  157.             float r = (float)random.NextDouble();
  158.             return (r * 2f - 1f) * maxAngle;
  159.         }
  160.  
  161.  
  162.         private PointF GetOffset(PointF dimensions)
  163.         {
  164.             float deltaX = (float)imageDimension - dimensions.X - 2f * (thinLineWidth + 1f);
  165.             float deltaY = (float)imageDimension - dimensions.Y - 2f * (thinLineWidth + 1f);
  166.  
  167.             float rX = 0f;
  168.             float rY = 0f;
  169.             if (randomizeOffset)
  170.             {
  171.                 rX = (float)random.NextDouble() / offsetRatio;
  172.                 rY = (float)random.NextDouble() / offsetRatio;
  173.             }
  174.             else
  175.             {
  176.                 rX = .15f + ((float)imagesCount / sequenceOffsetRatio);
  177.                 rY = .15f + ((float)imagesCount / sequenceOffsetRatio);
  178.             }
  179.  
  180.             float newX = (deltaX * rX) + (dimensions.X / 2f) + thinLineWidth + 1f;
  181.             float newY = (deltaY * rY) + (dimensions.Y / 2f) + thinLineWidth + 1f;
  182.  
  183.             return new PointF(newX, newY);
  184.         }
  185.  
  186.         public void Dispose()
  187.         {
  188.             surfaceGraphics.Dispose();
  189.             surfaceBitmap.Dispose();
  190.         }
  191.  
  192.         public void WritePngToStream(Stream outStream)
  193.         {
  194.             using (Bitmap outBitmap = new Bitmap(imageDimension, imageDimension))
  195.             {
  196.                 using (Graphics outGraphics = Graphics.FromImage(outBitmap))
  197.                 {
  198.  
  199.                     outGraphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
  200.                     outGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
  201.                     // center the image
  202.                     RectangleF bounds = surfaceBounds ?? new RectangleF();
  203.                     float deltaX = (imageDimension - bounds.Width) / 2f - bounds.Left;
  204.                     float deltaY = (imageDimension - bounds.Height) / 2f - bounds.Top;
  205.                     outGraphics.DrawImage(surfaceBitmap, new PointF(deltaX, deltaY));
  206.  
  207.                     outBitmap.Save(outStream, System.Drawing.Imaging.ImageFormat.Png);
  208.                 }
  209.             }
  210.         }
  211.     }
  212. }
Advertisement
Add Comment
Please, Sign In to add comment