/// <summary> /// Initializes a new instance of the <see cref="ThumbnailWriter"/> class. /// </summary> /// <param name="creator">The <see cref="ThumbnailCreator"/> /// (only used to get a jpeg compression encoder).</param> /// <param name="tgrid">The <see cref="ThumbnailGrid"/>.</param> /// <param name="directory">The directory to write the thumbnail page.</param> /// <param name="displayFilename">The display name of the <see cref="AVFileSet"/> /// from which the thumbnails are generated.</param> /// <param name="outTemplate">The template used to generate page filename.</param> /// <param name="nFiles">The number of files in set (>0 for multi-part videos).</param> /// <param name="stats">The stats of the <see cref="AVFileSet"/> to display /// in header.</param> /// <param name="duration">The duration of the <see cref="AVFileSet"/>.</param> public ThumbnailWriter(ThumbnailCreator creator, ThumbnailGrid tgrid, string directory, string displayFilename, string outTemplate, int nFiles, string stats, TimeSpan duration) { this._creator = creator; this._tgrid = tgrid; this._directory = directory; this._displayFilename = displayFilename; this._outTemplate = outTemplate; this._nFiles = nFiles; this._stats = stats; this._duration = duration; _thumbnailPage = null; }
/// <summary> /// Initializes a new instance of the <see cref="ThumbnailMultiWriter"/> class. /// </summary> /// <param name="creator">The <see cref="ThumbnailCreator"/> /// (only used to get a jpeg compression encoder).</param> /// <param name="tgrid">The <see cref="ThumbnailGrid"/>.</param> /// <param name="directory">The directory to write thumbnail pages.</param> /// <param name="displayFilename">The display name of the <see cref="AVFileSet"/> /// from which the thumbnails are generated.</param> /// <param name="outTemplate">The template used to generate page filenames.</param> /// <param name="nFiles">The number of files in set (>0 for multi-part videos).</param> /// <param name="interval">The interval between thumbnails.</param> /// <param name="stats">The stats of the <see cref="AVFileSet"/> to display /// in header.</param> /// <param name="duration">The duration of the <see cref="AVFileSet"/>.</param> /// <param name="nPages">The total number of thumbnail pages.</param> public ThumbnailMultiWriter(ThumbnailCreator creator, ThumbnailGrid tgrid, string directory, string displayFilename, string outTemplate, int nFiles, TimeSpan interval, string stats, TimeSpan duration, int nPages) { this._creator = creator; this._tgrid = tgrid; this._directory = directory; this._displayFilename = displayFilename; this._outTemplate = outTemplate; this._nFiles = nFiles; this._interval = interval; this._stats = stats; this._duration = duration; this._nPages = nPages; this._pageNum = 1; _thumbnailPage = null; }
/// <summary> /// Initializes a new instance of the <see cref="ThumbnailPage"/> class. /// </summary> /// <param name="creator">The <see cref="ThumbnailCreator"/> /// (only used to get a jpeg compression encoder).</param> /// <param name="tgrid">The <see cref="ThumbnailGrid"/> that specifies /// the page layout.</param> /// <param name="displayFilename">The display name of the <see cref="AVFileSet"/> /// from which the thumbnails are generated.</param> /// <param name="filename">The fullpath of thumbnail page to create.</param> /// <param name="nFiles">The number of files in set (>0 for multi-part videos).</param> /// <param name="time">The time of first thumbnail on page.</param> /// <param name="pageNum">The page number (0 for overview page).</param> /// <param name="duration">The duration of the <see cref="AVFileSet"/>.</param> /// <param name="nPages">The total number of thumbnail pages.</param> /// <param name="stats">The stats of the <see cref="AVFileSet"/> to display /// in header.</param> public ThumbnailPage(ThumbnailCreator creator, ThumbnailGrid tgrid, string displayFilename, string filename, int nFiles, TimeSpan time, int pageNum, TimeSpan duration, int nPages, string stats) { this._creator = creator; this._tgrid = tgrid; this._filename = filename; _pageBitmap = new System.Drawing.Bitmap (tgrid.Layout.Width, tgrid.Layout.Height); _graphics = System.Drawing.Graphics.FromImage (_pageBitmap); _graphics.PageUnit = System.Drawing.GraphicsUnit.Pixel; _graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; //_graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy; _graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; //_graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; _graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None; // can't use TextRenderingHint.ClearTypeGridFit with CompositingMode.SourceCopy //_graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit; //_graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; _graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; // Affects image resizing _graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; // Affects anti-aliasing of filled edges //_graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; _graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; _font = new System.Drawing.Font ("Arial", (float) (7 * creator.TNSettings.ScaleFactor), System.Drawing.FontStyle.Bold); _brushWhite = new System.Drawing.SolidBrush (System.Drawing.Color.White); _brushBlack = new System.Drawing.SolidBrush (System.Drawing.Color.Black); _borderPen = new System.Drawing.Pen (System.Drawing.Color.Wheat, tgrid.Layout.Border <= 1 ? 0 : tgrid.Layout.Border); _borderHilightPen = new System.Drawing.Pen (System.Drawing.Color.Red, tgrid.Layout.Border <= 1 ? 0 : tgrid.Layout.Border); //_borderPen.Alignment = System.Drawing.Drawing2D.PenAlignment.Inset; //_borderPen.LineJoin = System.Drawing.Drawing2D.LineJoin.Miter; _graphics.FillRectangle (_brushBlack, 0, 0, tgrid.Layout.Width, tgrid.Layout.Height); _thumbFormat = new System.Drawing.StringFormat (); switch (creator.TNSettings.LabelPosition) { case ThumbnailSettings.LabelPositions.None: case ThumbnailSettings.LabelPositions.LowerRight: { _thumbFormat.LineAlignment = System.Drawing.StringAlignment.Far; _thumbFormat.Alignment = System.Drawing.StringAlignment.Far; break; } case ThumbnailSettings.LabelPositions.LowerLeft: { _thumbFormat.LineAlignment = System.Drawing.StringAlignment.Far; _thumbFormat.Alignment = System.Drawing.StringAlignment.Near; break; } case ThumbnailSettings.LabelPositions.UpperRight: { _thumbFormat.LineAlignment = System.Drawing.StringAlignment.Near; _thumbFormat.Alignment = System.Drawing.StringAlignment.Far; break; } case ThumbnailSettings.LabelPositions.UpperLeft: { _thumbFormat.LineAlignment = System.Drawing.StringAlignment.Near; _thumbFormat.Alignment = System.Drawing.StringAlignment.Near; break; } } _headerFormat = new System.Drawing.StringFormat (); _headerFormat.LineAlignment = System.Drawing.StringAlignment.Center; _headerFormat.Alignment = System.Drawing.StringAlignment.Near; float inset = 2*tgrid.Layout.Margin; System.Drawing.RectangleF headerRectF = new System.Drawing.RectangleF (inset, 0, this._tgrid.Layout.Width - 2*inset, this._tgrid.Layout.HeaderHeight); //_graphics.DrawRectangle (_borderPen, // headerRectF.X, // headerRectF.Y, // headerRectF.Width, // headerRectF.Height); string leftSide; string timeformat = @"h\:mm\:ss"; if (time.Milliseconds > 0 && creator.TNSettings.AlwaysShowMilliseconds) timeformat = @"h\:mm\:ss\.ffff"; if (pageNum > 0) leftSide = String.Format ("{0} / {1} ({2} of {3})", time.ToString (timeformat), duration.ToString (@"h\:mm\:ss"), pageNum, nPages); else leftSide = String.Format ("{0}", duration.ToString (@"h\:mm\:ss")); if (nFiles > 0) leftSide += String.Format (" {0} files", nFiles); using (System.Drawing.Font headerFont = new System.Drawing.Font ( ThumbnailPageLayout.FONT_NAME, (float) (ThumbnailPageLayout.FONT_SIZE * creator.TNSettings.ScaleFactor), System.Drawing.FontStyle.Bold)) { _graphics.DrawString (leftSide, headerFont, _brushWhite, headerRectF, _headerFormat); _headerFormat.Alignment = System.Drawing.StringAlignment.Far; _graphics.DrawString (stats, headerFont, _brushWhite, headerRectF, _headerFormat); float left = headerRectF.Left + _graphics.MeasureString(leftSide, headerFont).Width; float right = headerRectF.Right - _graphics.MeasureString (stats, headerFont).Width; headerRectF = new System.Drawing.RectangleF ( left, headerRectF.Top, right - left, headerRectF.Height); _headerFormat.Alignment = System.Drawing.StringAlignment.Center; _graphics.DrawString (displayFilename, headerFont, _brushWhite, headerRectF, _headerFormat); } _pageNum = pageNum; _currentCol = 0; _currentRow = 0; }
/// <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> /// Processes the file as media item. OBSOLETE /// </summary> /// <param name="filename">The filename.</param> /// <param name="outputDirectory">The output directory.</param> private void processFile(string filename, string outputDirectory) { THelper.Information ("Processing {0} ...", filename); DateTime startTime = DateTime.Now; MSEEncoder.MediaItem mediaItem; try { mediaItem = new MSEEncoder.MediaItem (filename); } catch (MSEEncoder.InvalidMediaFileException) { THelper.Critical("\"" + filename + "\" isn't a video file."); return; } bool hasVideo = (mediaItem.OriginalFileType & MSEEncoder.FileType.Video) == MSEEncoder.FileType.Video; if (!hasVideo) { THelper.Critical ("\"" + filename + "\" isn't a video file."); return; } if (_tnSettings.End == TimeSpan.Zero) _tnSettings.End = mediaItem.FileDuration - new TimeSpan (0, 0, 5); else if (_tnSettings.End < TimeSpan.Zero) _tnSettings.End = mediaItem.FileDuration + _tnSettings.End; else if (_tnSettings.End > mediaItem.FileDuration) _tnSettings.End = mediaItem.FileDuration; DateTime mediaItemCreated = DateTime.Now; THelper.Information ("{0} to create Microsoft.Encoder.MediaItem.", (mediaItemCreated - startTime).ToString(@"h\:mm\:ss")); ThumbnailCreator tg; DateTime overviewCreated; int nThumbs; int originalBorder = _tnSettings.Border; _tnSettings.SrcRect = new System.Drawing.Rectangle (0, 0, mediaItem.OriginalVideoSize.Width, mediaItem.OriginalVideoSize.Height); double videoAspect = (double) mediaItem.OriginalVideoSize.Width / mediaItem.OriginalVideoSize.Height; _tnSettings.ThumbAspectRatio = videoAspect; int x, y, newWidth, newHeight; if (_cropAspect != 0.0) { if (_cropAspect > videoAspect) { x = 0; newWidth = mediaItem.OriginalVideoSize.Width; newHeight = (int) (mediaItem.OriginalVideoSize.Width / _cropAspect + 0.5); y = (int) ((mediaItem.OriginalVideoSize.Height - newHeight) / 2.0); } else { y = 0; newHeight = mediaItem.OriginalVideoSize.Height; newWidth = (int) (mediaItem.OriginalVideoSize.Height * _cropAspect + 0.5); x = (int) ((mediaItem.OriginalVideoSize.Width - newWidth) / 2.0); } _tnSettings.SrcRect = new System.Drawing.Rectangle (x, y, newWidth, newHeight); _tnSettings.ThumbAspectRatio = (double) newWidth / newHeight; } if (_stretchAspect != 0.0) { _tnSettings.ThumbAspectRatio = _stretchAspect; } if (!_skipOverview) { _tnSettings.Border = 1; tg = new ThumbnailCreator (_tnSettings, _debug); nThumbs = tg.GenerateOverviewThumbs (mediaItem, filename, outputDirectory); overviewCreated = DateTime.Now; THelper.Information ("{0} to create overview thumbnails.", (overviewCreated - mediaItemCreated).ToString(@"h\:mm\:ss")); THelper.Information ("{0} thumbs created. {1:F2} seconds / thumb.", nThumbs, (overviewCreated - mediaItemCreated).TotalSeconds / nThumbs); } else { overviewCreated = DateTime.Now; THelper.Information ("Overview page skipped."); } _tnSettings.Border = originalBorder; tg = new ThumbnailCreator (_tnSettings, _debug); nThumbs = 0; if (_tnSettings.Interval.TotalSeconds > 0) { TimeSpan originalInterval = _tnSettings.Interval; if (mediaItem.FileDuration.TotalMinutes < 45 && originalInterval.TotalSeconds > 2) _tnSettings.Interval = new TimeSpan (0, 0, 2); nThumbs = tg.GenerateMultiThumbs (mediaItem, filename, outputDirectory); _tnSettings.Interval = originalInterval; } DateTime multiCreated = DateTime.Now; if (nThumbs > 0) { THelper.Information ("{0} to generate multi-page thumbnails.", (multiCreated - overviewCreated).ToString(@"h\:mm\:ss")); THelper.Information ("{0} thumbs created. {1:F2} seconds / thumb.", nThumbs, (multiCreated - overviewCreated).TotalSeconds / nThumbs); } else { THelper.Information ("Multi-page thumbnails skipped."); } THelper.Information ("{0} overall time to process {1}.", (multiCreated - startTime).ToString(@"h\:mm\:ss"), filename); THelper.Information (); }
/// <summary> /// Generate thumbnail pages for the set of video files in list. /// </summary> /// <param name="filenames">A list of video files. Only a single /// thumbnail set is generated. Multiple files are /// treated as one long video.</param> /// <param name="displayFilename">The display filename to use for the video file /// set.</param> /// <param name="outputDirectory">The output directory.</param> private void ProcessFiles(List<string> filenames, string displayFilename, string outputDirectory) { DateTime startTime = DateTime.Now; AVFileSet avFiles = new AVFileSet (); MSEEncoder.AudioVideoFile avFile; DateTime tempStart, tempEnd; foreach (string filename in filenames) { try { THelper.Information ("Processing {0} ...", filename); tempStart = DateTime.Now; avFile = new MSEEncoder.AudioVideoFile (filename); tempEnd = DateTime.Now; THelper.Debug ("{0} to create Microsoft.Encoder.AudioVideoFile.", (tempEnd - tempStart).ToString (@"h\:mm\:ss\.ff")); } catch (MSEEncoder.InvalidMediaFileException) { THelper.Critical ("\"" + filename + "\" isn't a video file."); return; } tempStart = DateTime.Now; MSEEncoder.MediaItem mediaItem = new MSEEncoder.MediaItem (avFile); tempEnd = DateTime.Now; THelper.Debug ("{0} to create Microsoft.Encoder.MediaItem.", (tempEnd - tempStart).ToString (@"h\:mm\:ss\.ff")); bool hasVideo = (mediaItem.OriginalFileType & MSEEncoder.FileType.Video) == MSEEncoder.FileType.Video; if (!hasVideo) { THelper.Critical ("\"" + filename + "\" isn't a video file."); return; } tempStart = DateTime.Now; avFile.CalculateDuration (AVFileSet.IndexProgessHandler); Console.Write ("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); tempEnd = DateTime.Now; THelper.Debug ("{0} to run CalculateDuration.", (tempEnd - tempStart).ToString (@"h\:mm\:ss\.ff")); THelper.Debug ("AudioVideoFile.Duration {0} {1}.", avFile.Duration.ToString (@"h\:mm\:ss\.ffff"), filename); THelper.Debug ("VideoStream.Duration {0} {1}.", AVFileSet.GetVideoDuration(avFile).ToString (@"h\:mm\:ss\.ffff"), filename); THelper.Debug ("AudioStream.Duration {0} {1}.", AVFileSet.GetAudioDuration(avFile).ToString (@"h\:mm\:ss\.ffff"), filename); THelper.Debug ("AudioStream channels = {0} {1}.", AVFileSet.GetAudioChannels(avFile), filename); avFiles.Add (avFile); } avFiles.UpdateTotals (); DateTime avFileSetCreated = DateTime.Now; THelper.Information ("{0} Total time to create AVFileSet.", (avFileSetCreated - startTime).ToString (@"h\:mm\:ss")); THelper.Debug ("Using {0} Layout Mode.", _tnSettings.LayoutMode); if (_tnSettings.End == TimeSpan.Zero) _tnSettings.End = avFiles.TotalDuration; else if (_tnSettings.End < TimeSpan.Zero) _tnSettings.End = avFiles.TotalDuration + _tnSettings.End; else if (_tnSettings.End > avFiles.TotalDuration) _tnSettings.End = avFiles.TotalDuration; THelper.Information ( "Thumbnails Range {0} -> {1}", _tnSettings.Start.ToString(@"h\:mm\:ss\.fff"), _tnSettings.End.ToString (@"h\:mm\:ss\.fff")); THelper.Information ("Thumbnail Duration {0} (Total {1})", (_tnSettings.End - _tnSettings.Start).ToString(@"h\:mm\:ss\.fff"), avFiles.TotalDuration.ToString (@"h\:mm\:ss\.fff")); avFile = avFiles[0]; System.Drawing.Size videoSize = AVFileSet.GetVideoSize(avFile); if (outputDirectory != null) THelper.Information ("OutputDirectory is \"{0}\"", outputDirectory); string baseDirectory = outputDirectory; if (outputDirectory == null) { outputDirectory = ThumbnailCreator.GetDirectoryName (avFile.FileName); baseDirectory = outputDirectory; if (_tnSettings.SubDirectory.Length > 0) { outputDirectory = System.IO.Path.Combine (outputDirectory, _tnSettings.SubDirectory); if (!System.IO.Directory.Exists (outputDirectory)) System.IO.Directory.CreateDirectory (outputDirectory); } } if (displayFilename == null) displayFilename = avFiles.GetDisplayName (baseDirectory); ThumbnailCreator creator; DateTime overviewCreated; int nThumbs; int originalBorder = _tnSettings.Border; _tnSettings.SrcRect = new System.Drawing.Rectangle (0, 0, videoSize.Width, videoSize.Height); double videoAspect = (double) videoSize.Width / videoSize.Height; _tnSettings.ThumbAspectRatio = videoAspect; THelper.Debug ("Video Frame Size {0}x{1} ({2:F2})", videoSize.Width, videoSize.Height, videoAspect); bool manualSrcRect = false; if (_srcRect.Width != 0 && _srcRect.Height != 0) { _tnSettings.SetSrcRect (_srcRect); manualSrcRect = true; THelper.Information ("Changing video rectangle from 0,0+{0}x{1} to {2},{3}+{4}x{5}", videoSize.Width, videoSize.Height, _srcRect.X, _srcRect.Y, _srcRect.Width, _srcRect.Height); } else if (_cropAspect != 0.0) { _tnSettings.AdjustThumbAspectRatio (_cropAspect, videoAspect, videoSize); manualSrcRect = true; THelper.Information ("Cropping aspect ratio from {0:F3} to {1:F3}", videoAspect, _cropAspect); } if (_stretchAspect != 0.0) { _tnSettings.ThumbAspectRatio = _stretchAspect; manualSrcRect = true; THelper.Information ("Stretching aspect ratio from {0:F3} to {1:F3}", videoAspect, _stretchAspect); } if (!manualSrcRect && _autoAspectRatio) { double displayAspect = AVFileSet.GetAspectRatio(avFile); if (Math.Abs(videoAspect - displayAspect) > 0.05) { //if (displayAspect > videoAspect) // displayAspect -= 0.01; //else // displayAspect += 0.01; _tnSettings.AdjustThumbAspectRatio (displayAspect, videoAspect, videoSize); THelper.Information ("Auto adjusting aspect ratio from {0:F3} to {1:F3}", videoAspect, displayAspect); } } string outTemplate; if (_createOverview) { //_tnSettings.Border = 1; creator = new ThumbnailCreator (_tnSettings, null); outTemplate = System.IO.Path.GetFileNameWithoutExtension (displayFilename) + "_overview.jpg"; nThumbs = creator.GenerateOverviewThumbs (avFiles, displayFilename, outTemplate, outputDirectory); overviewCreated = DateTime.Now; THelper.Information ("{0} to create Overview thumbnails.", (overviewCreated - avFileSetCreated).ToString (@"h\:mm\:ss")); THelper.Information ("{0} thumbnails created. {1:F2} seconds / thumbnail.", nThumbs, (overviewCreated - avFileSetCreated).TotalSeconds / nThumbs); } else { overviewCreated = DateTime.Now; THelper.Information ("Overview page skipped."); } _tnSettings.Border = originalBorder; if (_tnSettings.Interval.TotalSeconds > 0) { nThumbs = 0; creator = new ThumbnailCreator (_tnSettings, null); TimeSpan originalInterval = _tnSettings.Interval; if (_autoInterval) { IEnumerator<KeyValuePair<int,int>> ranges = _autoIntervals.GetEnumerator (); ranges.MoveNext (); KeyValuePair<int,int> range = ranges.Current; int interval = range.Value; int maxInterval = interval; double totalMinutes = (_tnSettings.End - _tnSettings.Start).TotalMinutes; while (ranges.MoveNext ()) { range = ranges.Current; if (totalMinutes < range.Key) { THelper.Information ("Duration {0:F2} < {1} minutes. AutoInterval is {2} seconds.", totalMinutes, range.Key, range.Value); interval = range.Value; break; } } _tnSettings.Interval = new TimeSpan (0, 0, interval); if (interval == maxInterval) THelper.Information ("Duration {0:F2} > {1} minutes. AutoInterval is {2} seconds", totalMinutes, range.Key, interval); } outTemplate = System.IO.Path.GetFileNameWithoutExtension (displayFilename); outTemplate = outTemplate.Replace ("{", "("); outTemplate = outTemplate.Replace ("}", ")"); outTemplate = outTemplate + "_page{0:D4}.jpg"; nThumbs = creator.GenerateDetailThumbs (avFiles, displayFilename, outTemplate, outputDirectory); _tnSettings.Interval = originalInterval; DateTime detailsCreated = DateTime.Now; if (nThumbs > 0) { THelper.Information ("{0} to generate Detail page thumbnails.", (detailsCreated - overviewCreated).ToString (@"h\:mm\:ss")); THelper.Information ("{0} thumbnails created. {1:F2} seconds / thumbnail.", nThumbs, (detailsCreated - overviewCreated).TotalSeconds / nThumbs); } } else { THelper.Information ("Detail page thumbnails skipped."); } DateTime overall = DateTime.Now; THelper.Information ("{0} overall time to process {1}.", (overall - startTime).ToString (@"h\:mm\:ss"), displayFilename); THelper.Information (); }