GIT: perform LF normalization
This commit is contained in:
+70
-70
@@ -1,70 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.BI.Expressions;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
using Disco.BI.Extensions;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions.ImageResultImplementations
|
||||
{
|
||||
public abstract class BaseImageExpressionResult : IImageExpressionResult
|
||||
{
|
||||
public byte Quality { get; set; }
|
||||
public bool LosslessFormat { get; set; }
|
||||
public bool ShowField { get; set; }
|
||||
public string BackgroundColour { get; set; }
|
||||
public bool BackgroundPreferTransparent { get; set; }
|
||||
|
||||
public BaseImageExpressionResult()
|
||||
{
|
||||
this.LosslessFormat = false;
|
||||
this.Quality = 90;
|
||||
this.ShowField = false;
|
||||
this.BackgroundPreferTransparent = true;
|
||||
}
|
||||
|
||||
public abstract Stream GetImage(int Width, int Height);
|
||||
|
||||
protected Stream RenderImage(Image SourceImage, int Width, int Height)
|
||||
{
|
||||
if (SourceImage == null)
|
||||
throw new ArgumentNullException("SourceImage");
|
||||
if (Width <= 0)
|
||||
throw new ArgumentOutOfRangeException("Width", "Width must be > 0");
|
||||
if (Height <= 0)
|
||||
throw new ArgumentOutOfRangeException("Height", "Height must be > 0");
|
||||
|
||||
Brush backgroundBrush = null;
|
||||
if (!LosslessFormat || !BackgroundPreferTransparent)
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.BackgroundColour))
|
||||
backgroundBrush = Brushes.White;
|
||||
else
|
||||
backgroundBrush = new SolidBrush(ColorTranslator.FromHtml(this.BackgroundColour));
|
||||
}
|
||||
|
||||
using (Image resizedImage = SourceImage.ResizeImage(Width, Height, backgroundBrush))
|
||||
{
|
||||
return OutputImage(resizedImage);
|
||||
}
|
||||
}
|
||||
|
||||
protected Stream OutputImage(Image SourceImage)
|
||||
{
|
||||
MemoryStream imageStream = new MemoryStream();
|
||||
if (LosslessFormat)
|
||||
{ // Lossless Format - PNG
|
||||
SourceImage.SavePng(imageStream);
|
||||
}
|
||||
else
|
||||
{ // Lossy Format - JPG
|
||||
byte quality = Math.Min((byte)100, Math.Max((byte)1, this.Quality));
|
||||
SourceImage.SaveJpg(quality, imageStream);
|
||||
}
|
||||
imageStream.Position = 0;
|
||||
return imageStream;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.BI.Expressions;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
using Disco.BI.Extensions;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions.ImageResultImplementations
|
||||
{
|
||||
public abstract class BaseImageExpressionResult : IImageExpressionResult
|
||||
{
|
||||
public byte Quality { get; set; }
|
||||
public bool LosslessFormat { get; set; }
|
||||
public bool ShowField { get; set; }
|
||||
public string BackgroundColour { get; set; }
|
||||
public bool BackgroundPreferTransparent { get; set; }
|
||||
|
||||
public BaseImageExpressionResult()
|
||||
{
|
||||
this.LosslessFormat = false;
|
||||
this.Quality = 90;
|
||||
this.ShowField = false;
|
||||
this.BackgroundPreferTransparent = true;
|
||||
}
|
||||
|
||||
public abstract Stream GetImage(int Width, int Height);
|
||||
|
||||
protected Stream RenderImage(Image SourceImage, int Width, int Height)
|
||||
{
|
||||
if (SourceImage == null)
|
||||
throw new ArgumentNullException("SourceImage");
|
||||
if (Width <= 0)
|
||||
throw new ArgumentOutOfRangeException("Width", "Width must be > 0");
|
||||
if (Height <= 0)
|
||||
throw new ArgumentOutOfRangeException("Height", "Height must be > 0");
|
||||
|
||||
Brush backgroundBrush = null;
|
||||
if (!LosslessFormat || !BackgroundPreferTransparent)
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.BackgroundColour))
|
||||
backgroundBrush = Brushes.White;
|
||||
else
|
||||
backgroundBrush = new SolidBrush(ColorTranslator.FromHtml(this.BackgroundColour));
|
||||
}
|
||||
|
||||
using (Image resizedImage = SourceImage.ResizeImage(Width, Height, backgroundBrush))
|
||||
{
|
||||
return OutputImage(resizedImage);
|
||||
}
|
||||
}
|
||||
|
||||
protected Stream OutputImage(Image SourceImage)
|
||||
{
|
||||
MemoryStream imageStream = new MemoryStream();
|
||||
if (LosslessFormat)
|
||||
{ // Lossless Format - PNG
|
||||
SourceImage.SavePng(imageStream);
|
||||
}
|
||||
else
|
||||
{ // Lossy Format - JPG
|
||||
byte quality = Math.Min((byte)100, Math.Max((byte)1, this.Quality));
|
||||
SourceImage.SaveJpg(quality, imageStream);
|
||||
}
|
||||
imageStream.Position = 0;
|
||||
return imageStream;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-27
@@ -1,27 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions.ImageResultImplementations
|
||||
{
|
||||
public class BitmapImageExpressionResult : BaseImageExpressionResult
|
||||
{
|
||||
public Image Image { get; set; }
|
||||
|
||||
public BitmapImageExpressionResult(Image Image)
|
||||
{
|
||||
if (Image == null)
|
||||
throw new ArgumentNullException("Image");
|
||||
|
||||
this.Image = Image;
|
||||
}
|
||||
|
||||
public override Stream GetImage(int Width, int Height)
|
||||
{
|
||||
return this.RenderImage(this.Image, Width, Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions.ImageResultImplementations
|
||||
{
|
||||
public class BitmapImageExpressionResult : BaseImageExpressionResult
|
||||
{
|
||||
public Image Image { get; set; }
|
||||
|
||||
public BitmapImageExpressionResult(Image Image)
|
||||
{
|
||||
if (Image == null)
|
||||
throw new ArgumentNullException("Image");
|
||||
|
||||
this.Image = Image;
|
||||
}
|
||||
|
||||
public override Stream GetImage(int Width, int Height)
|
||||
{
|
||||
return this.RenderImage(this.Image, Width, Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+32
-32
@@ -1,32 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions.ImageResultImplementations
|
||||
{
|
||||
public class FileImageExpressionResult : BaseImageExpressionResult
|
||||
{
|
||||
public string AbsoluteFilePath { get; set; }
|
||||
|
||||
public FileImageExpressionResult(string AbsoluteFilePath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(AbsoluteFilePath))
|
||||
throw new ArgumentNullException("AbsoluteFilePath");
|
||||
if (!File.Exists(AbsoluteFilePath))
|
||||
throw new FileNotFoundException("Image not found", AbsoluteFilePath);
|
||||
|
||||
this.AbsoluteFilePath = AbsoluteFilePath;
|
||||
}
|
||||
|
||||
public override Stream GetImage(int Width, int Height)
|
||||
{
|
||||
using (Image SourceImage = Bitmap.FromFile(this.AbsoluteFilePath))
|
||||
{
|
||||
return this.RenderImage(SourceImage, Width, Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions.ImageResultImplementations
|
||||
{
|
||||
public class FileImageExpressionResult : BaseImageExpressionResult
|
||||
{
|
||||
public string AbsoluteFilePath { get; set; }
|
||||
|
||||
public FileImageExpressionResult(string AbsoluteFilePath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(AbsoluteFilePath))
|
||||
throw new ArgumentNullException("AbsoluteFilePath");
|
||||
if (!File.Exists(AbsoluteFilePath))
|
||||
throw new FileNotFoundException("Image not found", AbsoluteFilePath);
|
||||
|
||||
this.AbsoluteFilePath = AbsoluteFilePath;
|
||||
}
|
||||
|
||||
public override Stream GetImage(int Width, int Height)
|
||||
{
|
||||
using (Image SourceImage = Bitmap.FromFile(this.AbsoluteFilePath))
|
||||
{
|
||||
return this.RenderImage(SourceImage, Width, Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+181
-181
@@ -1,181 +1,181 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using Disco.BI.Extensions;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions.ImageResultImplementations
|
||||
{
|
||||
public class FileMontageImageExpressionResult : BaseImageExpressionResult
|
||||
{
|
||||
public List<string> AbsoluteFilePaths { get; set; }
|
||||
public bool MontageHorizontalLayout { get; set; }
|
||||
public bool MontageVerticalLayout { get; set; }
|
||||
public bool MontageTableLayout { get; set; }
|
||||
public int Padding { get; set; }
|
||||
|
||||
public FileMontageImageExpressionResult(List<string> AbsoluteFilePaths)
|
||||
{
|
||||
if (AbsoluteFilePaths == null)
|
||||
throw new ArgumentNullException("AbsoluteFilePaths");
|
||||
if (AbsoluteFilePaths.Count == 0)
|
||||
throw new ArgumentException("AbsoluteFilePaths is empty", "AbsoluteFilePaths");
|
||||
|
||||
this.AbsoluteFilePaths = AbsoluteFilePaths;
|
||||
this.MontageTableLayout = true;
|
||||
this.Padding = 4;
|
||||
}
|
||||
|
||||
public override Stream GetImage(int Width, int Height)
|
||||
{
|
||||
List<Image> Images = new List<Image>();
|
||||
try
|
||||
{
|
||||
// Load Images
|
||||
foreach (string imageFilePath in this.AbsoluteFilePaths)
|
||||
Images.Add(Bitmap.FromFile(imageFilePath));
|
||||
|
||||
// Build Montage
|
||||
using (Bitmap montageImage = new Bitmap(Width, Height))
|
||||
{
|
||||
using (Graphics montageGraphics = Graphics.FromImage(montageImage))
|
||||
{
|
||||
montageGraphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
montageGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
montageGraphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
|
||||
// Draw Background
|
||||
if (!LosslessFormat || !BackgroundPreferTransparent)
|
||||
{
|
||||
Brush backgroundBrush = Brushes.White;
|
||||
if (!string.IsNullOrEmpty(this.BackgroundColour))
|
||||
backgroundBrush = new SolidBrush(ColorTranslator.FromHtml(this.BackgroundColour));
|
||||
montageGraphics.FillRectangle(backgroundBrush, montageGraphics.VisibleClipBounds);
|
||||
}
|
||||
|
||||
if (this.MontageHorizontalLayout)
|
||||
DoHorizontalLayout(Images, montageGraphics);
|
||||
else
|
||||
if (this.MontageVerticalLayout)
|
||||
DoVirticalLayout(Images, montageGraphics);
|
||||
else
|
||||
DoTableLayout(Images, montageGraphics);
|
||||
}
|
||||
|
||||
return this.OutputImage(montageImage);
|
||||
}
|
||||
}
|
||||
catch (Exception) { throw; }
|
||||
finally
|
||||
{
|
||||
// Dispose of any Images
|
||||
if (Images != null)
|
||||
foreach (Image i in Images)
|
||||
i.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void DoHorizontalLayout(List<Image> Images, Graphics MontageGraphics)
|
||||
{
|
||||
|
||||
float imageScale;
|
||||
float imagePosition = 0;
|
||||
int imagesWidthTotal = Images.Sum(i => i.Width);
|
||||
int imagesHeightMax = Images.Max(i => i.Height);
|
||||
int imagesPadding = ((Images.Count - 1) * this.Padding);
|
||||
|
||||
imageScale = (float)(MontageGraphics.VisibleClipBounds.Width - imagesPadding) / (float)imagesWidthTotal;
|
||||
if ((MontageGraphics.VisibleClipBounds.Height / (float)imagesHeightMax) < imageScale)
|
||||
imageScale = (float)MontageGraphics.VisibleClipBounds.Height / (float)imagesHeightMax;
|
||||
foreach (Image image in Images)
|
||||
{
|
||||
MontageGraphics.DrawImageResized(image, imageScale, imagePosition, 0);
|
||||
imagePosition += (imageScale * image.Width) + this.Padding;
|
||||
}
|
||||
}
|
||||
private void DoVirticalLayout(List<Image> Images, Graphics MontageGraphics)
|
||||
{
|
||||
float imageScale;
|
||||
float imagePosition = 0;
|
||||
int imagesWidthMax = Images.Max(i => i.Width);
|
||||
int imagesHeightTotal = Images.Sum(i => i.Height);
|
||||
int imagesPadding = ((Images.Count - 1) * this.Padding);
|
||||
|
||||
imageScale = (float)(MontageGraphics.VisibleClipBounds.Height - imagesPadding) / (float)imagesHeightTotal;
|
||||
if ((MontageGraphics.VisibleClipBounds.Width / (float)imagesWidthMax) < imageScale)
|
||||
imageScale = (float)MontageGraphics.VisibleClipBounds.Width / (float)imagesWidthMax;
|
||||
foreach (Image image in Images)
|
||||
{
|
||||
MontageGraphics.DrawImageResized(image, imageScale, 0, imagePosition);
|
||||
imagePosition += (imageScale * image.Height) + this.Padding;
|
||||
}
|
||||
}
|
||||
private void DoTableLayout(List<Image> Images, Graphics MontageGraphics)
|
||||
{
|
||||
var stageSize = MontageGraphics.VisibleClipBounds.Size.ToSize();
|
||||
var itemAverageSize = new SizeF(Images.Average(i => (float)i.Size.Width), Images.Average(i => (float)i.Size.Height));
|
||||
|
||||
var calculatedLayout = CalculateColumnCount(stageSize, itemAverageSize, Images.Count);
|
||||
|
||||
SizeF cellSize = new SizeF((MontageGraphics.VisibleClipBounds.Width - ((calculatedLayout.Item1 - 1) * this.Padding)) / calculatedLayout.Item1,
|
||||
(MontageGraphics.VisibleClipBounds.Height - ((calculatedLayout.Item2 - 1) * this.Padding)) / calculatedLayout.Item2);
|
||||
|
||||
int imageIndex = 0;
|
||||
for (int rowIndex = 0; rowIndex < calculatedLayout.Item2; rowIndex++)
|
||||
{
|
||||
for (int columnIndex = 0; columnIndex < calculatedLayout.Item1; columnIndex++)
|
||||
{
|
||||
if (imageIndex < Images.Count)
|
||||
{
|
||||
var image = Images[imageIndex];
|
||||
var cellPoint = new PointF((cellSize.Width * columnIndex) + (this.Padding * columnIndex), (cellSize.Height * rowIndex) + (this.Padding * rowIndex));
|
||||
MontageGraphics.Clip = new Region(new RectangleF(cellPoint, cellSize));
|
||||
MontageGraphics.DrawImageResized(image);
|
||||
imageIndex++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Tuple<int, int, double> CalculateColumnCount(Size StageSize, SizeF ItemAverageSize, int ItemCount)
|
||||
{
|
||||
double? bestUsedSpace = null;
|
||||
int bestColumnCount = 1;
|
||||
int bestRowCount = 1;
|
||||
double bestItemRatio = 1;
|
||||
|
||||
for (int columnCount = 1; columnCount <= ItemCount; columnCount++)
|
||||
{
|
||||
int rowCount = (int)Math.Ceiling((double)ItemCount / (double)columnCount);
|
||||
|
||||
int requiredWidthPadding = (columnCount - 1) * this.Padding;
|
||||
int requiredHeightPadding = (rowCount - 1) * this.Padding;
|
||||
Size usableStageSize = new Size(StageSize.Width - requiredWidthPadding, StageSize.Height - requiredHeightPadding);
|
||||
double stageWidthRatio = (float)usableStageSize.Width / (float)usableStageSize.Height;
|
||||
double stageHeightRatio = (float)usableStageSize.Height / (float)usableStageSize.Width;
|
||||
|
||||
int requiredWidth = (int)Math.Ceiling(ItemAverageSize.Width * columnCount);
|
||||
int requiredHeight = (int)Math.Ceiling(ItemAverageSize.Height * rowCount);
|
||||
|
||||
int usedSpace = requiredWidth * requiredHeight;
|
||||
int stageArea = Math.Max((requiredWidth * (int)Math.Ceiling(requiredWidth * stageHeightRatio)),
|
||||
(requiredHeight * (int)Math.Ceiling(requiredHeight * stageWidthRatio)));
|
||||
double usedStageSpace = (double)usedSpace / stageArea;
|
||||
if (bestUsedSpace == null || bestUsedSpace < usedStageSpace)
|
||||
{
|
||||
bestUsedSpace = usedStageSpace;
|
||||
bestColumnCount = columnCount;
|
||||
bestRowCount = rowCount;
|
||||
bestItemRatio = Math.Min((double)usableStageSize.Width / (double)requiredWidth, (double)usableStageSize.Height / (double)requiredHeight);
|
||||
}
|
||||
}
|
||||
|
||||
return new Tuple<int, int, double>(bestColumnCount, bestRowCount, bestItemRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using Disco.BI.Extensions;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions.ImageResultImplementations
|
||||
{
|
||||
public class FileMontageImageExpressionResult : BaseImageExpressionResult
|
||||
{
|
||||
public List<string> AbsoluteFilePaths { get; set; }
|
||||
public bool MontageHorizontalLayout { get; set; }
|
||||
public bool MontageVerticalLayout { get; set; }
|
||||
public bool MontageTableLayout { get; set; }
|
||||
public int Padding { get; set; }
|
||||
|
||||
public FileMontageImageExpressionResult(List<string> AbsoluteFilePaths)
|
||||
{
|
||||
if (AbsoluteFilePaths == null)
|
||||
throw new ArgumentNullException("AbsoluteFilePaths");
|
||||
if (AbsoluteFilePaths.Count == 0)
|
||||
throw new ArgumentException("AbsoluteFilePaths is empty", "AbsoluteFilePaths");
|
||||
|
||||
this.AbsoluteFilePaths = AbsoluteFilePaths;
|
||||
this.MontageTableLayout = true;
|
||||
this.Padding = 4;
|
||||
}
|
||||
|
||||
public override Stream GetImage(int Width, int Height)
|
||||
{
|
||||
List<Image> Images = new List<Image>();
|
||||
try
|
||||
{
|
||||
// Load Images
|
||||
foreach (string imageFilePath in this.AbsoluteFilePaths)
|
||||
Images.Add(Bitmap.FromFile(imageFilePath));
|
||||
|
||||
// Build Montage
|
||||
using (Bitmap montageImage = new Bitmap(Width, Height))
|
||||
{
|
||||
using (Graphics montageGraphics = Graphics.FromImage(montageImage))
|
||||
{
|
||||
montageGraphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
montageGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
montageGraphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
|
||||
// Draw Background
|
||||
if (!LosslessFormat || !BackgroundPreferTransparent)
|
||||
{
|
||||
Brush backgroundBrush = Brushes.White;
|
||||
if (!string.IsNullOrEmpty(this.BackgroundColour))
|
||||
backgroundBrush = new SolidBrush(ColorTranslator.FromHtml(this.BackgroundColour));
|
||||
montageGraphics.FillRectangle(backgroundBrush, montageGraphics.VisibleClipBounds);
|
||||
}
|
||||
|
||||
if (this.MontageHorizontalLayout)
|
||||
DoHorizontalLayout(Images, montageGraphics);
|
||||
else
|
||||
if (this.MontageVerticalLayout)
|
||||
DoVirticalLayout(Images, montageGraphics);
|
||||
else
|
||||
DoTableLayout(Images, montageGraphics);
|
||||
}
|
||||
|
||||
return this.OutputImage(montageImage);
|
||||
}
|
||||
}
|
||||
catch (Exception) { throw; }
|
||||
finally
|
||||
{
|
||||
// Dispose of any Images
|
||||
if (Images != null)
|
||||
foreach (Image i in Images)
|
||||
i.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void DoHorizontalLayout(List<Image> Images, Graphics MontageGraphics)
|
||||
{
|
||||
|
||||
float imageScale;
|
||||
float imagePosition = 0;
|
||||
int imagesWidthTotal = Images.Sum(i => i.Width);
|
||||
int imagesHeightMax = Images.Max(i => i.Height);
|
||||
int imagesPadding = ((Images.Count - 1) * this.Padding);
|
||||
|
||||
imageScale = (float)(MontageGraphics.VisibleClipBounds.Width - imagesPadding) / (float)imagesWidthTotal;
|
||||
if ((MontageGraphics.VisibleClipBounds.Height / (float)imagesHeightMax) < imageScale)
|
||||
imageScale = (float)MontageGraphics.VisibleClipBounds.Height / (float)imagesHeightMax;
|
||||
foreach (Image image in Images)
|
||||
{
|
||||
MontageGraphics.DrawImageResized(image, imageScale, imagePosition, 0);
|
||||
imagePosition += (imageScale * image.Width) + this.Padding;
|
||||
}
|
||||
}
|
||||
private void DoVirticalLayout(List<Image> Images, Graphics MontageGraphics)
|
||||
{
|
||||
float imageScale;
|
||||
float imagePosition = 0;
|
||||
int imagesWidthMax = Images.Max(i => i.Width);
|
||||
int imagesHeightTotal = Images.Sum(i => i.Height);
|
||||
int imagesPadding = ((Images.Count - 1) * this.Padding);
|
||||
|
||||
imageScale = (float)(MontageGraphics.VisibleClipBounds.Height - imagesPadding) / (float)imagesHeightTotal;
|
||||
if ((MontageGraphics.VisibleClipBounds.Width / (float)imagesWidthMax) < imageScale)
|
||||
imageScale = (float)MontageGraphics.VisibleClipBounds.Width / (float)imagesWidthMax;
|
||||
foreach (Image image in Images)
|
||||
{
|
||||
MontageGraphics.DrawImageResized(image, imageScale, 0, imagePosition);
|
||||
imagePosition += (imageScale * image.Height) + this.Padding;
|
||||
}
|
||||
}
|
||||
private void DoTableLayout(List<Image> Images, Graphics MontageGraphics)
|
||||
{
|
||||
var stageSize = MontageGraphics.VisibleClipBounds.Size.ToSize();
|
||||
var itemAverageSize = new SizeF(Images.Average(i => (float)i.Size.Width), Images.Average(i => (float)i.Size.Height));
|
||||
|
||||
var calculatedLayout = CalculateColumnCount(stageSize, itemAverageSize, Images.Count);
|
||||
|
||||
SizeF cellSize = new SizeF((MontageGraphics.VisibleClipBounds.Width - ((calculatedLayout.Item1 - 1) * this.Padding)) / calculatedLayout.Item1,
|
||||
(MontageGraphics.VisibleClipBounds.Height - ((calculatedLayout.Item2 - 1) * this.Padding)) / calculatedLayout.Item2);
|
||||
|
||||
int imageIndex = 0;
|
||||
for (int rowIndex = 0; rowIndex < calculatedLayout.Item2; rowIndex++)
|
||||
{
|
||||
for (int columnIndex = 0; columnIndex < calculatedLayout.Item1; columnIndex++)
|
||||
{
|
||||
if (imageIndex < Images.Count)
|
||||
{
|
||||
var image = Images[imageIndex];
|
||||
var cellPoint = new PointF((cellSize.Width * columnIndex) + (this.Padding * columnIndex), (cellSize.Height * rowIndex) + (this.Padding * rowIndex));
|
||||
MontageGraphics.Clip = new Region(new RectangleF(cellPoint, cellSize));
|
||||
MontageGraphics.DrawImageResized(image);
|
||||
imageIndex++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Tuple<int, int, double> CalculateColumnCount(Size StageSize, SizeF ItemAverageSize, int ItemCount)
|
||||
{
|
||||
double? bestUsedSpace = null;
|
||||
int bestColumnCount = 1;
|
||||
int bestRowCount = 1;
|
||||
double bestItemRatio = 1;
|
||||
|
||||
for (int columnCount = 1; columnCount <= ItemCount; columnCount++)
|
||||
{
|
||||
int rowCount = (int)Math.Ceiling((double)ItemCount / (double)columnCount);
|
||||
|
||||
int requiredWidthPadding = (columnCount - 1) * this.Padding;
|
||||
int requiredHeightPadding = (rowCount - 1) * this.Padding;
|
||||
Size usableStageSize = new Size(StageSize.Width - requiredWidthPadding, StageSize.Height - requiredHeightPadding);
|
||||
double stageWidthRatio = (float)usableStageSize.Width / (float)usableStageSize.Height;
|
||||
double stageHeightRatio = (float)usableStageSize.Height / (float)usableStageSize.Width;
|
||||
|
||||
int requiredWidth = (int)Math.Ceiling(ItemAverageSize.Width * columnCount);
|
||||
int requiredHeight = (int)Math.Ceiling(ItemAverageSize.Height * rowCount);
|
||||
|
||||
int usedSpace = requiredWidth * requiredHeight;
|
||||
int stageArea = Math.Max((requiredWidth * (int)Math.Ceiling(requiredWidth * stageHeightRatio)),
|
||||
(requiredHeight * (int)Math.Ceiling(requiredHeight * stageWidthRatio)));
|
||||
double usedStageSpace = (double)usedSpace / stageArea;
|
||||
if (bestUsedSpace == null || bestUsedSpace < usedStageSpace)
|
||||
{
|
||||
bestUsedSpace = usedStageSpace;
|
||||
bestColumnCount = columnCount;
|
||||
bestRowCount = rowCount;
|
||||
bestItemRatio = Math.Min((double)usableStageSize.Width / (double)requiredWidth, (double)usableStageSize.Height / (double)requiredHeight);
|
||||
}
|
||||
}
|
||||
|
||||
return new Tuple<int, int, double>(bestColumnCount, bestRowCount, bestItemRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user