/// <summary> /// Initializes a new instance of the <see cref="ThumbnailGrid"/> class. /// </summary> /// <param name="layout">A <see cref="ThumbnailPageLayout"/>.</param> /// <param name="nColumns">The # of columns.</param> /// <param name="nRows">The # of rows.</param> /// <param name="thumbWidth">Thumbnail width.</param> /// <param name="thumbHeight">Thumbnail height.</param> public ThumbnailGrid(ThumbnailPageLayout layout, int nColumns, int nRows, int thumbWidth, int thumbHeight) { _layout = layout; _nColumns = nColumns; _nRows = nRows; _thumbWidth = thumbWidth; _thumbHeight = thumbHeight; }
/// <summary> /// Initializes a new instance of the <see cref="PDFPageComponent"/> class. /// </summary> public PDFPageComponent() { Pages = new ObservableCollection <IPDFPage>(); _standardPageLayout = new StandardPageLayout(this); _pageLayoutAdapters.Add(_standardPageLayout); _thumbnailPageLayout = new ThumbnailPageLayout(this); _pageLayoutAdapters.Add(_thumbnailPageLayout); }
/// <summary> /// Generates the multi-page thumbnails OBSOLETE. /// </summary> /// <param name="mediaItem">The /// <see cref="Microsoft.Expression.Encoder.MediaItem"/> to generate /// thumbnails for.</param> /// <param name="filename">The display name of the file to generate thumbs for.</param> /// <param name="outputDirectory">The output directory.</param> /// <returns>The number of thumbnails created.</returns> public int GenerateMultiThumbs(MSEEncoder.MediaItem mediaItem, string filename, string outputDirectory) { double thumbAspectRatio = TNSettings.ThumbAspectRatio; ThumbnailPageLayout container = new ThumbnailPageLayout (TNSettings); ThumbnailGrid tgrid; if (thumbAspectRatio < 1.44) tgrid = ThumbnailGrid.CreateUsingNColumns (container, TNSettings, thumbAspectRatio, true, _debug); else tgrid = ThumbnailGrid.CreateUsingNRows (container, TNSettings, thumbAspectRatio, true, _debug); container.AdjustSize (tgrid); //ThumbnailGrid tgrid = ThumbnailGrid.CreateUsingNRows (container, _maxMultiRows, _multiColumns, // aspectRatio, _mThreshold); //container.adjustWidth (tgrid.NColumns, tgrid.ThumbWidth); if (outputDirectory == null) outputDirectory = GetDirectoryName (filename); string fixedFilename = System.IO.Path.GetFileNameWithoutExtension (filename); fixedFilename = fixedFilename.Replace ("{", "("); fixedFilename = fixedFilename.Replace ("}", ")"); string outTemplate = fixedFilename + "_page{0:D4}.jpg"; int nThumbsPerPage = tgrid.NColumns * tgrid.NRows; int nThumbs = (int) ((TNSettings.End - TNSettings.Start).TotalSeconds / TNSettings.Interval.TotalSeconds) + 1; // start adjustment to make thumbnails occur at _interval seconds int nExtraStartSeconds = (int) (TNSettings.Start.TotalSeconds % TNSettings.Interval.TotalSeconds); int nStartIntervals = (int) (TNSettings.Start.TotalSeconds / TNSettings.Interval.TotalSeconds); if (nExtraStartSeconds != 0) { nThumbs++; nStartIntervals++; } int nExtraEndSeconds = (int) (TNSettings.End.TotalSeconds % TNSettings.Interval.TotalSeconds); int nEndIntervals = (int) (TNSettings.End.TotalSeconds / TNSettings.Interval.TotalSeconds); TimeSpan adjustedEnd = TNSettings.End; if (nExtraEndSeconds != 0) { nThumbs++; adjustedEnd = TNSettings.End; //adjustedEnd = new TimeSpan (0, 0, nEndIntervals * // (int) tnSettings.Interval.TotalSeconds); } int nPages = (int) ((float) nThumbs / nThumbsPerPage + 0.5); if (nPages * nThumbsPerPage < nThumbs) nPages++; string stats; if (mediaItem.OriginalVideoSize.Width != TNSettings.SrcRect.Width || mediaItem.OriginalVideoSize.Height != TNSettings.SrcRect.Height || Math.Abs ((double) mediaItem.OriginalVideoSize.Width / mediaItem.OriginalVideoSize.Height - TNSettings.ThumbAspectRatio) > 0.01) { stats = String.Format ("{0}x{1} ({2:F2}:1) [{3}x{4} ({5:F2}:1)] {6} {7}", TNSettings.SrcRect.Width, TNSettings.SrcRect.Height, TNSettings.ThumbAspectRatio, mediaItem.OriginalVideoSize.Width, mediaItem.OriginalVideoSize.Height, (double) mediaItem.OriginalVideoSize.Width / mediaItem.OriginalVideoSize.Height, //getAudioStreamStats(mediaItem), GetFileSizeString (mediaItem.MainMediaFile.FileSize), System.IO.File.GetLastWriteTime (filename).ToString ("g") ); } else { stats = String.Format ("{0}x{1} ({2:F2}:1) {3} {4}", mediaItem.OriginalVideoSize.Width, mediaItem.OriginalVideoSize.Height, TNSettings.ThumbAspectRatio, //getAudioStreamStats(mediaItem), GetFileSizeString (mediaItem.MainMediaFile.FileSize), System.IO.File.GetLastWriteTime (filename).ToString ("g") ); } THelper.Information ("Duration {0} - Generating {1} thumbs every {2} seconds on {3} pages.", mediaItem.FileDuration.ToString (@"h\:mm\:ss"), nThumbs, TNSettings.Interval.TotalSeconds, nPages); ThumbnailMultiWriter mwriter = new ThumbnailMultiWriter (this, tgrid, outputDirectory, filename, outTemplate, TNSettings.Interval, stats, mediaItem.FileDuration, nPages, TNSettings.ScaleFactor, _debug); TimeSpan currentTime = TNSettings.Start; int thumbCount = 0; if (nExtraStartSeconds != 0) { using (System.Drawing.Bitmap resized = GenerateThumbnail (mediaItem, currentTime, tgrid.ThumbWidth, tgrid.ThumbHeight, TNSettings.SrcRect)) { mwriter.Add (resized, currentTime, 0, TimeSpan.Zero); thumbCount++; } currentTime = new TimeSpan (0, 0, 0, 0, (int) (nStartIntervals * TNSettings.Interval.TotalMilliseconds)); } while (currentTime <= adjustedEnd) { using (System.Drawing.Bitmap resized = GenerateThumbnail (mediaItem, currentTime, tgrid.ThumbWidth, tgrid.ThumbHeight, TNSettings.SrcRect)) { mwriter.Add (resized, currentTime, 0, TimeSpan.Zero); thumbCount++; } currentTime += TNSettings.Interval; } if (nExtraEndSeconds != 0 && thumbCount < nThumbs) { using (System.Drawing.Bitmap resized = GenerateThumbnail (mediaItem, TNSettings.End, tgrid.ThumbWidth, tgrid.ThumbHeight, TNSettings.SrcRect)) { mwriter.Add (resized, TNSettings.End, 0, TimeSpan.Zero); thumbCount++; } } mwriter.Close (); return thumbCount; }
/// <summary> /// Creates the thumbnail grid. /// </summary> /// <param name="layoutMode">The <see cref="ThumbnailSettings.LayoutModes"/>.</param> /// <param name="nThumbs">The desired number of rows or columns.</param> /// <param name="nColumns">The number of desired columns.</param> /// <param name="nRows">The number of desired rows.</param> /// <param name="priorityThreshold">The threshold that determines when to switch /// between Column and Row Priority in /// <see cref="ThumbnailSettings.LayoutModes.Auto"/>.</param> /// <returns></returns> public ThumbnailGrid CreateThumbnailGrid(ThumbnailSettings.LayoutModes layoutMode, int nThumbs, int nColumns, int nRows, double priorityThreshold) { ThumbnailGrid tgrid = null; ThumbnailPageLayout container = new ThumbnailPageLayout (TNSettings); double thumbAspectRatio = TNSettings.ThumbAspectRatio; switch (layoutMode) { case ThumbnailSettings.LayoutModes.Auto: { if (thumbAspectRatio < priorityThreshold) { THelper.Debug ("Auto Column Priority Layout (aspect ratio {0:F2} < {1}), using {2} columns", thumbAspectRatio, priorityThreshold, nThumbs); tgrid = ThumbnailGrid.CreateUsingNColumnsWastedHeight (container, TNSettings, nThumbs, thumbAspectRatio); } else { THelper.Debug ("Auto Row Priority Layout (aspect ratio {0:F2} >= {1}), using {2} rows", thumbAspectRatio, priorityThreshold, nThumbs); tgrid = ThumbnailGrid.CreateUsingNRowsWastedWidth (container, TNSettings, nThumbs, thumbAspectRatio); } break; } case ThumbnailSettings.LayoutModes.Actual: { if (TNSettings.LayoutMode == ThumbnailSettings.LayoutModes.Actual) THelper.Debug ("Actual Layout: {0}x{1}", nColumns, nRows); tgrid = ThumbnailGrid.CreateUsingActual (container, TNSettings, nColumns, nRows, thumbAspectRatio); break; } case ThumbnailSettings.LayoutModes.RowPriority: { THelper.Debug ("Row Priority Layout, using {0} rows", nThumbs); tgrid = ThumbnailGrid.CreateUsingNRowsWastedWidth (container, TNSettings, nThumbs, thumbAspectRatio); break; } case ThumbnailSettings.LayoutModes.ColumnPriority: { THelper.Debug ("Column Priority Layout, using {0} columns", nThumbs); tgrid = ThumbnailGrid.CreateUsingNColumnsWastedHeight(container, TNSettings, nThumbs, thumbAspectRatio); break; } } container.AdjustSize (tgrid); return tgrid; }
/// <summary> /// Generates the overview thumbnail page OBSOLETE. /// </summary> /// <param name="mediaItem">The /// <see cref="Microsoft.Expression.Encoder.MediaItem"/> to generate /// thumbnails for.</param> /// <param name="filename">The display name of the file to generate thumbs for.</param> /// <param name="outputDirectory">The output directory.</param> /// <returns>The number of thumbnails created.</returns> public int GenerateOverviewThumbs(MSEEncoder.MediaItem mediaItem, string filename, string outputDirectory) { double thumbAspectRatio = TNSettings.ThumbAspectRatio; ThumbnailPageLayout container = new ThumbnailPageLayout (TNSettings); ThumbnailGrid tgrid; if (thumbAspectRatio < 1.36) tgrid = ThumbnailGrid.CreateUsingNColumns (container, TNSettings, thumbAspectRatio, false, _debug); else tgrid = ThumbnailGrid.CreateUsingNRows (container, TNSettings, thumbAspectRatio, false, _debug); container.AdjustSize (tgrid); if (outputDirectory == null) outputDirectory = GetDirectoryName (filename); string outTemplate = System.IO.Path.GetFileNameWithoutExtension (filename) + "_overview.jpg"; #if true string stats; if (mediaItem.OriginalVideoSize.Width != TNSettings.SrcRect.Width || mediaItem.OriginalVideoSize.Height != TNSettings.SrcRect.Height || Math.Abs ((double) mediaItem.OriginalVideoSize.Width / mediaItem.OriginalVideoSize.Height - TNSettings.ThumbAspectRatio) > 0.01) { stats = String.Format ("{0}x{1} ({2:F2}:1) [{3}x{4} ({5:F2}:1)] {6} {7}", TNSettings.SrcRect.Width, TNSettings.SrcRect.Height, TNSettings.ThumbAspectRatio, mediaItem.OriginalVideoSize.Width, mediaItem.OriginalVideoSize.Height, (double) mediaItem.OriginalVideoSize.Width / mediaItem.OriginalVideoSize.Height, //getAudioStreamStats(mediaItem), GetFileSizeString (mediaItem.MainMediaFile.FileSize), System.IO.File.GetLastWriteTime (filename).ToString ("g") ); } else { stats = String.Format ("{0}x{1} ({2:F2}:1) {3} {4}", mediaItem.OriginalVideoSize.Width, mediaItem.OriginalVideoSize.Height, TNSettings.ThumbAspectRatio, //getAudioStreamStats(mediaItem), GetFileSizeString (mediaItem.MainMediaFile.FileSize), System.IO.File.GetLastWriteTime (filename).ToString ("g") ); } #else string stats = String.Format ("{0}x{1} ({2:F2}:1) [{3}x{4} {5}x{6}] {7} {8}", mediaItem.OriginalVideoSize.Width, mediaItem.OriginalVideoSize.Height, (double) mediaItem.OriginalVideoSize.Width / mediaItem.OriginalVideoSize.Height, //getAudioStreamStats(mediaItem), tgrid.ThumbWidth, tgrid.ThumbHeight, tgrid.NColumns, tgrid.NRows, GetFileSizeString (mediaItem.MainMediaFile.FileSize), System.IO.File.GetLastWriteTime (filename).ToString ("g") ); #endif THelper.Information ("Generating {0} overview page thumbs.", tgrid.NThumbs); ThumbnailWriter writer = new ThumbnailWriter (this, tgrid, outputDirectory, filename, outTemplate, stats, mediaItem.FileDuration, TNSettings.ScaleFactor, _debug); double intervalSeconds = ((TNSettings.End.TotalSeconds - TNSettings.Start.TotalSeconds) / (tgrid.NColumns * tgrid.NRows - 1)); int milliseconds = (int) ((intervalSeconds - Math.Truncate (intervalSeconds)) * 1000 + 0.5); TimeSpan interval = new TimeSpan (0, 0, 0, (int) intervalSeconds, milliseconds); int nThumbsAdded = 0; TimeSpan currentTime = TNSettings.Start; while (currentTime <= TNSettings.End) { using (System.Drawing.Bitmap resized = GenerateThumbnail (mediaItem, currentTime, tgrid.ThumbWidth, tgrid.ThumbHeight, TNSettings.SrcRect)) { writer.Add (resized, currentTime); nThumbsAdded++; } currentTime += interval; } // Last thumb should always be end time. if (nThumbsAdded < tgrid.NThumbs) { using (System.Drawing.Bitmap resized = GenerateThumbnail (mediaItem, TNSettings.End, tgrid.ThumbWidth, tgrid.ThumbHeight, TNSettings.SrcRect)) { writer.Add (resized, TNSettings.End); nThumbsAdded++; } } writer.Close (); return tgrid.NThumbs; }
/// <summary> /// Dumps the Column/Rows determination (based on aspect ratio) Plot. /// </summary> /// <param name="filename">name of the image file to write to.</param> /// <param name="plotThresholds">if set to <c>true</c> plot threshold info.</param> private void DumpColRowsPlot(string filename, bool plotThresholds) { bool detailsPage; int nThumbs, nCols, nRows; double crossoverThreshold; filename = System.IO.Path.GetFileNameWithoutExtension (filename) + ".png"; if (System.IO.File.Exists (filename)) { Console.Write ("'{0}' already exists. Overwrite (Y/N) [N]?", filename); string answer = Console.ReadLine (); answer = answer.Trim ().ToLower (); if (answer != "y" && answer != "yes") { Console.Write ("Aborting operation."); return; } } if (_tnSettings.Interval.TotalSeconds > 0) { detailsPage = true; nThumbs = _tnSettings.DetailThumbs; nCols = _tnSettings.DetailColumns; nRows = _tnSettings.DetailRows; crossoverThreshold = _tnSettings.DetailThreshold; } else { detailsPage = false; nThumbs = _tnSettings.OverviewThumbs; nCols = _tnSettings.OverviewColumns; nRows = _tnSettings.OverviewRows; crossoverThreshold = _tnSettings.OverviewThreshold; } THelper.Information (""); THelper.Information ("Dumping Column/Rows Determination Plot"); THelper.Information ("Page: {0} {1}x{2} ({3:F2}:1)", detailsPage ? "Detail" : "Overview", _tnSettings.Width, _tnSettings.Height, _tnSettings.AspectRatio); THelper.Information ("Layout Mode: {0}", _tnSettings.LayoutMode); if (_tnSettings.LayoutMode == ThumbnailSettings.LayoutModes.Auto) THelper.Information ("Threshold: {0:F2}", crossoverThreshold); if (_tnSettings.LayoutMode == ThumbnailSettings.LayoutModes.Actual) { THelper.Information ("Actual: {1}x{2}", nCols, nRows); } else { THelper.Information ("RC Optimization: {0}", _tnSettings.RCOptimization); THelper.Information ("Max RC Opt Steps: {0}", _tnSettings.MaxOptimizationSteps); THelper.Information ("Desired: {0} thumbs", nThumbs); THelper.Information ("Minimum: {0} columns, {1} rows", _tnSettings.MinColumns, _tnSettings.MinRows); } THelper.Information (""); System.Drawing.Font titleFont = new System.Drawing.Font ("Ariel", 24, System.Drawing.FontStyle.Bold); System.Drawing.Font subTitleFont = new System.Drawing.Font ("Ariel", 13, System.Drawing.FontStyle.Bold); System.Drawing.Font axisLabelFont = new System.Drawing.Font ("Ariel", 20, System.Drawing.FontStyle.Bold); System.Drawing.Font axisFont = new System.Drawing.Font ("Ariel", 12, System.Drawing.FontStyle.Bold); System.Drawing.Font annotationFont = new System.Drawing.Font ("Ariel", 10, System.Drawing.FontStyle.Regular); System.Drawing.Font annotationItFont = new System.Drawing.Font ("Ariel", 10, System.Drawing.FontStyle.Italic); Charting.Chart chart = new Charting.Chart (); Charting.ChartArea chartArea = chart.ChartAreas.Add ("Wasted"); Charting.Legend legend = new Charting.Legend ("Wasted"); legend.DockedToChartArea = "Wasted"; legend.Font = axisFont; legend.Docking = Charting.Docking.Bottom; legend.Alignment = System.Drawing.StringAlignment.Far; legend.LegendStyle = Charting.LegendStyle.Column; chart.Legends.Add (legend); Charting.LabelStyle labelStyle1 = new Charting.LabelStyle(); labelStyle1.Font = axisFont; Charting.LabelStyle labelStyle2 = new Charting.LabelStyle (); labelStyle2.Font = axisFont; Charting.LabelStyle labelStyle3 = new Charting.LabelStyle (); labelStyle3.Font = axisFont; chart.BackColor = System.Drawing.Color.Wheat; chartArea.BorderWidth = 3; chartArea.BorderDashStyle = Charting.ChartDashStyle.Solid; //chartArea.BorderColor = System.Drawing.Color.Violet; legend.BackColor = System.Drawing.Color.Wheat; string titleStr = "Optimum Number of Columns & Rows"; if (plotThresholds) titleStr += "\nUsing % Wasted Thumbnail Width & Height"; Charting.Title title = chart.Titles.Add (titleStr); title.Font = titleFont; //subTitle.DockingOffset = -2; Charting.TextAnnotation desired = new Charting.TextAnnotation (); desired.Font = subTitleFont; switch (_tnSettings.LayoutMode) { case ThumbnailSettings.LayoutModes.Auto: chartArea.BackColor = System.Drawing.Color.Beige; desired.Text = String.Format ( "{0} Cols or Rows; Min {1} Cols, {2} Rows; {3} Max Opt Steps", nThumbs, _tnSettings.MinColumns, _tnSettings.MinRows, _tnSettings.MaxOptimizationSteps); break; case ThumbnailSettings.LayoutModes.Actual: chartArea.BackColor = System.Drawing.Color.Ivory; desired.Text = String.Format ("{0} Columns and {1} Rows", nCols, nRows); break; case ThumbnailSettings.LayoutModes.RowPriority: chartArea.BackColor = System.Drawing.Color.Beige; desired.Text = String.Format ( "{0} Rows; Min {1} Columns; {2} Max Opt Steps", nThumbs, _tnSettings.MinColumns, _tnSettings.MaxOptimizationSteps); break; case ThumbnailSettings.LayoutModes.ColumnPriority: chartArea.BackColor = System.Drawing.Color.AliceBlue; desired.Text = String.Format ( "{0} Columns; Min {1} Rows; {2} Max Opt Steps", nThumbs, _tnSettings.MinRows, _tnSettings.MaxOptimizationSteps); break; } desired.Text += detailsPage ? "\nDetail Page" : "\nOverview Page"; desired.Text += String.Format (" {0}x{1} ({2:F2}:1)", _tnSettings.Width, _tnSettings.Height, _tnSettings.AspectRatio); desired.Alignment = System.Drawing.ContentAlignment.BottomLeft; desired.X = 1; desired.Y = 95; chart.Annotations.Add (desired); Charting.TextAnnotation layout = new Charting.TextAnnotation (); layout.Font = subTitleFont; layout.Text = String.Format("{0} Layout Mode", _tnSettings.LayoutMode); if (_tnSettings.LayoutMode != ThumbnailSettings.LayoutModes.Actual) layout.Text += String.Format ("\nRow/Column Optimization {0}", _tnSettings.RCOptimization ? "enabled" : "disabled"); layout.Alignment = System.Drawing.ContentAlignment.BottomRight; layout.X = 77; layout.Y = 95; chart.Annotations.Add (layout); chart.Width = 1280; chart.Height = 1024; int lineWidth = 5; int dotsWidth = 2; chartArea.AxisX.Title = "Video Aspect Ratio"; chartArea.AxisX.TitleFont = axisLabelFont; chartArea.AxisX.MajorGrid.Enabled = false; chartArea.AxisX.MajorTickMark.Interval = 0.10; chartArea.AxisX.Minimum = 1.0; chartArea.AxisX.Maximum = 3.0; chartArea.AxisX.Interval = 0.5; chartArea.AxisX.LineWidth = 3; chartArea.AxisX.MajorTickMark.LineWidth = 3; chartArea.AxisX.LabelStyle = labelStyle1; chartArea.AxisX.LabelStyle.Format = "F2"; chartArea.AxisX.IsMarginVisible = true; if (_tnSettings.LayoutMode == ThumbnailSettings.LayoutModes.Auto && crossoverThreshold > 1.0) { Charting.StripLine stripLine = new Charting.StripLine (); stripLine.IntervalOffset = 0.0; stripLine.StripWidth = crossoverThreshold - 1.0; stripLine.Interval = 10000; stripLine.BackColor = System.Drawing.Color.AliceBlue; chartArea.AxisX.StripLines.Add (stripLine); } chartArea.AxisY.Title = "# of Columns or Rows"; chartArea.AxisY.TitleFont = axisLabelFont; chartArea.AxisY.MajorGrid.Enabled = false; chartArea.AxisY.MajorTickMark.Interval = 1.0; chartArea.AxisY.LineWidth = 3; chartArea.AxisY.MajorTickMark.LineWidth = 3; chartArea.AxisY.LabelStyle = labelStyle2; //chartArea.AxisY.LabelStyle.IsEndLabelVisible = false; chartArea.AxisY.IsMarginVisible = true; if (!plotThresholds) { chartArea.AxisY2.Enabled = Charting.AxisEnabled.True; //chartArea.AxisY2.Title = "# of Columns or Rows"; chartArea.AxisY2.TitleFont = axisLabelFont; chartArea.AxisY2.MajorGrid.Enabled = false; chartArea.AxisY2.MajorTickMark.Interval = 1.0; chartArea.AxisY2.LineWidth = 3; chartArea.AxisY2.MajorTickMark.LineWidth = 3; chartArea.AxisY2.LabelStyle = labelStyle3; //chartArea.AxisY2.LabelStyle.IsEndLabelVisible = false; chartArea.AxisY2.IsMarginVisible = true; } Charting.Series seriesNCols = chart.Series.Add ("# of Columns"); seriesNCols.ChartType = Charting.SeriesChartType.StepLine; seriesNCols.ChartArea = "Wasted"; seriesNCols.Legend = "Wasted"; seriesNCols.IsVisibleInLegend = true; seriesNCols.BorderWidth = lineWidth; Charting.Series seriesNRows = chart.Series.Add ("# of Rows"); seriesNRows.ChartType = Charting.SeriesChartType.StepLine; seriesNRows.ChartArea = "Wasted"; seriesNRows.Legend = "Wasted"; seriesNRows.IsVisibleInLegend = true; seriesNRows.BorderWidth = lineWidth; Charting.Series seriesWW = null; Charting.Series seriesWH = null; if (plotThresholds) { chartArea.AxisY2.Title = "% Wasted Thumbnail Width or Height"; chartArea.AxisY2.TitleFont = axisLabelFont; chartArea.AxisY2.MajorGrid.Enabled = false; chartArea.AxisY2.LineWidth = 3; chartArea.AxisY2.MajorTickMark.LineWidth = 3; chartArea.AxisY2.LabelStyle = labelStyle3; //chartArea.AxisY2.LabelStyle.IsEndLabelVisible = false; chartArea.AxisY2.Maximum = 100.0; seriesWW = chart.Series.Add ("%Wasted Width"); seriesWW.ChartType = Charting.SeriesChartType.Line; seriesWW.ChartArea = "Wasted"; seriesWW.Legend = "Wasted"; seriesWW.IsVisibleInLegend = true; seriesWW.BorderWidth = dotsWidth; seriesWW.BorderDashStyle = Charting.ChartDashStyle.Dot; seriesWW.YAxisType = Charting.AxisType.Secondary; seriesWH = chart.Series.Add ("%Wasted Height"); seriesWH.ChartType = Charting.SeriesChartType.Line; seriesWH.ChartArea = "Wasted"; seriesWH.Legend = "Wasted"; seriesWH.IsVisibleInLegend = true; seriesWH.BorderWidth = dotsWidth; seriesWH.BorderDashStyle = Charting.ChartDashStyle.Dot; seriesWH.YAxisType = Charting.AxisType.Secondary; } ThumbnailCreator creator = new ThumbnailCreator (_tnSettings, null); ThumbnailPageLayout container = new ThumbnailPageLayout (_tnSettings); ThumbnailPageLayout newContainer; double wastedWidth, wastedHeight; int extraWidth, extraHeight; double extraWidthPercent, extraHeightPercent; for (double aspectRatio=1.0; aspectRatio <= 3.0; aspectRatio += 0.01) { _tnSettings.ThumbAspectRatio = aspectRatio; ThumbnailGrid tg = creator.CreateThumbnailGrid(_tnSettings.LayoutMode, nThumbs, nCols, nRows, crossoverThreshold); newContainer = tg.Layout; container.CalcWasted (_tnSettings, tg, out wastedWidth, out wastedHeight); extraWidth = (int) (wastedWidth * tg.ThumbWidth); extraHeight = (int) (wastedHeight * tg.ThumbHeight); extraWidthPercent = 100.0 * extraWidth / newContainer.Width; extraHeightPercent = 100.0 * extraHeight / newContainer.Height; THelper.Information (String.Format ( "{9,4}x{10,4} ({13,4:F2}) {0,4:F2} {1,2}x{2,2} {3,3:D}x{4,3:D} " + "{5,6:F2}x{6,6:F2} {7,3:D}x{8,3:D} {11:F1}x{12:F1}", aspectRatio, tg.NColumns, tg.NRows, tg.ThumbWidth, tg.ThumbHeight, wastedWidth, wastedHeight, extraWidth, extraHeight, newContainer.Width, newContainer.Height, extraWidthPercent, extraHeightPercent, newContainer.AspectRatio )); int index; if (plotThresholds) { index = seriesWW.Points.AddXY (aspectRatio, wastedWidth * 100.0); if (wastedWidth == 0.0) seriesWW.Points[index].IsEmpty = true; index = seriesWH.Points.AddXY (aspectRatio, wastedHeight * 100.0); if (wastedHeight == 0.0) seriesWH.Points[index].IsEmpty = true; } seriesNCols.Points.AddXY (aspectRatio, tg.NColumns); seriesNRows.Points.AddXY (aspectRatio, tg.NRows); } chartArea.RecalculateAxesScale (); AddARAnnotation (chart, "Fullscreen 4:3\n(1.33)", 1.33, annotationFont, plotThresholds); AddARAnnotation (chart, "HD 16:9\n(1.78)", 1.78, annotationFont, plotThresholds); AddARAnnotation (chart, "Widescreen\n(1.85)", 1.85, annotationFont, plotThresholds); AddARAnnotation (chart, "CinemaScope\n(2.35)", 2.35, annotationFont, plotThresholds); AddARAnnotation (chart, "Ultra-Panavision\n(2.76)", 2.76, annotationFont, plotThresholds); AddARAnnotation (chart, String.Format ("Layout Threshold\n({0:F2})", crossoverThreshold), crossoverThreshold, _tnSettings.LayoutMode == ThumbnailSettings.LayoutModes.Auto ? annotationFont : annotationItFont, plotThresholds, true); if (_tnSettings.RCOptimization && plotThresholds) { switch (_tnSettings.LayoutMode) { case ThumbnailSettings.LayoutModes.Auto: if (_tnSettings.WidthThreshold == _tnSettings.HeightThreshold) AddThresholdAnnotation (chart, String.Format ("Width & Height Threshold\n" + "({0:F2})", _tnSettings.WidthThreshold), _tnSettings.WidthThreshold, annotationFont); else { AddThresholdAnnotation (chart, String.Format ("Width Threshold\n" + "({0:F2})", _tnSettings.WidthThreshold), _tnSettings.WidthThreshold, annotationFont); AddThresholdAnnotation (chart, String.Format ("Height Threshold\n" + "({0:F2})", _tnSettings.HeightThreshold), _tnSettings.HeightThreshold, annotationFont); } break; case ThumbnailSettings.LayoutModes.RowPriority: AddThresholdAnnotation (chart, String.Format ("Width Threshold\n" + "({0:F2})", _tnSettings.WidthThreshold), _tnSettings.WidthThreshold, annotationFont); break; case ThumbnailSettings.LayoutModes.ColumnPriority: AddThresholdAnnotation (chart, String.Format ("Height Threshold\n" + "({0:F2})", _tnSettings.HeightThreshold), _tnSettings.HeightThreshold, annotationFont); break; } } chart.SaveImage (filename, Charting.ChartImageFormat.Png); THelper.Information ("'{0}' created.", filename); labelStyle1.Dispose (); labelStyle2.Dispose (); labelStyle3.Dispose (); titleFont.Dispose (); subTitleFont.Dispose (); axisFont.Dispose (); annotationFont.Dispose (); annotationItFont.Dispose (); chart.Dispose (); }
/// <summary> /// Create ThumbnailGrid the using desired # of rows and /// <see cref="ThumbnailSettings"/> - PercentPage method /// </summary> /// <param name="layout">The <see cref="ThumbnailPageLayout"/>.</param> /// <param name="tnSettings">The <see cref="ThumbnailSettings"/>.</param> /// <param name="aspectRatio">The thumbnail aspect ratio.</param> /// <param name="percentPageWidth">percent of the page width used.</param> /// <returns>new <see cref="ThumbnailGrid"/></returns> private static ThumbnailGrid CreateUsingNRowsPercentPage( ThumbnailPageLayout layout, ThumbnailSettings tnSettings, double aspectRatio, out double percentPageWidth ) { ThumbnailGrid thumbnailGrid; int nRows = tnSettings.OverviewRows; SortedList<double, int> wastedPercents = new SortedList<double,int> (); if ((THelper.ConsoleLevels & System.Diagnostics.SourceLevels.Verbose) == System.Diagnostics.SourceLevels.Verbose || !(!tnSettings.RCOptimization || (tnSettings.LayoutMode == ThumbnailSettings.LayoutModes.Actual))) { for (int i=tnSettings.MinOverviewRows; ; i++) { thumbnailGrid = CreateUsingNRows (layout, i, aspectRatio); if (thumbnailGrid.NColumns > 2) { double wastedPercent = thumbnailGrid.CalculateWastedPercentPage (layout); if (wastedPercents.ContainsKey (wastedPercent)) { if (i == nRows) { wastedPercents.Remove (wastedPercent); wastedPercents.Add (wastedPercent, i); } } else wastedPercents.Add(wastedPercent, i); } if (i > nRows && thumbnailGrid.WastedWidth <= tnSettings.WidthThreshold) break; } } if ((THelper.ConsoleLevels & System.Diagnostics.SourceLevels.Verbose) == System.Diagnostics.SourceLevels.Verbose) { THelper.Debug (" {0:F2} aspect ratio", aspectRatio); foreach (KeyValuePair<double,int> kvp in wastedPercents) { thumbnailGrid = CreateUsingNRows (layout, kvp.Value, aspectRatio); THelper.Debug (" {0}x{1} {2:F2} {3:F2}", thumbnailGrid.NColumns, thumbnailGrid.NRows, thumbnailGrid.WastedWidth, kvp.Key); } } thumbnailGrid = CreateUsingNRows (layout, nRows, aspectRatio); percentPageWidth = thumbnailGrid.CalculateWastedPercentPage (layout); if (!tnSettings.RCOptimization) { THelper.Debug (" Row optimization disabled, using {0} rows", nRows); THelper.Debug (" {0:F2} aspect ratio", aspectRatio); THelper.Debug (" {0}x{1} {2:F2} {3:F2}", thumbnailGrid.NColumns, thumbnailGrid.NRows, thumbnailGrid.WastedWidth, percentPageWidth); return thumbnailGrid; } if (percentPageWidth < 0.15) { THelper.Debug (" {0} rows is good enough.", nRows); THelper.Debug (" {0:F2} aspect ratio", aspectRatio); THelper.Debug (" {0}x{1} {2:F2} {3:F2}", thumbnailGrid.NColumns, thumbnailGrid.NRows, thumbnailGrid.WastedWidth, percentPageWidth); return thumbnailGrid; } if (wastedPercents.Values[0] != nRows && Math.Abs (percentPageWidth - wastedPercents.Keys[0]) < 0.15) { THelper.Debug (" {0} rows is close to best.", nRows); thumbnailGrid = CreateUsingNRows (layout, nRows, aspectRatio); } else { THelper.Debug (" {0} rows is best.", wastedPercents.Values[0]); thumbnailGrid = CreateUsingNRows (layout, wastedPercents.Values[0], aspectRatio); } percentPageWidth = thumbnailGrid.CalculateWastedPercentPage (layout); return thumbnailGrid; }
/// <summary> /// Create ThumbnailGrid the using desired # of rows and /// <see cref="ThumbnailSettings"/>. /// </summary> /// <param name="layout">The <see cref="ThumbnailPageLayout"/>.</param> /// <param name="tnSettings">The <see cref="ThumbnailSettings"/>.</param> /// <param name="nColumns">The desired number of columns.</param> /// <param name="nRows">The desired number of rows.</param> /// <param name="aspectRatio">The thumbnail aspect ratio.</param> /// <returns> /// new <see cref="ThumbnailGrid"/> /// </returns> public static ThumbnailGrid CreateUsingNRows(ThumbnailPageLayout layout, ThumbnailSettings tnSettings, int nColumns, int nRows, double aspectRatio ) { ThumbnailGrid tgWastedWidth; tgWastedWidth = CreateUsingNRowsWastedWidth (layout, tnSettings, nColumns, nRows, aspectRatio); return tgWastedWidth; if (tgWastedWidth.WastedWidth < 1.50 || tnSettings.Raw) return tgWastedWidth; // Following should now be never reached. ThumbnailGrid tgPercentPage; double percentPageWidth; tgPercentPage = CreateUsingNRowsPercentPage (layout, tnSettings, aspectRatio, debug, out percentPageWidth); if (percentPageWidth < 0.15) return tgPercentPage; else return tgWastedWidth; }
/// <summary> /// Create ThumbnailGrid the using desired # of rows. /// </summary> /// <param name="layout">The <see cref="ThumbnailPageLayout"/>.</param> /// <param name="nRows">The desired # of rows.</param> /// <param name="aspectRatio">The thumbnail aspect ratio.</param> /// <returns>new <see cref="ThumbnailGrid"/></returns> private static ThumbnailGrid CreateUsingNRows(ThumbnailPageLayout layout, int nRows, double aspectRatio) { int nColumns; int thumbWidth; int thumbHeight; thumbHeight = layout.CalcThumbHeightFromNRows (nRows); thumbWidth = (int) (thumbHeight * aspectRatio + 0.5); nColumns = layout.CalcColumnsFromThumbWidth (thumbWidth); ThumbnailGrid thumbnailGrid = new ThumbnailGrid (layout, nColumns, nRows, thumbWidth, thumbHeight); return thumbnailGrid; }
/// <summary> /// Create ThumbnailGrid the using desired # of columns. /// </summary> /// <param name="layout">The <see cref="ThumbnailPageLayout"/>.</param> /// <param name="nColumns">The desired # of columns.</param> /// <param name="aspectRatio">The thumbnail aspect ratio.</param> /// <returns> /// new <see cref="ThumbnailGrid"/> /// </returns> private static ThumbnailGrid CreateUsingNColumns(ThumbnailPageLayout layout, int nColumns, double aspectRatio) { int nRows; int thumbWidth; int thumbHeight; thumbWidth = layout.CalcThumbWidthFromNCols (nColumns); thumbHeight = (int) (thumbWidth / aspectRatio + 0.5); nRows = layout.CalcRowsFromThumbHeight (thumbHeight); ThumbnailGrid thumbnailGrid = new ThumbnailGrid (layout, nColumns, nRows, thumbWidth, thumbHeight); return thumbnailGrid; }
/// <summary> /// Calculates the wasted width in percent of page width. /// </summary> /// <param name="layout">A <see cref="ThumbnailPageLayout"/>.</param> /// <returns>percent wasted width</returns> public double CalculateWastedPercentPage(ThumbnailPageLayout layout) { double wastedPixels = ThumbWidth * WastedWidth; return wastedPixels / layout.Width; }
/// <summary> /// Create ThumbnailGrid the using desired thumbnail width. /// </summary> /// <param name="layout">The <see cref="ThumbnailPageLayout"/>.</param> /// <param name="thumbWidth">The desired thumbnail width.</param> /// <param name="aspectRatio">The thumbnail aspect ratio.</param> /// <returns>new <see cref="ThumbnailGrid"/></returns> public static ThumbnailGrid CreateUsingThumbWidth(ThumbnailPageLayout layout, int thumbWidth, double aspectRatio) { int nRows; int nColumns; int thumbHeight; nColumns = layout.CalcColumnsFromThumbWidth(thumbWidth); thumbHeight = (int) (thumbWidth / aspectRatio + 0.5); nRows = layout.CalcRowsFromThumbHeight (thumbHeight); ThumbnailGrid thumbnailGrid = new ThumbnailGrid (layout, nColumns, nRows, thumbWidth, thumbHeight); return thumbnailGrid; }
/// <summary> /// Create ThumbnailGrid the using desired columns & rows. /// </summary> /// <param name="layout">The <see cref="ThumbnailPageLayout"/>.</param> /// <param name="nColumns">The # of columns.</param> /// <param name="nRows">The # of rows.</param> /// <param name="aspectRatio">The thumbnail aspect ratio.</param> /// <param name="fitWidth">if set to <c>true</c>use page layout width, /// otherwise use page layout height.</param> /// <returns>new <see cref="ThumbnailGrid"/></returns> public static ThumbnailGrid CreateUsingRaw(ThumbnailPageLayout layout, int nColumns, int nRows, double aspectRatio, bool fitWidth) { int thumbWidth; int thumbHeight; if (fitWidth) { thumbWidth = layout.CalcThumbWidthFromNCols (nColumns); thumbHeight = (int) (thumbWidth / aspectRatio + 0.5); layout.AdjustHeight (nRows, thumbHeight); } else { thumbHeight = layout.CalcThumbHeightFromNRows (nRows); thumbWidth = (int) (thumbHeight * aspectRatio + 0.5); layout.AdjustWidth (nColumns, thumbWidth); } ThumbnailGrid thumbnailGrid = new ThumbnailGrid (layout, nColumns, nRows, thumbWidth, thumbHeight); layout.AdjustSize (thumbnailGrid); return thumbnailGrid; }
/// <summary> /// Create ThumbnailGrid the using desired # of rows and /// <see cref="ThumbnailSettings"/> - WastedWidth method /// </summary> /// <param name="layout">The <see cref="ThumbnailPageLayout"/>.</param> /// <param name="tnSettings">The <see cref="ThumbnailSettings"/>.</param> /// <param name="nRows">The desired # of rows.</param> /// <param name="aspectRatio">The thumbnail aspect ratio.</param> /// <returns>new <see cref="ThumbnailGrid"/></returns> public static ThumbnailGrid CreateUsingNRowsWastedWidth( ThumbnailPageLayout layout, ThumbnailSettings tnSettings, int nRows, double aspectRatio) { ThumbnailPageLayout originalLayout = new ThumbnailPageLayout (layout); ThumbnailGrid thumbnailGrid; #if false double smallerPenalty = 0.20; double largerPenalty = smallerPenalty / 4.0; SortedList<double, Tuple<double,double,int>> wastedWidths = new SortedList<double, Tuple<double, double, int>> (); Tuple<double, double, int> wastedPenalty; if (debug || !(tnSettings.SkipOptimization || tnSettings.Raw)) { for (int i=tnSettings.MinOverviewRows; ; i++) { thumbnailGrid = CreateUsingNRows (layout, i, aspectRatio); if (i < nRows) wastedPenalty = new Tuple<double, double, int> (thumbnailGrid.WastedWidth, (nRows - i) * smallerPenalty, i); else if (i > nRows) wastedPenalty = new Tuple<double, double, int> (thumbnailGrid.WastedWidth, (i - nRows) * largerPenalty, i); else wastedPenalty = new Tuple<double, double, int> (thumbnailGrid.WastedWidth, 0.0, i); if (thumbnailGrid.NColumns > 2) wastedWidths.Add (wastedPenalty.Item1 + wastedPenalty.Item2, wastedPenalty); if (i > nRows && thumbnailGrid.WastedWidth <= tnSettings.WidthThreshold) break; } } if (debug) { THelper.Debug (" {0:F2} aspect ratio, {1} header height", aspectRatio, layout.HeaderHeight); foreach (KeyValuePair<double,Tuple<double,double,int>> kvp in wastedWidths) { thumbnailGrid = CreateUsingNRows (layout, kvp.Value.Item3, aspectRatio); THelper.Debug (" {0}x{1} {2:F2}={3:F2}+{4:F2}", thumbnailGrid.NColumns, thumbnailGrid.NRows, kvp.Key, kvp.Value.Item1, kvp.Value.Item2); } } #endif double wastedWidth, wastedHeight; ThumbnailPageLayout newLayout = new ThumbnailPageLayout (originalLayout); thumbnailGrid = CreateUsingNRows (newLayout, nRows, aspectRatio); newLayout.AdjustSize (thumbnailGrid); originalLayout.CalcWasted (tnSettings, thumbnailGrid, out wastedWidth, out wastedHeight); if (!tnSettings.RCOptimization) { THelper.Debug (" Column optimization disabled, using {0} columns", thumbnailGrid.NColumns); THelper.Debug (" {0:F2} aspect ratio", aspectRatio); THelper.Debug (" {0}x{1} {2:F3}x{3:F3}", thumbnailGrid.NColumns, thumbnailGrid.NRows, wastedWidth, wastedHeight); return thumbnailGrid; } bool minSet = false; if (thumbnailGrid.NColumns < tnSettings.MinColumns) { THelper.Debug (" {0} columns < minimum, setting to {1}", thumbnailGrid.NColumns, tnSettings.MinColumns); newLayout = new ThumbnailPageLayout (originalLayout); thumbnailGrid = ThumbnailGrid.CreateUsingRaw (newLayout, tnSettings.MinColumns, nRows, aspectRatio, false); originalLayout.CalcWasted (tnSettings, thumbnailGrid, out wastedWidth, out wastedHeight); minSet = true; } if (wastedWidth - tnSettings.WidthThreshold < 0.005) { THelper.Debug (" {0:F2} aspect ratio", aspectRatio); THelper.Debug (" {0} columns is good enough, wasted width {1:F3} <= {2:F3}", thumbnailGrid.NColumns, wastedWidth, tnSettings.WidthThreshold); THelper.Debug (" {0}x{1} {2:F3}x{3:F3}", thumbnailGrid.NColumns, thumbnailGrid.NRows, wastedWidth, wastedHeight); if (!minSet) return thumbnailGrid; } int nSteps = 1; while (true) { if (tnSettings.MaxOptimizationSteps > 0 && nSteps > tnSettings.MaxOptimizationSteps) { THelper.Debug (" {0} max optimization steps reached.", tnSettings.MaxOptimizationSteps); break; } if (wastedWidth - tnSettings.WidthThreshold >= 0.005) { double savedWastedWidth = wastedWidth; newLayout = new ThumbnailPageLayout (originalLayout); thumbnailGrid = ThumbnailGrid.CreateUsingRaw (newLayout, thumbnailGrid.NColumns + 1, nRows, aspectRatio, false); originalLayout.CalcWasted (tnSettings, thumbnailGrid, out wastedWidth, out wastedHeight); THelper.Debug (" {0:F2} aspect ratio", aspectRatio); THelper.Debug (" Wasted width {0:F3} > {1:F3}, increased columns: " + "{2}x{3} {4:F3}x{5:F3} ", savedWastedWidth, tnSettings.WidthThreshold, thumbnailGrid.NColumns, thumbnailGrid.NRows, wastedWidth, wastedHeight); } // still need to check this if minimum was set. if (wastedHeight - tnSettings.HeightThreshold < 0.0025) break; else { double savedWastedHeight = wastedHeight; newLayout = new ThumbnailPageLayout (originalLayout); thumbnailGrid = ThumbnailGrid.CreateUsingRaw (newLayout, thumbnailGrid.NColumns, thumbnailGrid.NRows+1, aspectRatio, false); originalLayout.CalcWasted (tnSettings, thumbnailGrid, out wastedWidth, out wastedHeight); THelper.Debug (" Now wasted height {0:F3} > {1:F3}, increased rows: " + "{2}x{3} {4:F3}x{5:F3} ", savedWastedHeight, tnSettings.HeightThreshold, thumbnailGrid.NColumns, thumbnailGrid.NRows, wastedWidth, wastedHeight); } nSteps++; } return thumbnailGrid; #if false //Following should now be never reached. if (wastedWidths.Values[0].Item1 > 0.60) { thumbnailGrid = ThumbnailGrid.CreateUsingRaw (layout, thumbnailGrid.NColumns + 1, nRows, aspectRatio, false); if (debug) THelper.Debug (" {0}x{1} Best still wastes > 0.60, increasing columns.", thumbnailGrid.NColumns, nRows); return thumbnailGrid; } if (wastedWidths.Values[0].Item3 != nRows && Math.Abs (desiredWastedWidth - wastedWidths.Values[0].Item1) < 0.15) { if (debug) THelper.Debug (" {0} rows is close to best.", nRows); thumbnailGrid = CreateUsingNRows (layout, nRows, aspectRatio); } else { if (debug) THelper.Debug (" {0} rows is best.", wastedWidths.Values[0].Item3); thumbnailGrid = CreateUsingNRows (layout, wastedWidths.Values[0].Item3, aspectRatio); } return thumbnailGrid; #endif }
/// <summary> /// Create ThumbnailGrid the using desired # of columns and <see cref="ThumbnailSettings"/>. /// </summary> /// <param name="layout">The <see cref="ThumbnailPageLayout"/>.</param> /// <param name="tnSettings">The <see cref="ThumbnailSettings"/>.</param> /// <param name="nColumns">The desired number of columns.</param> /// <param name="aspectRatio">The thumbnail aspect ratio.</param> /// <returns> /// new <see cref="ThumbnailGrid"/> /// </returns> public static ThumbnailGrid CreateUsingNColumnsWastedHeight( ThumbnailPageLayout layout, ThumbnailSettings tnSettings, int nColumns, double aspectRatio ) { ThumbnailPageLayout originalLayout = new ThumbnailPageLayout (layout); ThumbnailGrid thumbnailGrid; #if false SortedList<double,int> wastedHeights = new SortedList<double, int> (); if (debug || !(tnSettings.SkipOptimization || tnSettings.Raw)) { for (int i=nColumns - 1; ; i++) { thumbnailGrid = CreateUsingNColumns (layout, i, aspectRatio); if (thumbnailGrid.NRows <= tnSettings.MaxMultiRows) wastedHeights.Add (thumbnailGrid.WastedHeight, i); if (i > nColumns && thumbnailGrid.WastedHeight <= tnSettings.HeightThreshold) break; } } if (debug) { THelper.Debug (" {0:F2} aspect ratio, {1} header height", aspectRatio, layout.HeaderHeight); foreach (KeyValuePair<double,int> kvp in wastedHeights) { thumbnailGrid = CreateUsingNColumns (layout, kvp.Value, aspectRatio); THelper.Debug(" {0}x{1} {2:F2}", thumbnailGrid.NColumns, thumbnailGrid.NRows, kvp.Key); } } #endif double wastedWidth, wastedHeight; ThumbnailPageLayout newLayout = new ThumbnailPageLayout (originalLayout); thumbnailGrid = CreateUsingNColumns (newLayout, nColumns, aspectRatio); newLayout.AdjustSize (thumbnailGrid); originalLayout.CalcWasted (tnSettings, thumbnailGrid, out wastedWidth, out wastedHeight); if (!tnSettings.RCOptimization) { THelper.Debug (" Row optimization disabled, using {0} rows", thumbnailGrid.NRows); THelper.Debug (" {0:F2} aspect ratio", aspectRatio); THelper.Debug (" {0}x{1} {2:F3}x{3:F3}", thumbnailGrid.NColumns, thumbnailGrid.NRows, wastedWidth, wastedHeight); return thumbnailGrid; } bool minSet = false; if (thumbnailGrid.NRows < tnSettings.MinRows) { THelper.Debug (" {0} rows < minimum, setting to {1}", thumbnailGrid.NRows, tnSettings.MinRows); newLayout = new ThumbnailPageLayout (originalLayout); thumbnailGrid = ThumbnailGrid.CreateUsingRaw (newLayout, nColumns, tnSettings.MinRows, aspectRatio, true); originalLayout.CalcWasted (tnSettings, thumbnailGrid, out wastedWidth, out wastedHeight); minSet = true; } if (wastedHeight - tnSettings.HeightThreshold < 0.0025) { THelper.Debug (" {0:F2} aspect ratio", aspectRatio); THelper.Debug (" {0} rows is good enough, wasted height {1:F3} <= {2:F3}", thumbnailGrid.NRows, wastedHeight, tnSettings.HeightThreshold); THelper.Debug (" {0}x{1} {2:F3}x{3:F3}", thumbnailGrid.NColumns, thumbnailGrid.NRows, wastedWidth, wastedHeight); if (!minSet) return thumbnailGrid; } int nSteps = 1; while (true) { if (tnSettings.MaxOptimizationSteps > 0 && nSteps > tnSettings.MaxOptimizationSteps) { THelper.Debug (" {0} Max Optimization steps reached.", tnSettings.MaxOptimizationSteps); break; } if (wastedHeight - tnSettings.HeightThreshold >= 0.0025) { double savedWastedHeight = wastedHeight; newLayout = new ThumbnailPageLayout (originalLayout); thumbnailGrid = ThumbnailGrid.CreateUsingRaw (newLayout, nColumns, thumbnailGrid.NRows + 1, aspectRatio, true); originalLayout.CalcWasted (tnSettings, thumbnailGrid, out wastedWidth, out wastedHeight); THelper.Debug (" {0:F2} aspect ratio", aspectRatio); THelper.Debug (" Wasted height {0:F3} > {1:F3}, increased rows: " + "{2}x{3} {4:F3}x{5:F3} ", savedWastedHeight, tnSettings.HeightThreshold, thumbnailGrid.NColumns, thumbnailGrid.NRows, wastedWidth, wastedHeight); } // still need to check this if minimum was set. if (wastedWidth - tnSettings.WidthThreshold < 0.005) break; else { double savedWastedWidth = wastedWidth; newLayout = new ThumbnailPageLayout (originalLayout); thumbnailGrid = ThumbnailGrid.CreateUsingRaw (newLayout, nColumns + 1, thumbnailGrid.NRows, aspectRatio, true); originalLayout.CalcWasted (tnSettings, thumbnailGrid, out wastedWidth, out wastedHeight); THelper.Debug (" Now wasted width {0:F3} > {1:F3}, increased columns: " + "{2}x{3} {4:F3}x{5:F3} ", savedWastedWidth, tnSettings.WidthThreshold, thumbnailGrid.NColumns, thumbnailGrid.NRows, wastedWidth, wastedHeight); } nSteps++; } return thumbnailGrid; #if false if (wastedHeights.Values[0] != nColumns && Math.Abs (desiredWastedHeight - wastedHeights.Keys[0]) < 0.15) { if (debug) THelper.Debug (" {0} columns is close to best.", nColumns); thumbnailGrid = CreateUsingNColumns (layout, nColumns, aspectRatio); } else { if (debug) THelper.Debug (" {0} columns is best.", wastedHeights.Values[0]); thumbnailGrid = CreateUsingNColumns (layout, wastedHeights.Values[0], aspectRatio); } return thumbnailGrid; #endif }
/// <summary> /// Creates the using actual rows and columns specified. /// </summary> /// <param name="layout">The <see cref="ThumbnailPageLayout"/>.</param> /// <param name="tnSettings">The <see cref="ThumbnailSettings"/>.</param> /// <param name="nColumns">The desired number of columns.</param> /// <param name="nRows">The desired number of rows.</param> /// <param name="aspectRatio">The thumbnail aspect ratio.</param> /// <returns> /// new <see cref="ThumbnailGrid"/> /// </returns> public static ThumbnailGrid CreateUsingActual(ThumbnailPageLayout layout, ThumbnailSettings tnSettings, int nColumns, int nRows, double aspectRatio) { double wastedWidth, wastedHeight; bool fitWidth = tnSettings.ThumbAspectRatio > tnSettings.AspectRatio; ThumbnailGrid thumbnailGrid = CreateUsingRaw (layout, nColumns, nRows, aspectRatio, fitWidth); layout.CalcWasted (tnSettings, thumbnailGrid, out wastedWidth, out wastedHeight); THelper.Debug (" Actual specified, using {0}x{1} ({2})", nColumns, nRows, fitWidth ? "FitWidth" : "FitHeight"); THelper.Debug (" {0:F2} aspect ratio", aspectRatio); THelper.Debug (" {0}x{1} {2:F3}x{3:F3}", thumbnailGrid.NColumns, thumbnailGrid.NRows, wastedWidth, wastedHeight); return thumbnailGrid; }