public static bool WriteBDNXmlFile(TextSubtitle subtitle, string fileName, int videoWidth, int videoHeight, float fps) { if (File.Exists(fileName)) { return(false); } string partFileName = Path.GetFileNameWithoutExtension(fileName); XmlDocument outputDocument = new XmlDocument(); outputDocument.AppendChild(outputDocument.CreateXmlDeclaration("1.0", "UTF-8", null)); XmlNode docNode = outputDocument.CreateElement("BDN"); outputDocument.AppendChild(docNode); AppendAttribute(docNode, "Version", "0.93", outputDocument); AppendAttribute(docNode, "xsi", "noNamespaceSchemaLocation", "http://www.w3.org/2001/XMLSchema-instance", "BD-03-006-0093b BDN File Format.xsd", outputDocument); XmlNode descNode = outputDocument.CreateElement("Description"); docNode.AppendChild(descNode); XmlNode workNode = outputDocument.CreateElement("Name"); AppendAttribute(workNode, "Title", partFileName, outputDocument); AppendAttribute(workNode, "Content", string.Empty, outputDocument); descNode.AppendChild(workNode); workNode = outputDocument.CreateElement("Language"); AppendAttribute(workNode, "Code", string.Empty, outputDocument); descNode.AppendChild(workNode); workNode = outputDocument.CreateElement("Format"); AppendAttribute(workNode, "VideoFormat", string.Format("{0:0}p", videoHeight), outputDocument); AppendAttribute(workNode, "FrameRate", string.Format(AppSettings.CInfo, "{0:0.000}", fps), outputDocument); AppendAttribute(workNode, "DropFrame", "False", outputDocument); descNode.AppendChild(workNode); workNode = outputDocument.CreateElement("Events"); AppendAttribute(workNode, "Type", "Graphic", outputDocument); AppendAttribute(workNode, "FirstEventInTC", CreateBDNTimeStamp(subtitle.Captions.First().StartTime, fps), outputDocument); AppendAttribute(workNode, "LastEventOutTC", CreateBDNTimeStamp(subtitle.Captions.Last().EndTime, fps), outputDocument); AppendAttribute(workNode, "NumberofEvents", subtitle.Captions.Count.ToString(AppSettings.CInfo), outputDocument); descNode.AppendChild(workNode); XmlNode eventNode = outputDocument.CreateElement("Events"); docNode.AppendChild(eventNode); int i = 0; foreach (SubCaption caption in subtitle.Captions) { ImageHolder image = PNGImage.CreateImage(caption, subtitle.Style, i, videoWidth, videoHeight, fileName); if (string.IsNullOrEmpty(image.FileName) || image.Width == 0 || image.Height == 0) { continue; } workNode = outputDocument.CreateElement("Event"); AppendAttribute(workNode, "InTC", CreateBDNTimeStamp(caption.StartTime, fps), outputDocument); AppendAttribute(workNode, "OutTC", CreateBDNTimeStamp(caption.EndTime, fps), outputDocument); AppendAttribute(workNode, "Forced", "False", outputDocument); eventNode.AppendChild(workNode); XmlNode gNode = outputDocument.CreateElement("Graphic"); AppendAttribute(gNode, "Width", image.Width.ToString(AppSettings.CInfo), outputDocument); AppendAttribute(gNode, "Height", image.Height.ToString(AppSettings.CInfo), outputDocument); int posX = (int)Math.Ceiling((float)videoWidth / 2 - (float)image.Width / 2); int posY = videoHeight - image.Height - 120; AppendAttribute(gNode, "X", posX.ToString(AppSettings.CInfo), outputDocument); AppendAttribute(gNode, "Y", posY.ToString(AppSettings.CInfo), outputDocument); gNode.InnerText = image.FileName; workNode.AppendChild(gNode); i++; } outputDocument.Save(fileName); return(true); }
public static ImageHolder CreateImage(SubCaption caption, SubtitleStyle style, int number, int videoWidth, int videoHeight, string baseFName) { _boldStyle = false; _italicStyle = false; _underlineStyle = false; _strikeStyle = false; ImageHolder result = new ImageHolder(); if (string.IsNullOrEmpty(baseFName)) { return(new ImageHolder()); } string basePath = Path.GetDirectoryName(baseFName); string baseName = Path.GetFileNameWithoutExtension(baseFName); if (string.IsNullOrEmpty(basePath) || string.IsNullOrEmpty(baseName)) { return(new ImageHolder()); } result.FileName = string.Format(AppSettings.CInfo, "{0}_{1:g}.png", Path.Combine(basePath, baseName), number); SizeF imgSize = new SizeF(); FontStyle styleFontStyle = FontStyle.Regular; if (style.Bold) { styleFontStyle = styleFontStyle | FontStyle.Bold; } if (style.Italic) { styleFontStyle = styleFontStyle | FontStyle.Italic; } Font styleFont = new Font(style.FontName, style.FontSize, styleFontStyle, GraphicsUnit.Point); StringFormat stringFormat = new StringFormat(); List <SizeF> lineSizes = new List <SizeF>(); string rawText = Regex.Replace(caption.Text, "</*?(?:i|b)>", "", RegexOptions.Singleline | RegexOptions.Multiline); string[] rawTextLines = rawText.Split(new[] { Environment.NewLine }, StringSplitOptions.None); foreach (string rawTextLine in rawTextLines) { using (GraphicsPath rawLinePath = new GraphicsPath()) { rawLinePath.AddString(rawTextLine, styleFont.FontFamily, (int)styleFontStyle, styleFont.SizeInPoints, new PointF(), stringFormat); lineSizes.Add(rawLinePath.GetBounds().Size); } } string[] textLines = caption.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None); float lastLineBreak = 0f; foreach (SizeF lineSize in lineSizes) { imgSize.Height += lineSize.Height; lastLineBreak = lineSize.Height / 3; imgSize.Height += lastLineBreak; if (lineSize.Width > imgSize.Width) { imgSize.Width = lineSize.Width; } } imgSize.Height -= lastLineBreak; if (imgSize.IsEmpty) { return(new ImageHolder()); } stringFormat.SetMeasurableCharacterRanges(new[] { new CharacterRange(0, 1) }); RectangleF whiteSpace; using (Image img = new Bitmap((int)imgSize.Width, (int)imgSize.Height, PixelFormat.Format32bppArgb)) { using (Graphics g = Graphics.FromImage(img)) { RectangleF origin = new RectangleF(new PointF(0f, 0f), imgSize); Region[] regions2 = g.MeasureCharacterRanges(" .", styleFont, origin, stringFormat); if (!regions2.Any()) { return(new ImageHolder()); } whiteSpace = regions2[0].GetBounds(g); } } GraphicsPath wordpath = new GraphicsPath(); GraphicsPath wordPathShadow = new GraphicsPath(); int shadowOffset = style.Shadow; RectangleF wStart = new RectangleF { Y = 0, X = 0 }; RectangleF wStartShadow = wStart; wStartShadow.Offset(shadowOffset, shadowOffset); for (int i = 0; i < textLines.Length; i++) { string textLine = textLines[i]; SizeF lineSize = lineSizes[i]; wStart.Offset(imgSize.Width / 2 - lineSize.Width / 2, 0); wStartShadow.Offset(imgSize.Width / 2 - lineSize.Width / 2, 0); string[] words = textLine.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries); foreach (string word in words) { using (GraphicsPath singleWord = new GraphicsPath(), singleWordShadow = new GraphicsPath()) { string lWord; FontStyle fontStyle = GetStyleFont(word, out lWord, styleFontStyle); if (string.IsNullOrEmpty(lWord)) { continue; } singleWord.AddString(lWord, styleFont.FontFamily, (int)fontStyle, styleFont.SizeInPoints, wStart.Location, stringFormat); singleWordShadow.AddString(lWord, styleFont.FontFamily, (int)fontStyle, styleFont.SizeInPoints, wStartShadow.Location, stringFormat); wordpath.AddPath(singleWord, false); wordPathShadow.AddPath(singleWordShadow, false); wStart.Offset(singleWord.GetBounds().Size.Width + whiteSpace.Size.Width, 0); wStartShadow.Offset(singleWordShadow.GetBounds().Size.Width + whiteSpace.Size.Width, 0); } } wStart.X = 0; wStart.Offset(0, lineSize.Height + lineSize.Height / 3); wStartShadow.X = shadowOffset; wStartShadow.Offset(0, lineSize.Height + lineSize.Height / 3); } imgSize.Width = wordPathShadow.GetBounds().Right; imgSize.Height = wordPathShadow.GetBounds().Bottom; using (Image img = new Bitmap((int)imgSize.Width + style.MarginL + style.MarginR, (int)imgSize.Height + style.MarginV * 2, PixelFormat.Format32bppArgb)) { using (Graphics g = Graphics.FromImage(img)) { g.CompositingMode = CompositingMode.SourceOver; g.CompositingQuality = CompositingQuality.HighQuality; g.TextRenderingHint = TextRenderingHint.AntiAlias; g.SmoothingMode = SmoothingMode.HighQuality; g.PixelOffsetMode = PixelOffsetMode.HighQuality; g.InterpolationMode = InterpolationMode.High; Brush primBrush = new SolidBrush(style.PrimaryColor); Brush shadowBrush = new SolidBrush(Color.FromArgb(64, style.BackColor)); Pen outPen = new Pen(style.OutlineColor) { Alignment = PenAlignment.Outset }; if (style.BorderStyle == 1) { outPen.Width = style.Outline == 0 && style.Shadow > 0 ? 1 : style.Outline; style.Outline = (int)outPen.Width; } g.FillRectangle(Brushes.Transparent, 0, 0, img.Width, img.Height); // draw shadow if (style.BorderStyle == 1 && style.Shadow > 0) { g.FillPath(shadowBrush, wordPathShadow); } g.FillPath(primBrush, wordpath); // draw outline if (style.BorderStyle == 1 && style.Outline > 0) { g.DrawPath(outPen, wordpath); } } img.Save(result.FileName, ImageFormat.Png); result.FileName = Path.GetFileName(result.FileName); result.Height = img.Height; result.Width = img.Width; } return(result); }
public static ImageHolder CreateImage(SubCaption caption, SubtitleStyle style, int number, int videoWidth, int videoHeight, string baseFName) { _boldStyle = false; _italicStyle = false; _underlineStyle = false; _strikeStyle = false; ImageHolder result = new ImageHolder(); if (string.IsNullOrEmpty(baseFName)) return new ImageHolder(); string basePath = Path.GetDirectoryName(baseFName); string baseName = Path.GetFileNameWithoutExtension(baseFName); if (string.IsNullOrEmpty(basePath) || string.IsNullOrEmpty(baseName)) return new ImageHolder(); result.FileName = string.Format(AppSettings.CInfo, "{0}_{1:g}.png", Path.Combine(basePath, baseName), number); SizeF imgSize = new SizeF(); FontStyle styleFontStyle = FontStyle.Regular; if (style.Bold) styleFontStyle = styleFontStyle | FontStyle.Bold; if (style.Italic) styleFontStyle = styleFontStyle | FontStyle.Italic; Font styleFont = new Font(style.FontName, style.FontSize, styleFontStyle, GraphicsUnit.Point); StringFormat stringFormat = new StringFormat(); List<SizeF> lineSizes = new List<SizeF>(); string rawText = Regex.Replace(caption.Text, "</*?(?:i|b)>", "", RegexOptions.Singleline | RegexOptions.Multiline); string[] rawTextLines = rawText.Split(new[] {Environment.NewLine}, StringSplitOptions.None); foreach (string rawTextLine in rawTextLines) { using (GraphicsPath rawLinePath = new GraphicsPath()) { rawLinePath.AddString(rawTextLine, styleFont.FontFamily, (int) styleFontStyle, styleFont.SizeInPoints, new PointF(), stringFormat); lineSizes.Add(rawLinePath.GetBounds().Size); } } string[] textLines = caption.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None); float lastLineBreak = 0f; foreach (SizeF lineSize in lineSizes) { imgSize.Height += lineSize.Height; lastLineBreak = lineSize.Height/3; imgSize.Height += lastLineBreak; if (lineSize.Width > imgSize.Width) imgSize.Width = lineSize.Width; } imgSize.Height -= lastLineBreak; if (imgSize.IsEmpty) return new ImageHolder(); stringFormat.SetMeasurableCharacterRanges(new[] { new CharacterRange(0, 1) }); RectangleF whiteSpace; using (Image img = new Bitmap((int)imgSize.Width, (int)imgSize.Height, PixelFormat.Format32bppArgb)) { using (Graphics g = Graphics.FromImage(img)) { RectangleF origin = new RectangleF(new PointF(0f,0f), imgSize); Region[] regions2 = g.MeasureCharacterRanges(" .", styleFont, origin, stringFormat); if (!regions2.Any()) return new ImageHolder(); whiteSpace = regions2[0].GetBounds(g); } } GraphicsPath wordpath = new GraphicsPath(); GraphicsPath wordPathShadow = new GraphicsPath(); int shadowOffset = style.Shadow; RectangleF wStart = new RectangleF { Y = 0, X = 0 }; RectangleF wStartShadow = wStart; wStartShadow.Offset(shadowOffset, shadowOffset); for (int i = 0; i < textLines.Length; i++) { string textLine = textLines[i]; SizeF lineSize = lineSizes[i]; wStart.Offset(imgSize.Width / 2 - lineSize.Width / 2, 0); wStartShadow.Offset(imgSize.Width / 2 - lineSize.Width / 2, 0); string[] words = textLine.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries); foreach (string word in words) { using (GraphicsPath singleWord = new GraphicsPath(), singleWordShadow = new GraphicsPath()) { string lWord; FontStyle fontStyle = GetStyleFont(word, out lWord, styleFontStyle); if (string.IsNullOrEmpty(lWord)) continue; singleWord.AddString(lWord, styleFont.FontFamily, (int) fontStyle, styleFont.SizeInPoints, wStart.Location, stringFormat); singleWordShadow.AddString(lWord, styleFont.FontFamily, (int) fontStyle, styleFont.SizeInPoints, wStartShadow.Location, stringFormat); wordpath.AddPath(singleWord, false); wordPathShadow.AddPath(singleWordShadow, false); wStart.Offset(singleWord.GetBounds().Size.Width + whiteSpace.Size.Width, 0); wStartShadow.Offset(singleWordShadow.GetBounds().Size.Width + whiteSpace.Size.Width, 0); } } wStart.X = 0; wStart.Offset(0, lineSize.Height + lineSize.Height / 3); wStartShadow.X = shadowOffset; wStartShadow.Offset(0, lineSize.Height + lineSize.Height / 3); } imgSize.Width = wordPathShadow.GetBounds().Right; imgSize.Height = wordPathShadow.GetBounds().Bottom; using (Image img = new Bitmap((int)imgSize.Width + style.MarginL + style.MarginR, (int)imgSize.Height + style.MarginV * 2, PixelFormat.Format32bppArgb)) { using (Graphics g = Graphics.FromImage(img)) { g.CompositingMode = CompositingMode.SourceOver; g.CompositingQuality = CompositingQuality.HighQuality; g.TextRenderingHint = TextRenderingHint.AntiAlias; g.SmoothingMode = SmoothingMode.HighQuality; g.PixelOffsetMode = PixelOffsetMode.HighQuality; g.InterpolationMode = InterpolationMode.High; Brush primBrush = new SolidBrush(style.PrimaryColor); Brush shadowBrush = new SolidBrush(Color.FromArgb(64, style.BackColor)); Pen outPen = new Pen(style.OutlineColor) {Alignment = PenAlignment.Outset}; if (style.BorderStyle == 1) { outPen.Width = style.Outline == 0 && style.Shadow > 0 ? 1 : style.Outline; style.Outline = (int) outPen.Width; } g.FillRectangle(Brushes.Transparent, 0, 0, img.Width, img.Height); // draw shadow if (style.BorderStyle == 1 && style.Shadow > 0) g.FillPath(shadowBrush, wordPathShadow); g.FillPath(primBrush, wordpath); // draw outline if (style.BorderStyle == 1 && style.Outline > 0) g.DrawPath(outPen, wordpath); } img.Save(result.FileName, ImageFormat.Png); result.FileName = Path.GetFileName(result.FileName); result.Height = img.Height; result.Width = img.Width; } return result; }