private static Font GetFont(MakeBitmapParameter parameter, float fontSize) { Font font; try { var fontStyle = FontStyle.Regular; if (parameter.SubtitleFontBold) { fontStyle = FontStyle.Bold; } font = new Font(parameter.SubtitleFontName, fontSize, fontStyle); } catch (Exception exception) { try { var fontStyle = FontStyle.Regular; if (!parameter.SubtitleFontBold) { fontStyle = FontStyle.Bold; } font = new Font(parameter.SubtitleFontName, fontSize, fontStyle); } catch { MessageBox.Show(exception.Message); if (FontFamily.Families[0].IsStyleAvailable(FontStyle.Regular)) { font = new Font(FontFamily.Families[0].Name, fontSize); } else if (FontFamily.Families.Length > 1 && FontFamily.Families[1].IsStyleAvailable(FontStyle.Regular)) { font = new Font(FontFamily.Families[1].Name, fontSize); } else if (FontFamily.Families.Length > 2 && FontFamily.Families[1].IsStyleAvailable(FontStyle.Regular)) { font = new Font(FontFamily.Families[2].Name, fontSize); } else { font = new Font("Arial", fontSize); } } } return(font); }
private float GetFontHeight() { if (comboBoxSubtitleFont.SelectedItem == null || comboBoxSubtitleFontSize.SelectedItem == null) { return(Configuration.Settings.Tools.ExportLastLineHeight); } var mbp = new MakeBitmapParameter { SubtitleFontName = comboBoxSubtitleFont.SelectedItem.ToString(), SubtitleFontSize = int.Parse(comboBoxSubtitleFontSize.SelectedItem.ToString()), SubtitleFontBold = checkBoxBold.Checked, }; var fontSize = (float)TextDraw.GetFontSize(mbp.SubtitleFontSize); using (var font = GetFont(mbp, fontSize)) using (var bmp = new Bitmap(100, 100)) using (var g = Graphics.FromImage(bmp)) { var textSize = g.MeasureString("Hj!", font); return(textSize.Height); } }
/// <summary> /// The calc width via draw. /// </summary> /// <param name="text"> /// The text. /// </param> /// <param name="parameter"> /// The parameter. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> private static int CalcWidthViaDraw(string text, MakeBitmapParameter parameter) { // text = HtmlUtil.RemoveHtmlTags(text, true).Trim(); text = text.Trim(); var path = new GraphicsPath(); var sb = new StringBuilder(); int i = 0; bool isItalic = false; bool isBold = parameter.SubtitleFontBold; const float top = 5f; bool newLine = false; float left = 1.0f; float leftMargin = left; int newLinePathPoint = -1; Color c = parameter.SubtitleColor; var colorStack = new Stack<Color>(); var lastText = new StringBuilder(); var sf = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Near }; var bmp = new Bitmap(parameter.ScreenWidth, 200); var g = Graphics.FromImage(bmp); g.CompositingQuality = CompositingQuality.HighSpeed; g.SmoothingMode = SmoothingMode.HighSpeed; g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; Font font = SetFont(parameter, parameter.SubtitleFontSize); while (i < text.Length) { if (text.Substring(i).StartsWith("<font ", StringComparison.OrdinalIgnoreCase)) { float addLeft = 0; int oldPathPointIndex = path.PointCount; if (oldPathPointIndex < 0) { oldPathPointIndex = 0; } if (sb.Length > 0) { lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); } if (path.PointCount > 0) { var list = (PointF[])path.PathPoints.Clone(); // avoid using very slow path.PathPoints indexer!!! for (int k = oldPathPointIndex; k < list.Length; k++) { if (list[k].X > addLeft) { addLeft = list[k].X; } } } if (path.PointCount == 0) { addLeft = left; } else if (addLeft < 0.01) { addLeft = left + 2; } left = addLeft; DrawShadowAndPath(parameter, g, path); var p2 = new SolidBrush(c); g.FillPath(p2, path); p2.Dispose(); path.Reset(); path = new GraphicsPath(); sb = new StringBuilder(); int endIndex = text.Substring(i).IndexOf('>'); if (endIndex < 0) { i += 9999; } else { string fontContent = text.Substring(i, endIndex); if (fontContent.Contains(" color=")) { string[] arr = fontContent.Substring(fontContent.IndexOf(" color=", StringComparison.Ordinal) + 7).Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (arr.Length > 0) { string fontColor = arr[0].Trim('\'').Trim('"').Trim('\''); try { colorStack.Push(c); // save old color if (fontColor.StartsWith("rgb(")) { arr = fontColor.Remove(0, 4).TrimEnd(')').Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); c = Color.FromArgb(int.Parse(arr[0]), int.Parse(arr[1]), int.Parse(arr[2])); } else { c = ColorTranslator.FromHtml(fontColor); } } catch { c = parameter.SubtitleColor; } } } i += endIndex; } } else if (text.Substring(i).StartsWith("</font>", StringComparison.OrdinalIgnoreCase)) { if (text.Substring(i).ToLower().Replace("</font>", string.Empty).Length > 0) { if (lastText.EndsWith(' ') && !sb.StartsWith(' ')) { string t = sb.ToString(); sb.Clear(); sb.Append(' '); sb.Append(t); } float addLeft = 0; int oldPathPointIndex = path.PointCount - 1; if (oldPathPointIndex < 0) { oldPathPointIndex = 0; } if (sb.Length > 0) { if (lastText.Length > 0 && left > 2) { left -= 1.5f; } lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); } if (path.PointCount > 0) { var list = (PointF[])path.PathPoints.Clone(); // avoid using very slow path.PathPoints indexer!!! for (int k = oldPathPointIndex; k < list.Length; k++) { if (list[k].X > addLeft) { addLeft = list[k].X; } } } if (addLeft < 0.01) { addLeft = left + 2; } left = addLeft; DrawShadowAndPath(parameter, g, path); g.FillPath(new SolidBrush(c), path); path.Reset(); sb = new StringBuilder(); if (colorStack.Count > 0) { c = colorStack.Pop(); } if (left >= 3) { left -= 2.5f; } } i += 6; } else if (text.Substring(i).StartsWith("<i>", StringComparison.OrdinalIgnoreCase)) { if (sb.Length > 0) { lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); } isItalic = true; i += 2; } else if (text.Substring(i).StartsWith("</i>", StringComparison.OrdinalIgnoreCase) && isItalic) { if (lastText.EndsWith(' ') && !sb.StartsWith(' ')) { string t = sb.ToString(); sb.Clear(); sb.Append(' '); sb.Append(t); } lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); isItalic = false; i += 3; } else if (text.Substring(i).StartsWith("<b>", StringComparison.OrdinalIgnoreCase)) { if (sb.Length > 0) { lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, isBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); } isBold = true; i += 2; } else if (text.Substring(i).StartsWith("</b>", StringComparison.OrdinalIgnoreCase) && isBold) { if (lastText.EndsWith(' ') && !sb.StartsWith(' ')) { string t = sb.ToString(); sb.Clear(); sb.Append(' '); sb.Append(t); } lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, isBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); isBold = false; i += 3; } else { sb.Append(text[i]); } i++; } if (sb.Length > 0) { TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); } DrawShadowAndPath(parameter, g, path); g.FillPath(new SolidBrush(c), path); g.Dispose(); var nbmp = new NikseBitmap(bmp); nbmp.CropTransparentSidesAndBottom(0, true); bmp.Dispose(); font.Dispose(); sf.Dispose(); return nbmp.Width; }
/// <summary> /// The generate image from text with style. /// </summary> /// <param name="p"> /// The p. /// </param> /// <param name="mbp"> /// The mbp. /// </param> /// <returns> /// The <see cref="Bitmap"/>. /// </returns> private Bitmap GenerateImageFromTextWithStyle(Paragraph p, out MakeBitmapParameter mbp) { mbp = new MakeBitmapParameter(); mbp.P = p; if (this._vobSubOcr != null) { var index = this._subtitle.GetIndex(p); if (index >= 0) { return this._vobSubOcr.GetSubtitleBitmap(index); } } mbp.AlignLeft = this.comboBoxHAlign.SelectedIndex == 0; mbp.AlignRight = this.comboBoxHAlign.SelectedIndex == 2; mbp.SimpleRendering = this.checkBoxSimpleRender.Checked; mbp.BorderWidth = this._borderWidth; mbp.BorderColor = this._borderColor; mbp.SubtitleFontName = this._subtitleFontName; mbp.SubtitleColor = this._subtitleColor; mbp.SubtitleFontSize = this._subtitleFontSize; mbp.SubtitleFontBold = this._subtitleFontBold; mbp.LineHeight = (int)this.numericUpDownLineSpacing.Value; mbp.FullFrame = this.checkBoxFullFrameImage.Checked; mbp.FullFrameBackgroundcolor = this.panelFullFrameBackground.BackColor; if (this._format.HasStyleSupport && !string.IsNullOrEmpty(p.Extra)) { if (this._format.GetType() == typeof(SubStationAlpha)) { var style = AdvancedSubStationAlpha.GetSsaStyle(p.Extra, this._subtitle.Header); mbp.SubtitleColor = style.Primary; mbp.SubtitleFontBold = style.Bold; mbp.SubtitleFontSize = style.FontSize; if (style.BorderStyle == "3") { mbp.BackgroundColor = style.Background; } } else if (this._format.GetType() == typeof(AdvancedSubStationAlpha)) { var style = AdvancedSubStationAlpha.GetSsaStyle(p.Extra, this._subtitle.Header); mbp.SubtitleColor = style.Primary; mbp.SubtitleFontBold = style.Bold; mbp.SubtitleFontSize = style.FontSize; if (style.BorderStyle == "3") { mbp.BackgroundColor = style.Outline; } } } if (this.comboBoxBorderWidth.SelectedItem.ToString() == Configuration.Settings.Language.ExportPngXml.BorderStyleBoxForEachLine) { this._borderWidth = 0; mbp.BackgroundColor = this.panelBorderColor.BackColor; mbp.BoxSingleLine = true; } else if (this.comboBoxBorderWidth.SelectedItem.ToString() == Configuration.Settings.Language.ExportPngXml.BorderStyleOneBox) { this._borderWidth = 0; mbp.BackgroundColor = this.panelBorderColor.BackColor; } int width; int height; this.GetResolution(out width, out height); mbp.ScreenWidth = width; mbp.ScreenHeight = height; mbp.VideoResolution = this.comboBoxResolution.Text; mbp.Type3D = this.comboBox3D.SelectedIndex; mbp.Depth3D = (int)this.numericUpDownDepth3D.Value; mbp.BottomMargin = this.comboBoxBottomMargin.SelectedIndex; mbp.ShadowWidth = this.comboBoxShadowWidth.SelectedIndex; mbp.ShadowAlpha = (int)this.numericUpDownShadowTransparency.Value; mbp.ShadowColor = this.panelShadowColor.BackColor; mbp.LineHeight = (int)this.numericUpDownLineSpacing.Value; mbp.Forced = this.subtitleListView1.Items[this._subtitle.GetIndex(p)].Checked; mbp.LineJoin = Configuration.Settings.Tools.ExportPenLineJoin; var bmp = GenerateImageFromTextWithStyle(mbp); if (this._exportType == "VOBSUB" || this._exportType == "STL" || this._exportType == "SPUMUX") { var nbmp = new NikseBitmap(bmp); nbmp.ConverToFourColors(Color.Transparent, this._subtitleColor, this._borderColor, !this.checkBoxTransAntiAliase.Checked); var temp = nbmp.GetBitmap(); bmp.Dispose(); return temp; } return bmp; }
/// <summary> /// The set font. /// </summary> /// <param name="parameter"> /// The parameter. /// </param> /// <param name="fontSize"> /// The font size. /// </param> /// <returns> /// The <see cref="Font"/>. /// </returns> private static Font SetFont(MakeBitmapParameter parameter, float fontSize) { Font font; try { var fontStyle = FontStyle.Regular; if (parameter.SubtitleFontBold) { fontStyle = FontStyle.Bold; } font = new Font(parameter.SubtitleFontName, fontSize, fontStyle); } catch (Exception exception) { try { var fontStyle = FontStyle.Regular; if (!parameter.SubtitleFontBold) { fontStyle = FontStyle.Bold; } font = new Font(parameter.SubtitleFontName, fontSize, fontStyle); } catch { MessageBox.Show(exception.Message); if (FontFamily.Families[0].IsStyleAvailable(FontStyle.Regular)) { font = new Font(FontFamily.Families[0].Name, fontSize); } else if (FontFamily.Families.Length > 1 && FontFamily.Families[1].IsStyleAvailable(FontStyle.Regular)) { font = new Font(FontFamily.Families[1].Name, fontSize); } else if (FontFamily.Families.Length > 2 && FontFamily.Families[1].IsStyleAvailable(FontStyle.Regular)) { font = new Font(FontFamily.Families[2].Name, fontSize); } else { font = new Font("Arial", fontSize); } } } return font; }
private static int CalcWidthViaDraw(string text, MakeBitmapParameter parameter) { var nbmp = GenereateBitmapForCalc(text, parameter); nbmp.CropTransparentSidesAndBottom(0, true); return nbmp.Width; }
/// <summary> /// The combo box subtitle font_ selected index changed. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The e. /// </param> private void comboBoxSubtitleFont_SelectedIndexChanged(object sender, EventArgs e) { var bmp = new Bitmap(100, 100); using (var g = Graphics.FromImage(bmp)) { var mbp = new MakeBitmapParameter { SubtitleFontName = this._subtitleFontName, SubtitleFontSize = float.Parse(this.comboBoxSubtitleFontSize.SelectedItem.ToString()), SubtitleFontBold = this._subtitleFontBold }; var fontSize = g.DpiY * mbp.SubtitleFontSize / 72; Font font = SetFont(mbp, fontSize); SizeF textSize = g.MeasureString("Hj!", font); int lineHeight = (int)Math.Round(textSize.Height * 0.64f); if (lineHeight >= this.numericUpDownLineSpacing.Minimum && lineHeight <= this.numericUpDownLineSpacing.Maximum && lineHeight != this.numericUpDownLineSpacing.Value) { this.numericUpDownLineSpacing.Value = lineHeight; } } bmp.Dispose(); this.subtitleListView1_SelectedIndexChanged(null, null); }
/// <summary> /// The draw shadow and path. /// </summary> /// <param name="parameter"> /// The parameter. /// </param> /// <param name="g"> /// The g. /// </param> /// <param name="path"> /// The path. /// </param> private static void DrawShadowAndPath(MakeBitmapParameter parameter, Graphics g, GraphicsPath path) { if (parameter.ShadowWidth > 0) { var shadowPath = (GraphicsPath)path.Clone(); for (int k = 0; k < parameter.ShadowWidth; k++) { var translateMatrix = new Matrix(); translateMatrix.Translate(1, 1); shadowPath.Transform(translateMatrix); var p1 = new Pen(Color.FromArgb(parameter.ShadowAlpha, parameter.ShadowColor), parameter.BorderWidth); SetLineJoin(parameter.LineJoin, p1); g.DrawPath(p1, shadowPath); p1.Dispose(); } } if (parameter.BorderWidth > 0) { var p1 = new Pen(parameter.BorderColor, parameter.BorderWidth); SetLineJoin(parameter.LineJoin, p1); g.DrawPath(p1, path); p1.Dispose(); } }
/// <summary> /// The get alignment from paragraph. /// </summary> /// <param name="p"> /// The p. /// </param> /// <param name="format"> /// The format. /// </param> /// <param name="subtitle"> /// The subtitle. /// </param> /// <returns> /// The <see cref="ContentAlignment"/>. /// </returns> private static ContentAlignment GetAlignmentFromParagraph(MakeBitmapParameter p, SubtitleFormat format, Subtitle subtitle) { var alignment = ContentAlignment.BottomCenter; if (p.AlignLeft) { alignment = ContentAlignment.BottomLeft; } else if (p.AlignRight) { alignment = ContentAlignment.BottomRight; } if (format.HasStyleSupport && !string.IsNullOrEmpty(p.P.Extra)) { if (format.GetType() == typeof(SubStationAlpha)) { var style = AdvancedSubStationAlpha.GetSsaStyle(p.P.Extra, subtitle.Header); alignment = GetSsaAlignment("{\\a" + style.Alignment + "}", alignment); } else if (format.GetType() == typeof(AdvancedSubStationAlpha)) { var style = AdvancedSubStationAlpha.GetSsaStyle(p.P.Extra, subtitle.Header); alignment = GetAssAlignment("{\\an" + style.Alignment + "}", alignment); } } string text = p.P.Text; if (format.GetType() == typeof(SubStationAlpha) && text.Length > 5) { text = p.P.Text.Substring(0, 6); alignment = GetSsaAlignment(text, alignment); } else if (text.Length > 6) { text = p.P.Text.Substring(0, 6); alignment = GetAssAlignment(text, alignment); } return alignment; }
private string FormatFabTime(TimeCode time, MakeBitmapParameter param) { if (param.Bitmap.Width == 720 && param.Bitmap.Width == 480) // NTSC return string.Format("{0:00};{1:00};{2:00};{3:00}", time.Hours, time.Minutes, time.Seconds, SubtitleFormat.MillisecondsToFramesMaxFrameRate(time.Milliseconds)); return string.Format("{0:00}:{1:00}:{2:00}:{3:00}", time.Hours, time.Minutes, time.Seconds, SubtitleFormat.MillisecondsToFramesMaxFrameRate(time.Milliseconds)); }
private static Bitmap GenerateImageFromTextWithStyle(MakeBitmapParameter parameter) { string text = parameter.P.Text; text = RemoveSubStationAlphaFormatting(text); text = text.Replace("<I>", "<i>"); text = text.Replace("</I>", "</i>"); text = Utilities.FixInvalidItalicTags(text); text = text.Replace("<B>", "<b>"); text = text.Replace("</B>", "</b>"); // no support for underline text = text.Replace("<u>", string.Empty); text = text.Replace("</u>", string.Empty); text = text.Replace("<U>", string.Empty); text = text.Replace("</U>", string.Empty); var bmp = new Bitmap(1, 1); var g = Graphics.FromImage(bmp); var fontSize = g.DpiY * parameter.SubtitleFontSize / 72; Font font = SetFont(parameter, parameter.SubtitleFontSize); var lineHeight = parameter.LineHeight; // (textSize.Height * 0.64f); var textSize = g.MeasureString(Utilities.RemoveHtmlTags(text), font); g.Dispose(); bmp.Dispose(); int sizeX = (int)(textSize.Width * 1.8) + 150; int sizeY = (int)(textSize.Height * 0.9) + 50; if (sizeX < 1) sizeX = 1; if (sizeY < 1) sizeY = 1; bmp = new Bitmap(sizeX, sizeY); g = Graphics.FromImage(bmp); if (parameter.BackgroundColor != Color.Transparent) g.FillRectangle(new SolidBrush(parameter.BackgroundColor), 0, 0, bmp.Width, bmp.Height); // align lines with gjpqy, a bit lower var lines = text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); int baseLinePadding = 13; if (parameter.SubtitleFontSize < 30) baseLinePadding = 12; if (parameter.SubtitleFontSize < 25) baseLinePadding = 9; if (lines.Length > 0) { if (lines[lines.Length - 1].Contains("g") || lines[lines.Length - 1].Contains("j") || lines[lines.Length - 1].Contains("p") || lines[lines.Length - 1].Contains("q") || lines[lines.Length - 1].Contains("y") || lines[lines.Length - 1].Contains(",")) { string textNoBelow = lines[lines.Length - 1].Replace("g", "a").Replace("j", "a").Replace("p", "a").Replace("q", "a").Replace("y", "a").Replace(",", "a"); baseLinePadding -= (int)Math.Round((TextDraw.MeasureTextHeight(font, lines[lines.Length - 1], parameter.SubtitleFontBold) - TextDraw.MeasureTextHeight(font, textNoBelow, parameter.SubtitleFontBold))); } else { baseLinePadding += 1; } if (baseLinePadding < 0) baseLinePadding = 0; } //TODO: Better baseline - test http://bobpowell.net/formattingtext.aspx //float baselineOffset=font.SizeInPoints/font.FontFamily.GetEmHeight(font.Style)*font.FontFamily.GetCellAscent(font.Style); //float baselineOffsetPixels = g.DpiY/72f*baselineOffset; //baseLinePadding = (int)Math.Round(baselineOffsetPixels); var lefts = new List<float>(); if (text.ToLower().Contains("<font") || text.ToLower().Contains("<i>")) { foreach (string line in text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries)) { string lineNoHtml = Utilities.RemoveHtmlFontTag(line.Replace("<i>", string.Empty).Replace("</i>", string.Empty)); if (parameter.AlignLeft) lefts.Add(5); else if (parameter.AlignRight) lefts.Add(bmp.Width - CalcWidthViaDraw(lineNoHtml, parameter) + 15); // calculate via drawing+crop else lefts.Add((bmp.Width - CalcWidthViaDraw(lineNoHtml, parameter) + 15) / 2); // calculate via drawing+crop } } else { foreach (string line in Utilities.RemoveHtmlFontTag(text.Replace("<i>", string.Empty).Replace("</i>", string.Empty)).Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries)) { if (parameter.AlignLeft) lefts.Add(5); else if (parameter.AlignRight) lefts.Add(bmp.Width - (TextDraw.MeasureTextWidth(font, line, parameter.SubtitleFontBold) + 15)); else lefts.Add((bmp.Width - TextDraw.MeasureTextWidth(font, line, parameter.SubtitleFontBold) + 15) / 2); } } g.CompositingQuality = CompositingQuality.HighQuality; g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.SmoothingMode = SmoothingMode.HighQuality; g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; var sf = new StringFormat(); sf.Alignment = StringAlignment.Near; sf.LineAlignment = StringAlignment.Near;// draw the text to a path if (parameter.SimpleRendering) { if (text.StartsWith("<font ") && Utilities.CountTagInText(text, "<font") == 1) { parameter.SubtitleColor = Utilities.GetColorFromFontString(text, parameter.SubtitleColor); } text = Utilities.RemoveHtmlTags(text, true); //TODO: Perhaps check single color... System.Drawing.SolidBrush brush = new SolidBrush(parameter.BorderColor); int x = 3; int y = 3; sf.Alignment = StringAlignment.Near; if (parameter.AlignLeft) { sf.Alignment = StringAlignment.Near; } else if (parameter.AlignRight) { sf.Alignment = StringAlignment.Far; x = parameter.ScreenWidth - 5; } else { sf.Alignment = StringAlignment.Center; x = parameter.ScreenWidth / 2; } bmp = new Bitmap(parameter.ScreenWidth, sizeY); Graphics surface = Graphics.FromImage(bmp); surface.CompositingQuality = CompositingQuality.HighSpeed; surface.InterpolationMode = InterpolationMode.Default; surface.SmoothingMode = SmoothingMode.HighSpeed; surface.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; for (int j = 0; j < parameter.BorderWidth; j++) { surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j + 1, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j + 1, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j + 1, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j - 1, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j - 1, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j - 1, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j + 1, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j + 1, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j + 1, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j - 1, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j - 1, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j - 1, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + 1, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + 1, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + 1, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - 1, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - 1, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - 1, Y = y + 1 - j }, sf); } brush.Dispose(); brush = new SolidBrush(parameter.SubtitleColor); surface.CompositingQuality = CompositingQuality.HighQuality; surface.SmoothingMode = SmoothingMode.HighQuality; surface.InterpolationMode = InterpolationMode.HighQualityBicubic; surface.DrawString(text, font, brush, new PointF { X = x, Y = y }, sf); surface.Dispose(); brush.Dispose(); } else { var path = new GraphicsPath(); var sb = new StringBuilder(); int i = 0; bool isItalic = false; bool isBold = parameter.SubtitleFontBold; float left = 5; if (lefts.Count > 0) left = lefts[0]; float top = 5; bool newLine = false; int lineNumber = 0; float leftMargin = left; int newLinePathPoint = -1; Color c = parameter.SubtitleColor; var colorStack = new Stack<Color>(); var lastText = new StringBuilder(); while (i < text.Length) { if (text.Substring(i).ToLower().StartsWith("<font ")) { float addLeft = 0; int oldPathPointIndex = path.PointCount; if (oldPathPointIndex < 0) oldPathPointIndex = 0; if (sb.Length > 0) { lastText.Append(sb.ToString()); TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); } if (path.PointCount > 0) { PointF[] list = (PointF[])path.PathPoints.Clone(); // avoid using very slow path.PathPoints indexer!!! for (int k = oldPathPointIndex; k < list.Length; k++) { if (list[k].X > addLeft) addLeft = list[k].X; } } if (path.PointCount == 0) addLeft = left; else if (addLeft < 0.01) addLeft = left + 2; left = addLeft; DrawShadowAndPAth(parameter, g, path); var p2 = new SolidBrush(c); g.FillPath(p2, path); p2.Dispose(); path.Reset(); path = new GraphicsPath(); sb = new StringBuilder(); int endIndex = text.Substring(i).IndexOf(">"); if (endIndex == -1) { i += 9999; } else { string fontContent = text.Substring(i, endIndex); if (fontContent.Contains(" color=")) { string[] arr = fontContent.Substring(fontContent.IndexOf(" color=") + 7).Trim().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if (arr.Length > 0) { string fontColor = arr[0].Trim('\'').Trim('"').Trim('\''); try { colorStack.Push(c); // save old color if (fontColor.StartsWith("rgb(")) { arr = fontColor.Remove(0, 4).TrimEnd(')').Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); c = Color.FromArgb(int.Parse(arr[0]), int.Parse(arr[1]), int.Parse(arr[2])); } else { c = ColorTranslator.FromHtml(fontColor); } } catch { c = parameter.SubtitleColor; } } } i += endIndex; } } else if (text.Substring(i).ToLower().StartsWith("</font>")) { if (text.Substring(i).ToLower().Replace("</font>", string.Empty).Length > 0) { if (lastText.ToString().EndsWith(" ") && !sb.ToString().StartsWith(" ")) { string t = sb.ToString(); sb = new StringBuilder(); sb.Append(" " + t); } float addLeft = 0; int oldPathPointIndex = path.PointCount - 1; if (oldPathPointIndex < 0) oldPathPointIndex = 0; if (sb.Length > 0) { if (lastText.Length > 0 && left > 2) left -= 1.5f; lastText.Append(sb.ToString()); TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); } if (path.PointCount > 0) { PointF[] list = (PointF[])path.PathPoints.Clone(); // avoid using very slow path.PathPoints indexer!!! for (int k = oldPathPointIndex; k < list.Length; k++) { if (list[k].X > addLeft) addLeft = list[k].X; } } if (addLeft < 0.01) addLeft = left + 2; left = addLeft; DrawShadowAndPAth(parameter, g, path); g.FillPath(new SolidBrush(c), path); path.Reset(); sb = new StringBuilder(); if (colorStack.Count > 0) c = colorStack.Pop(); if (left >= 3) left -= 2.5f; } i += 6; } else if (text.Substring(i).ToLower().StartsWith("<i>")) { if (sb.Length > 0) { lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); } isItalic = true; i += 2; } else if (text.Substring(i).ToLower().StartsWith("</i>") && isItalic) { if (lastText.ToString().EndsWith(" ") && !sb.ToString().StartsWith(" ")) { string t = sb.ToString(); sb = new StringBuilder(); sb.Append(" " + t); } lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); isItalic = false; i += 3; } else if (text.Substring(i).ToLower().StartsWith("<b>")) { if (sb.Length > 0) { lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, isBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); } isBold = true; i += 2; } else if (text.Substring(i).ToLower().StartsWith("</b>") && isBold) { if (lastText.ToString().EndsWith(" ") && !sb.ToString().StartsWith(" ")) { string t = sb.ToString(); sb = new StringBuilder(); sb.Append(" " + t); } lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, isBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); isBold = false; i += 3; } else if (text.Substring(i).StartsWith(Environment.NewLine)) { lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, isBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); top += lineHeight; newLine = true; i += Environment.NewLine.Length - 1; lineNumber++; if (lineNumber < lefts.Count) { leftMargin = lefts[lineNumber]; left = leftMargin; } } else { sb.Append(text.Substring(i, 1)); } i++; } if (sb.Length > 0) TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); DrawShadowAndPAth(parameter, g, path); g.FillPath(new SolidBrush(c), path); g.Dispose(); } var nbmp = new NikseBitmap(bmp); if (parameter.BackgroundColor == Color.Transparent) { nbmp.CropTransparentSidesAndBottom(baseLinePadding, true); nbmp.CropTransparentSidesAndBottom(2, false); } else { nbmp.CropSidesAndBottom(baseLinePadding, parameter.BackgroundColor, true); nbmp.CropSidesAndBottom(4, parameter.BackgroundColor, true); nbmp.CropTop(4, parameter.BackgroundColor); } if (nbmp.Width > parameter.ScreenWidth) { parameter.Error = "#" + parameter.P.Number.ToString(CultureInfo.InvariantCulture) + ": " + nbmp.Width.ToString(CultureInfo.InvariantCulture) + " > " + parameter.ScreenWidth.ToString(CultureInfo.InvariantCulture); } if (parameter.Type3D == 1) // Half-side-by-side 3D { Bitmap singleBmp = nbmp.GetBitmap(); Bitmap singleHalfBmp = ScaleToHalfWidth(singleBmp); singleBmp.Dispose(); Bitmap sideBySideBmp = new Bitmap(parameter.ScreenWidth, singleHalfBmp.Height); int singleWidth = parameter.ScreenWidth / 2; int singleLeftMargin = (singleWidth - singleHalfBmp.Width) / 2; using (Graphics gSideBySide = Graphics.FromImage(sideBySideBmp)) { gSideBySide.DrawImage(singleHalfBmp, singleLeftMargin + parameter.Depth3D, 0); gSideBySide.DrawImage(singleHalfBmp, singleWidth + singleLeftMargin - parameter.Depth3D, 0); } nbmp = new NikseBitmap(sideBySideBmp); if (parameter.BackgroundColor == Color.Transparent) nbmp.CropTransparentSidesAndBottom(2, true); else nbmp.CropSidesAndBottom(4, parameter.BackgroundColor, true); } else if (parameter.Type3D == 2) // Half-Top/Bottom 3D { Bitmap singleBmp = nbmp.GetBitmap(); Bitmap singleHalfBmp = ScaleToHalfHeight(singleBmp); singleBmp.Dispose(); Bitmap topBottomBmp = new Bitmap(parameter.ScreenWidth, parameter.ScreenHeight - parameter.BottomMargin); int singleHeight = parameter.ScreenHeight / 2; int leftM = (parameter.ScreenWidth / 2) - (singleHalfBmp.Width / 2); using (Graphics gTopBottom = Graphics.FromImage(topBottomBmp)) { gTopBottom.DrawImage(singleHalfBmp, leftM + parameter.Depth3D, singleHeight - singleHalfBmp.Height - parameter.BottomMargin); gTopBottom.DrawImage(singleHalfBmp, leftM - parameter.Depth3D, parameter.ScreenHeight - parameter.BottomMargin - singleHalfBmp.Height); } nbmp = new NikseBitmap(topBottomBmp); if (parameter.BackgroundColor == Color.Transparent) { nbmp.CropTop(2, Color.Transparent); nbmp.CropTransparentSidesAndBottom(2, false); } else { nbmp.CropTop(4, parameter.BackgroundColor); nbmp.CropSidesAndBottom(4, parameter.BackgroundColor, false); } } return nbmp.GetBitmap(); }
private int WriteParagraph(int width, StringBuilder sb, int border, int height, int imagesSavedCount, VobSubWriter vobSubWriter, FileStream binarySubtitleFile, MakeBitmapParameter param, int i) { if (param.Bitmap != null) { if (_exportType == "BLURAYSUP") { if (!param.Saved) binarySubtitleFile.Write(param.Buffer, 0, param.Buffer.Length); param.Saved = true; } else if (_exportType == "VOBSUB") { if (!param.Saved) vobSubWriter.WriteParagraph(param.P, param.Bitmap, param.Alignment); param.Saved = true; } else if (_exportType == "FAB") { if (!param.Saved) { string numberString = string.Format("IMAGE{0:000}", i); string fileName = Path.Combine(folderBrowserDialog1.SelectedPath, numberString + "." + comboBoxImageFormat.Text.ToLower()); param.Bitmap.Save(fileName, ImageFormat); imagesSavedCount++; //RACE001.TIF 00;00;02;02 00;00;03;15 000 000 720 480 //RACE002.TIF 00;00;05;18 00;00;09;20 000 000 720 480 int top = param.ScreenHeight - (param.Bitmap.Height + param.BottomMargin); int left = (param.ScreenWidth - param.Bitmap.Width) / 2; if (param.Alignment == ContentAlignment.BottomLeft || param.Alignment == ContentAlignment.MiddleLeft || param.Alignment == ContentAlignment.TopLeft) left = param.BottomMargin; else if (param.Alignment == ContentAlignment.BottomRight || param.Alignment == ContentAlignment.MiddleRight || param.Alignment == ContentAlignment.TopRight) left = param.ScreenWidth - param.Bitmap.Width - param.BottomMargin; if (param.Alignment == ContentAlignment.TopLeft || param.Alignment == ContentAlignment.TopCenter || param.Alignment == ContentAlignment.TopRight) top = param.BottomMargin; if (param.Alignment == ContentAlignment.MiddleLeft || param.Alignment == ContentAlignment.MiddleCenter || param.Alignment == ContentAlignment.MiddleRight) top = param.ScreenHeight - (param.Bitmap.Height / 2); sb.AppendLine(string.Format("{0} {1} {2} {3} {4} {5} {6}", Path.GetFileName(fileName), FormatFabTime(param.P.StartTime, param), FormatFabTime(param.P.EndTime, param), left, top, left + param.Bitmap.Width, top + param.Bitmap.Height)); param.Saved = true; } } else if (_exportType == "STL") { if (!param.Saved) { string numberString = string.Format("IMAGE{0:000}", i); string fileName = Path.Combine(folderBrowserDialog1.SelectedPath, numberString + "." + comboBoxImageFormat.Text.ToLower()); param.Bitmap.Save(fileName, ImageFormat); imagesSavedCount++; const string paragraphWriteFormat = "{0} , {1} , {2}\r\n"; const string timeFormat = "{0:00}:{1:00}:{2:00}:{3:00}"; double factor = (1000.0 / Configuration.Settings.General.CurrentFrameRate); string startTime = string.Format(timeFormat, param.P.StartTime.Hours, param.P.StartTime.Minutes, param.P.StartTime.Seconds, (int)Math.Round(param.P.StartTime.Milliseconds / factor)); string endTime = string.Format(timeFormat, param.P.EndTime.Hours, param.P.EndTime.Minutes, param.P.EndTime.Seconds, (int)Math.Round(param.P.EndTime.Milliseconds / factor)); sb.Append(string.Format(paragraphWriteFormat, startTime, endTime, fileName)); param.Saved = true; } } else if (_exportType == "SPUMUX") { if (!param.Saved) { string numberString = string.Format("IMAGE{0:000}", i); string fileName = Path.Combine(folderBrowserDialog1.SelectedPath, numberString + "." + comboBoxImageFormat.Text.ToLower()); foreach (var encoder in ImageCodecInfo.GetImageEncoders()) { if (encoder.FormatID == ImageFormat.Png.Guid) { var parameters = new EncoderParameters(); parameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 8); var nbmp = new NikseBitmap(param.Bitmap); var b = nbmp.ConverTo8BitsPerPixel(); b.Save(fileName, encoder, parameters); b.Dispose(); break; } } imagesSavedCount++; const string paragraphWriteFormat = "\t\t<spu start=\"{0}\" end=\"{1}\" image=\"{2}\" />"; const string timeFormat = "{0:00}:{1:00}:{2:00}:{3:00}"; double factor = (1000.0 / Configuration.Settings.General.CurrentFrameRate); string startTime = string.Format(timeFormat, param.P.StartTime.Hours, param.P.StartTime.Minutes, param.P.StartTime.Seconds, (int)Math.Round(param.P.StartTime.Milliseconds / factor)); string endTime = string.Format(timeFormat, param.P.EndTime.Hours, param.P.EndTime.Minutes, param.P.EndTime.Seconds, (int)Math.Round(param.P.EndTime.Milliseconds / factor)); sb.AppendLine(string.Format(paragraphWriteFormat, startTime, endTime, fileName)); param.Saved = true; } } else if (_exportType == "FCP") { if (!param.Saved) { string numberString = string.Format(Path.GetFileNameWithoutExtension(Path.GetFileName(param.SavDialogFileName)) + "{0:0000}", i); string fileName = numberString + "." + comboBoxImageFormat.Text.ToLower(); string fileNameNoPath = Path.GetFileName(fileName); string fileNameNoExt = Path.GetFileNameWithoutExtension(fileNameNoPath); string template = " <clipitem id=\"" + fileNameNoPath + "\">" + Environment.NewLine + @" <name>" + fileNameNoPath + @"</name> <duration>[DURATION]</duration> <rate> <ntsc>FALSE</ntsc> <timebase>25</timebase> </rate> <in>[IN]</in> <out>[OUT]</out> <start>[START]</start> <end>[END]</end> <pixelaspectratio>PAL-601</pixelaspectratio> <stillframe>TRUE</stillframe> <anamorphic>FALSE</anamorphic> <alphatype>straight</alphatype> <masterclipid>" + fileNameNoPath + @"1</masterclipid>" + Environment.NewLine + " <file id=\"" + fileNameNoExt + "\">" + @" <name>" + fileNameNoPath + @"</name> <pathurl>file://localhost/" + fileNameNoPath + @"</pathurl> <rate> <timebase>25</timebase> </rate> <duration>[DURATION]</duration> <width>" + param.ScreenWidth.ToString() + @"</width> <height>" + param.ScreenHeight.ToString() + @"</height> <media> <video> <duration>[DURATION]</duration> <stillframe>TRUE</stillframe> <samplecharacteristics> <width>720</width> <height>576</height> </samplecharacteristics> </video> </media> </file> <sourcetrack> <mediatype>video</mediatype> </sourcetrack> <fielddominance>none</fielddominance> </clipitem>"; fileName = Path.Combine(Path.GetDirectoryName(param.SavDialogFileName), fileName); if (comboBoxImageFormat.Text == "8-bit png") { foreach (var encoder in ImageCodecInfo.GetImageEncoders()) { if (encoder.FormatID == ImageFormat.Png.Guid) { var parameters = new EncoderParameters(); parameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 8); var nbmp = new NikseBitmap(param.Bitmap); var b = nbmp.ConverTo8BitsPerPixel(); b.Save(fileName, encoder, parameters); b.Dispose(); break; } } } else { param.Bitmap.Save(fileName, ImageFormat); } imagesSavedCount++; int duration = (int)Math.Round(param.P.Duration.TotalSeconds * 25.0); int start = (int)Math.Round(param.P.StartTime.TotalSeconds * 25.0); int end = (int)Math.Round(param.P.EndTime.TotalSeconds * 25.0); template = template.Replace("[DURATION]", duration.ToString(CultureInfo.InvariantCulture)); template = template.Replace("[IN]", start.ToString(CultureInfo.InvariantCulture)); template = template.Replace("[OUT]", end.ToString(CultureInfo.InvariantCulture)); template = template.Replace("[START]", start.ToString(CultureInfo.InvariantCulture)); template = template.Replace("[END]", end.ToString(CultureInfo.InvariantCulture)); sb.AppendLine(template); param.Saved = true; } } else if (_exportType == "DOST") { if (!param.Saved) { string numberString = string.Format("{0:0000}", i); string fileName = Path.Combine(Path.GetDirectoryName(saveFileDialog1.FileName), Path.GetFileNameWithoutExtension(saveFileDialog1.FileName)).Replace(" ", "_") + "_" + numberString + ".png"; foreach (var encoder in ImageCodecInfo.GetImageEncoders()) { if (encoder.FormatID == ImageFormat.Png.Guid) { var parameters = new EncoderParameters(1); parameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 8); var nbmp = new NikseBitmap(param.Bitmap); var b = nbmp.ConverTo8BitsPerPixel(); b.Save(fileName, encoder, parameters); b.Dispose(); break; } } imagesSavedCount++; const string paragraphWriteFormat = "{0}\t{1}\t{2}\t{4}\t{5}\t{3}\t0\t0"; int top = param.ScreenHeight - (param.Bitmap.Height + param.BottomMargin); int left = (param.ScreenWidth - param.Bitmap.Width) / 2; if (param.Alignment == ContentAlignment.BottomLeft || param.Alignment == ContentAlignment.MiddleLeft || param.Alignment == ContentAlignment.TopLeft) left = param.BottomMargin; else if (param.Alignment == ContentAlignment.BottomRight || param.Alignment == ContentAlignment.MiddleRight || param.Alignment == ContentAlignment.TopRight) left = param.ScreenWidth - param.Bitmap.Width - param.BottomMargin; if (param.Alignment == ContentAlignment.TopLeft || param.Alignment == ContentAlignment.TopCenter || param.Alignment == ContentAlignment.TopRight) top = param.BottomMargin; if (param.Alignment == ContentAlignment.MiddleLeft || param.Alignment == ContentAlignment.MiddleCenter || param.Alignment == ContentAlignment.MiddleRight) top = param.ScreenHeight - (param.Bitmap.Height / 2); string startTime = BdnXmlTimeCode(param.P.StartTime); string endTime = BdnXmlTimeCode(param.P.EndTime); sb.AppendLine(string.Format(paragraphWriteFormat, numberString, startTime, endTime, Path.GetFileName(fileName), left, top)); param.Saved = true; } } else if (_exportType == "IMAGE/FRAME") { if (!param.Saved) { var imageFormat = ImageFormat; int lastFrame = imagesSavedCount; int startFrame = (int)Math.Round(param.P.StartTime.TotalMilliseconds / (1000.0 / param.FramesPerSeconds)); var empty = new Bitmap(param.ScreenWidth, param.ScreenHeight); if (imagesSavedCount == 0 && checkBoxSkipEmptyFrameAtStart.Checked) { } else { // Save empty picture for each frame up to start frame for (int k = lastFrame + 1; k < startFrame; k++) { string numberString = string.Format("{0:00000}", k); string fileName = Path.Combine(folderBrowserDialog1.SelectedPath, numberString + "." + comboBoxImageFormat.Text.ToLower()); empty.Save(fileName, imageFormat); imagesSavedCount++; } } int endFrame = (int)Math.Round(param.P.EndTime.TotalMilliseconds / (1000.0 / param.FramesPerSeconds)); var fullSize = new Bitmap(param.ScreenWidth, param.ScreenHeight); Graphics g = Graphics.FromImage(fullSize); g.DrawImage(param.Bitmap, (param.ScreenWidth - param.Bitmap.Width) / 2, param.ScreenHeight - (param.Bitmap.Height + param.BottomMargin)); g.Dispose(); if (imagesSavedCount > startFrame) startFrame = imagesSavedCount; // no overlapping // Save sub picture for each frame in duration for (int k = startFrame; k <= endFrame; k++) { string numberString = string.Format("{0:00000}", k); string fileName = Path.Combine(folderBrowserDialog1.SelectedPath, numberString + "." + comboBoxImageFormat.Text.ToLower()); fullSize.Save(fileName, imageFormat); imagesSavedCount++; } fullSize.Dispose(); param.Saved = true; } } else { if (!param.Saved) { string numberString = string.Format("{0:0000}", i); string fileName = Path.Combine(folderBrowserDialog1.SelectedPath, numberString + ".png"); param.Bitmap.Save(fileName, ImageFormat.Png); imagesSavedCount++; //<Event InTC="00:00:24:07" OutTC="00:00:31:13" Forced="False"> // <Graphic Width="696" Height="111" X="612" Y="930">subtitle_exp_0001.png</Graphic> //</Event> sb.AppendLine("<Event InTC=\"" + BdnXmlTimeCode(param.P.StartTime) + "\" OutTC=\"" + BdnXmlTimeCode(param.P.EndTime) + "\" Forced=\"False\">"); int x = (width - param.Bitmap.Width) / 2; int y = height - (param.Bitmap.Height + param.BottomMargin); switch (param.Alignment) { case ContentAlignment.BottomLeft: x = border; y = height - (param.Bitmap.Height + param.BottomMargin); break; case ContentAlignment.BottomRight: x = height - param.Bitmap.Width - border; y = height - (param.Bitmap.Height + param.BottomMargin); break; case ContentAlignment.MiddleCenter: x = (width - param.Bitmap.Width) / 2; y = (height - param.Bitmap.Height) / 2; break; case ContentAlignment.MiddleLeft: x = border; y = (height - param.Bitmap.Height) / 2; break; case ContentAlignment.MiddleRight: x = width - param.Bitmap.Width - border; y = (height - param.Bitmap.Height) / 2; break; case ContentAlignment.TopCenter: x = (width - param.Bitmap.Width) / 2; y = border; break; case ContentAlignment.TopLeft: x = border; y = border; break; case ContentAlignment.TopRight: x = width - param.Bitmap.Width - border; y = border; break; default: // ContentAlignment.BottomCenter: break; } sb.AppendLine(" <Graphic Width=\"" + param.Bitmap.Width.ToString(CultureInfo.InvariantCulture) + "\" Height=\"" + param.Bitmap.Height.ToString(CultureInfo.InvariantCulture) + "\" X=\"" + x.ToString(CultureInfo.InvariantCulture) + "\" Y=\"" + y.ToString(CultureInfo.InvariantCulture) + "\">" + numberString + ".png</Graphic>"); sb.AppendLine("</Event>"); param.Saved = true; } } } return imagesSavedCount; }
private MakeBitmapParameter MakeMakeBitmapParameter(int index, int screenWidth,int screenHeight) { var parameter = new MakeBitmapParameter { Type = _exportType, SubtitleColor = _subtitleColor, SubtitleFontName = _subtitleFontName, SubtitleFontSize = _subtitleFontSize, SubtitleFontBold = _subtitleFontBold, BorderColor = _borderColor, BorderWidth = _borderWidth, SimpleRendering = checkBoxSimpleRender.Checked, AlignLeft = comboBoxHAlign.SelectedIndex == 0, AlignRight = comboBoxHAlign.SelectedIndex == 2, ScreenWidth = screenWidth, ScreenHeight = screenHeight, Bitmap = null, FramesPerSeconds = FrameRate, BottomMargin = comboBoxBottomMargin.SelectedIndex, Saved = false, Alignment = ContentAlignment.BottomCenter, Type3D = comboBox3D.SelectedIndex, Depth3D = (int)numericUpDownDepth3D.Value, BackgroundColor = Color.Transparent, SavDialogFileName = saveFileDialog1.FileName, ShadowColor = panelShadowColor.BackColor, ShadowWidth = (int)comboBoxShadowWidth.SelectedIndex, ShadowAlpha = (int)numericUpDownShadowTransparency.Value, LineHeight = (int)numericUpDownLineSpacing.Value, }; if (index < _subtitle.Paragraphs.Count) { parameter.P = _subtitle.Paragraphs[index]; parameter.Alignment = GetAlignmentFromParagraph(parameter.P,_format, _subtitle); if (_format.HasStyleSupport && !string.IsNullOrEmpty(parameter.P.Extra)) { if (_format.GetType() == typeof(SubStationAlpha)) { var style = AdvancedSubStationAlpha.GetSsaStyle(parameter.P.Extra, _subtitle.Header); parameter.SubtitleColor = style.Primary; parameter.SubtitleFontBold = style.Bold; parameter.SubtitleFontSize = style.FontSize; if (style.BorderStyle == "3") { parameter.BackgroundColor = style.Background; } } else if (_format.GetType() == typeof(AdvancedSubStationAlpha)) { var style = AdvancedSubStationAlpha.GetSsaStyle(parameter.P.Extra, _subtitle.Header); parameter.SubtitleColor = style.Primary; parameter.SubtitleFontBold = style.Bold; parameter.SubtitleFontSize = style.FontSize; if (style.BorderStyle == "3") { parameter.BackgroundColor = style.Outline; } } } } else { parameter.P = null; } return parameter; }
private Bitmap GenerateImageFromTextWithStyle(Paragraph p, out MakeBitmapParameter mbp) { mbp = new MakeBitmapParameter(); mbp.P = p; if (_vobSubOcr != null) { var index = _subtitle.GetIndex(p); if (index >= 0) return _vobSubOcr.GetSubtitleBitmap(index); } mbp.AlignLeft = comboBoxHAlign.SelectedIndex == 0; mbp.AlignRight = comboBoxHAlign.SelectedIndex == 2; mbp.SimpleRendering = checkBoxSimpleRender.Checked; mbp.BorderWidth = _borderWidth; mbp.BorderColor = _borderColor; mbp.SubtitleFontName = _subtitleFontName; mbp.SubtitleColor = _subtitleColor; mbp.SubtitleFontSize = _subtitleFontSize; mbp.SubtitleFontBold = _subtitleFontBold; mbp.LineHeight = (int) numericUpDownLineSpacing.Value; if (_format.HasStyleSupport && !string.IsNullOrEmpty(p.Extra)) { if (_format.GetType() == typeof(SubStationAlpha)) { var style = AdvancedSubStationAlpha.GetSsaStyle(p.Extra, _subtitle.Header); mbp.SubtitleColor = style.Primary; mbp.SubtitleFontBold = style.Bold; mbp.SubtitleFontSize = style.FontSize; if (style.BorderStyle == "3") { mbp.BackgroundColor = style.Background; } } else if (_format.GetType() == typeof(AdvancedSubStationAlpha)) { var style = AdvancedSubStationAlpha.GetSsaStyle(p.Extra, _subtitle.Header); mbp.SubtitleColor = style.Primary; mbp.SubtitleFontBold = style.Bold; mbp.SubtitleFontSize = style.FontSize; if (style.BorderStyle == "3") { mbp.BackgroundColor = style.Outline; } } } int width = 0; int height = 0; GetResolution(ref width, ref height); mbp.ScreenWidth = width; mbp.ScreenHeight = height; mbp.Type3D = comboBox3D.SelectedIndex; mbp.Depth3D = (int)numericUpDownDepth3D.Value; mbp.BottomMargin = comboBoxBottomMargin.SelectedIndex; mbp.ShadowWidth = comboBoxShadowWidth.SelectedIndex; mbp.ShadowAlpha = (int)numericUpDownShadowTransparency.Value; mbp.ShadowColor = panelShadowColor.BackColor; mbp.LineHeight = (int)numericUpDownLineSpacing.Value; if (_exportType == "VOBSUB" || _exportType == "STL" || _exportType == "SPUMUX") { mbp.LineJoinRound = true; } var bmp = GenerateImageFromTextWithStyle(mbp); if (_exportType == "VOBSUB" || _exportType == "STL" || _exportType == "SPUMUX") { var nbmp = new NikseBitmap(bmp); nbmp.ConverToFourColors(Color.Transparent, _subtitleColor, _borderColor, GetOutlineColor(_borderColor)); bmp = nbmp.GetBitmap(); } return bmp; }
/// <summary> /// The generate image from text with style. /// </summary> /// <param name="parameter"> /// The parameter. /// </param> /// <returns> /// The <see cref="Bitmap"/>. /// </returns> private static Bitmap GenerateImageFromTextWithStyle(MakeBitmapParameter parameter) { Bitmap bmp = null; if (!parameter.SimpleRendering && parameter.P.Text.Contains(Environment.NewLine) && (parameter.BoxSingleLine || parameter.P.Text.Contains(BoxSingleLineText))) { string old = parameter.P.Text; int oldType3D = parameter.Type3D; if (parameter.Type3D == 2) { // Half-Top/Bottom 3D parameter.Type3D = 0; // fix later } Color oldBackgroundColor = parameter.BackgroundColor; if (parameter.P.Text.Contains(BoxSingleLineText)) { parameter.P.Text = parameter.P.Text.Replace("<" + BoxSingleLineText + ">", string.Empty).Replace("</" + BoxSingleLineText + ">", string.Empty); parameter.BackgroundColor = parameter.BorderColor; } bool italicOn = false; string fontTag = string.Empty; foreach (string line in parameter.P.Text.Replace(Environment.NewLine, "\n").Split('\n')) { parameter.P.Text = line; if (italicOn) { parameter.P.Text = "<i>" + parameter.P.Text; } italicOn = parameter.P.Text.Contains("<i>") && !parameter.P.Text.Contains("</i>"); parameter.P.Text = fontTag + parameter.P.Text; if (parameter.P.Text.Contains("<font ") && !parameter.P.Text.Contains("</font>")) { int start = parameter.P.Text.LastIndexOf("<font ", StringComparison.Ordinal); int end = parameter.P.Text.IndexOf('>', start); fontTag = parameter.P.Text.Substring(start, end - start + 1); } var lineImage = GenerateImageFromTextWithStyleInner(parameter); if (bmp == null) { bmp = lineImage; } else { int w = Math.Max(bmp.Width, lineImage.Width); int h = bmp.Height + lineImage.Height; int l1; if (parameter.AlignLeft) { l1 = 0; } else if (parameter.AlignRight) { l1 = w - bmp.Width; } else { l1 = (int)Math.Round((w - bmp.Width) / 2.0); } int l2; if (parameter.AlignLeft) { l2 = 0; } else if (parameter.AlignRight) { l2 = w - lineImage.Width; } else { l2 = (int)Math.Round((w - lineImage.Width) / 2.0); } if (parameter.LineHeight > lineImage.Height) { h += parameter.LineHeight - lineImage.Height; var largeImage = new Bitmap(w, h); var g = Graphics.FromImage(largeImage); g.DrawImageUnscaled(bmp, new Point(l1, 0)); g.DrawImageUnscaled(lineImage, new Point(l2, bmp.Height + parameter.LineHeight - lineImage.Height)); bmp.Dispose(); bmp = largeImage; g.Dispose(); } else { var largeImage = new Bitmap(w, h); var g = Graphics.FromImage(largeImage); g.DrawImageUnscaled(bmp, new Point(l1, 0)); g.DrawImageUnscaled(lineImage, new Point(l2, bmp.Height)); bmp.Dispose(); bmp = largeImage; g.Dispose(); } } } parameter.P.Text = old; parameter.Type3D = oldType3D; parameter.BackgroundColor = oldBackgroundColor; if (parameter.Type3D == 2) { // Half-side-by-side 3D - due to per line we need to do this after making lines var newBmp = Make3DTopBottom(parameter, new NikseBitmap(bmp)).GetBitmap(); if (bmp != null) { bmp.Dispose(); } bmp = newBmp; } } else { Color oldBackgroundColor = parameter.BackgroundColor; string oldText = parameter.P.Text; if (parameter.P.Text.Contains(BoxMultiLineText) || parameter.P.Text.Contains(BoxSingleLineText)) { parameter.P.Text = parameter.P.Text.Replace("<" + BoxMultiLineText + ">", string.Empty).Replace("</" + BoxMultiLineText + ">", string.Empty); parameter.P.Text = parameter.P.Text.Replace("<" + BoxSingleLineText + ">", string.Empty).Replace("</" + BoxSingleLineText + ">", string.Empty); parameter.BackgroundColor = parameter.BorderColor; } bmp = GenerateImageFromTextWithStyleInner(parameter); parameter.P.Text = oldText; parameter.BackgroundColor = oldBackgroundColor; } return bmp; }
private void UpdateLineSpacing() { Bitmap bmp = new Bitmap(100, 100); using (Graphics g = Graphics.FromImage(bmp)) { var mbp = new MakeBitmapParameter(); mbp.SubtitleFontName = _subtitleFontName; mbp.SubtitleFontSize = float.Parse(comboBoxSubtitleFontSize.SelectedItem.ToString()); mbp.SubtitleFontBold = _subtitleFontBold; var fontSize = g.DpiY * mbp.SubtitleFontSize / 72; Font font = SetFont(mbp, fontSize); SizeF textSize = g.MeasureString("Hj!", font); int lineHeight = (int)Math.Round(textSize.Height * 0.64f); var style = string.Empty; if (subtitleListView1.SelectedIndices.Count > 0) style = GetStyleName(_subtitle.Paragraphs[subtitleListView1.SelectedItems[0].Index]); if (_lineHeights.ContainsKey(style)) numericUpDownLineSpacing.Value = _lineHeights[style]; else if (lineHeight >= numericUpDownLineSpacing.Minimum && lineHeight <= numericUpDownLineSpacing.Maximum && lineHeight != numericUpDownLineSpacing.Value) numericUpDownLineSpacing.Value = lineHeight; else if (lineHeight > numericUpDownLineSpacing.Maximum) numericUpDownLineSpacing.Value = numericUpDownLineSpacing.Maximum; } }
/// <summary> /// The generate image from text with style inner. /// </summary> /// <param name="parameter"> /// The parameter. /// </param> /// <returns> /// The <see cref="Bitmap"/>. /// </returns> private static Bitmap GenerateImageFromTextWithStyleInner(MakeBitmapParameter parameter) { string text = parameter.P.Text; text = RemoveSubStationAlphaFormatting(text); text = text.Replace("<I>", "<i>"); text = text.Replace("</I>", "</i>"); text = HtmlUtil.FixInvalidItalicTags(text); text = text.Replace("<B>", "<b>"); text = text.Replace("</B>", "</b>"); // no support for underline text = HtmlUtil.RemoveOpenCloseTags(text, HtmlUtil.TagUnderline); Font font = null; Bitmap bmp = null; try { font = SetFont(parameter, parameter.SubtitleFontSize); var lineHeight = parameter.LineHeight; // (textSize.Height * 0.64f); SizeF textSize; using (var bmpTemp = new Bitmap(1, 1)) using (var g = Graphics.FromImage(bmpTemp)) { textSize = g.MeasureString(HtmlUtil.RemoveHtmlTags(text), font); } int sizeX = (int)(textSize.Width * 1.8) + 150; int sizeY = (int)(textSize.Height * 0.9) + 50; if (sizeX < 1) { sizeX = 1; } if (sizeY < 1) { sizeY = 1; } if (parameter.BackgroundColor != Color.Transparent) { var nbmpTemp = new NikseBitmap(sizeX, sizeY); nbmpTemp.Fill(parameter.BackgroundColor); bmp = nbmpTemp.GetBitmap(); } else { bmp = new Bitmap(sizeX, sizeY); } // align lines with gjpqy, a bit lower var lines = text.SplitToLines(); int baseLinePadding = 13; if (parameter.SubtitleFontSize < 30) { baseLinePadding = 12; } if (parameter.SubtitleFontSize < 25) { baseLinePadding = 9; } if (lines.Length > 0) { var lastLine = lines[lines.Length - 1]; if (lastLine.Contains(new[] { 'g', 'j', 'p', 'q', 'y', ',', 'ý', 'ę', 'ç', 'Ç' })) { var textNoBelow = lastLine.Replace('g', 'a').Replace('j', 'a').Replace('p', 'a').Replace('q', 'a').Replace('y', 'a').Replace(',', 'a').Replace('ý', 'a').Replace('ę', 'a').Replace('ç', 'a').Replace('Ç', 'a'); baseLinePadding -= (int)Math.Round(TextDraw.MeasureTextHeight(font, lastLine, parameter.SubtitleFontBold) - TextDraw.MeasureTextHeight(font, textNoBelow, parameter.SubtitleFontBold)); } else { baseLinePadding += 1; } if (baseLinePadding < 0) { baseLinePadding = 0; } } // TODO: Better baseline - test http://bobpowell.net/formattingtext.aspx // float baselineOffset=font.SizeInPoints/font.FontFamily.GetEmHeight(font.Style)*font.FontFamily.GetCellAscent(font.Style); // float baselineOffsetPixels = g.DpiY/72f*baselineOffset; // baseLinePadding = (int)Math.Round(baselineOffsetPixels); var lefts = new List<float>(); if (text.Contains("<font", StringComparison.OrdinalIgnoreCase) || text.Contains("<i>", StringComparison.OrdinalIgnoreCase)) { foreach (string line in text.SplitToLines()) { var lineNoHtml = HtmlUtil.RemoveOpenCloseTags(line, HtmlUtil.TagItalic, HtmlUtil.TagFont); if (parameter.AlignLeft) { lefts.Add(5); } else if (parameter.AlignRight) { lefts.Add(bmp.Width - CalcWidthViaDraw(lineNoHtml, parameter) - 15); // calculate via drawing+crop } else { lefts.Add((float)((bmp.Width - CalcWidthViaDraw(lineNoHtml, parameter) + 5.0) / 2.0)); // calculate via drawing+crop } } } else { foreach (var line in HtmlUtil.RemoveOpenCloseTags(text, HtmlUtil.TagItalic, HtmlUtil.TagFont).SplitToLines()) { if (parameter.AlignLeft) { lefts.Add(5); } else if (parameter.AlignRight) { lefts.Add(bmp.Width - (TextDraw.MeasureTextWidth(font, line, parameter.SubtitleFontBold) + 15)); } else { lefts.Add((float)((bmp.Width - TextDraw.MeasureTextWidth(font, line, parameter.SubtitleFontBold) + 15) / 2.0)); } } } var sf = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Near }; using (var g = Graphics.FromImage(bmp)) { g.CompositingQuality = CompositingQuality.HighQuality; g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.SmoothingMode = SmoothingMode.HighQuality; g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; if (parameter.SimpleRendering) { if (text.StartsWith("<font ", StringComparison.Ordinal) && Utilities.CountTagInText(text, "<font") == 1) { parameter.SubtitleColor = Utilities.GetColorFromFontString(text, parameter.SubtitleColor); } text = HtmlUtil.RemoveHtmlTags(text, true); // TODO: Perhaps check single color... var brush = new SolidBrush(parameter.BorderColor); int x = 3; const int y = 3; sf.Alignment = StringAlignment.Near; if (parameter.AlignLeft) { sf.Alignment = StringAlignment.Near; } else if (parameter.AlignRight) { sf.Alignment = StringAlignment.Far; x = parameter.ScreenWidth - 5; } else { sf.Alignment = StringAlignment.Center; x = parameter.ScreenWidth / 2; } bmp = new Bitmap(parameter.ScreenWidth, sizeY); Graphics surface = Graphics.FromImage(bmp); surface.CompositingQuality = CompositingQuality.HighSpeed; surface.InterpolationMode = InterpolationMode.Default; surface.SmoothingMode = SmoothingMode.HighSpeed; surface.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; for (int j = 0; j < parameter.BorderWidth; j++) { surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j + 1, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j + 1, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j + 1, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j - 1, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j - 1, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j - 1, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j + 1, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j + 1, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j + 1, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j - 1, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j - 1, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - j - 1, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j + 1, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y - 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y - 0 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + j - 1, Y = y + 1 + j }, sf); surface.DrawString(text, font, brush, new PointF { X = x, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + 1, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + 1, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x + 1, Y = y + 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - 1, Y = y - 1 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - 1, Y = y - 0 - j }, sf); surface.DrawString(text, font, brush, new PointF { X = x - 1, Y = y + 1 - j }, sf); } brush.Dispose(); brush = new SolidBrush(parameter.SubtitleColor); surface.CompositingQuality = CompositingQuality.HighQuality; surface.SmoothingMode = SmoothingMode.HighQuality; surface.InterpolationMode = InterpolationMode.HighQualityBicubic; surface.DrawString(text, font, brush, new PointF { X = x, Y = y }, sf); surface.Dispose(); brush.Dispose(); } else { var path = new GraphicsPath(); var sb = new StringBuilder(); bool isItalic = false; bool isBold = parameter.SubtitleFontBold; float left = 5; if (lefts.Count > 0) { left = lefts[0]; } float top = 5; bool newLine = false; int lineNumber = 0; float leftMargin = left; int newLinePathPoint = -1; Color c = parameter.SubtitleColor; var colorStack = new Stack<Color>(); var lastText = new StringBuilder(); int numberOfCharsOnCurrentLine = 0; for (var i = 0; i < text.Length; i++) { if (text.Substring(i).StartsWith("<font ", StringComparison.OrdinalIgnoreCase)) { float addLeft = 0; int oldPathPointIndex = path.PointCount; if (oldPathPointIndex < 0) { oldPathPointIndex = 0; } if (sb.Length > 0) { lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); } if (path.PointCount > 0) { var list = (PointF[])path.PathPoints.Clone(); // avoid using very slow path.PathPoints indexer!!! for (int k = oldPathPointIndex; k < list.Length; k++) { if (list[k].X > addLeft) { addLeft = list[k].X; } } } if (path.PointCount == 0) { addLeft = left; } else if (addLeft < 0.01) { addLeft = left + 2; } left = addLeft; DrawShadowAndPath(parameter, g, path); var p2 = new SolidBrush(c); g.FillPath(p2, path); p2.Dispose(); path.Reset(); path = new GraphicsPath(); sb = new StringBuilder(); int endIndex = text.Substring(i).IndexOf('>'); if (endIndex < 0) { i += 9999; } else { string fontContent = text.Substring(i, endIndex); if (fontContent.Contains(" color=")) { string[] arr = fontContent.Substring(fontContent.IndexOf(" color=", StringComparison.Ordinal) + 7).Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (arr.Length > 0) { string fontColor = arr[0].Trim('\'').Trim('"').Trim('\''); try { colorStack.Push(c); // save old color if (fontColor.StartsWith("rgb(", StringComparison.Ordinal)) { arr = fontColor.Remove(0, 4).TrimEnd(')').Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); c = Color.FromArgb(int.Parse(arr[0]), int.Parse(arr[1]), int.Parse(arr[2])); } else { c = ColorTranslator.FromHtml(fontColor); } } catch { c = parameter.SubtitleColor; } } } i += endIndex; } } else if (text.Substring(i).StartsWith("</font>", StringComparison.OrdinalIgnoreCase)) { if (text.Substring(i).ToLower().Replace("</font>", string.Empty).Length > 0) { if (lastText.EndsWith(' ') && !sb.StartsWith(' ')) { string t = sb.ToString(); sb.Clear(); sb.Append(' '); sb.Append(t); } float addLeft = 0; int oldPathPointIndex = path.PointCount - 1; if (oldPathPointIndex < 0) { oldPathPointIndex = 0; } if (sb.Length > 0) { if (lastText.Length > 0 && left > 2) { left -= 1.5f; } lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); } if (path.PointCount > 0) { var list = (PointF[])path.PathPoints.Clone(); // avoid using very slow path.PathPoints indexer!!! for (int k = oldPathPointIndex; k < list.Length; k++) { if (list[k].X > addLeft) { addLeft = list[k].X; } } } if (addLeft < 0.01) { addLeft = left + 2; } left = addLeft; DrawShadowAndPath(parameter, g, path); g.FillPath(new SolidBrush(c), path); path.Reset(); sb = new StringBuilder(); if (colorStack.Count > 0) { c = colorStack.Pop(); } if (left >= 3) { left -= 2.5f; } } i += 6; } else if (text.Substring(i).StartsWith("<i>", StringComparison.OrdinalIgnoreCase)) { if (sb.Length > 0) { lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); } isItalic = true; i += 2; } else if (text.Substring(i).StartsWith("</i>", StringComparison.OrdinalIgnoreCase) && isItalic) { if (lastText.EndsWith(' ') && !sb.StartsWith(' ')) { string t = sb.ToString(); sb.Clear(); sb.Append(' '); sb.Append(t); } lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); isItalic = false; i += 3; } else if (text.Substring(i).StartsWith("<b>", StringComparison.OrdinalIgnoreCase)) { if (sb.Length > 0) { lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, isBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); } isBold = true; i += 2; } else if (text.Substring(i).StartsWith("</b>", StringComparison.OrdinalIgnoreCase) && isBold) { if (lastText.EndsWith(' ') && !sb.StartsWith(' ')) { string t = sb.ToString(); sb.Clear(); sb.Append(' '); sb.Append(t); } lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, isBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); isBold = false; i += 3; } else if (text.Substring(i).StartsWith(Environment.NewLine, StringComparison.Ordinal)) { lastText.Append(sb); TextDraw.DrawText(font, sf, path, sb, isItalic, isBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); top += lineHeight; newLine = true; i += Environment.NewLine.Length - 1; lineNumber++; if (lineNumber < lefts.Count) { leftMargin = lefts[lineNumber]; left = leftMargin; } numberOfCharsOnCurrentLine = 0; } else { if (numberOfCharsOnCurrentLine != 0 || text[i] != ' ') { sb.Append(text[i]); numberOfCharsOnCurrentLine++; } } } if (sb.Length > 0) { TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint); } DrawShadowAndPath(parameter, g, path); g.FillPath(new SolidBrush(c), path); } } sf.Dispose(); var nbmp = new NikseBitmap(bmp); if (parameter.BackgroundColor == Color.Transparent) { nbmp.CropTransparentSidesAndBottom(baseLinePadding, true); nbmp.CropTransparentSidesAndBottom(2, false); } else { nbmp.CropSidesAndBottom(4, parameter.BackgroundColor, true); nbmp.CropTop(4, parameter.BackgroundColor); } if (nbmp.Width > parameter.ScreenWidth) { parameter.Error = "#" + parameter.P.Number.ToString(CultureInfo.InvariantCulture) + ": " + nbmp.Width.ToString(CultureInfo.InvariantCulture) + " > " + parameter.ScreenWidth.ToString(CultureInfo.InvariantCulture); } if (parameter.Type3D == 1) { // Half-side-by-side 3D Bitmap singleBmp = nbmp.GetBitmap(); Bitmap singleHalfBmp = ScaleToHalfWidth(singleBmp); singleBmp.Dispose(); var sideBySideBmp = new Bitmap(parameter.ScreenWidth, singleHalfBmp.Height); int singleWidth = parameter.ScreenWidth / 2; int singleLeftMargin = (singleWidth - singleHalfBmp.Width) / 2; using (Graphics gSideBySide = Graphics.FromImage(sideBySideBmp)) { gSideBySide.DrawImage(singleHalfBmp, singleLeftMargin + parameter.Depth3D, 0); gSideBySide.DrawImage(singleHalfBmp, singleWidth + singleLeftMargin - parameter.Depth3D, 0); } nbmp = new NikseBitmap(sideBySideBmp); if (parameter.BackgroundColor == Color.Transparent) { nbmp.CropTransparentSidesAndBottom(2, true); } else { nbmp.CropSidesAndBottom(4, parameter.BackgroundColor, true); } } else if (parameter.Type3D == 2) { // Half-Top/Bottom 3D nbmp = Make3DTopBottom(parameter, nbmp); } return nbmp.GetBitmap(); } finally { if (font != null) { font.Dispose(); } if (bmp != null) { bmp.Dispose(); } } }
private void comboBoxSubtitleFontSize_SelectedIndexChanged(object sender, EventArgs e) { Bitmap bmp = new Bitmap(100, 100); using (Graphics g = Graphics.FromImage(bmp)) { var mbp = new MakeBitmapParameter(); mbp.SubtitleFontName = _subtitleFontName; mbp.SubtitleFontSize = float.Parse(comboBoxSubtitleFontSize.SelectedItem.ToString()); mbp.SubtitleFontBold = _subtitleFontBold; var fontSize = g.DpiY * mbp.SubtitleFontSize / 72; Font font = SetFont(mbp, fontSize); SizeF textSize = g.MeasureString("Hj!", font); int lineHeight = (int)Math.Round(textSize.Height * 0.64f); if (lineHeight >= numericUpDownLineSpacing.Minimum && lineHeight <= numericUpDownLineSpacing.Maximum && lineHeight != numericUpDownLineSpacing.Value) numericUpDownLineSpacing.Value = lineHeight; else if (lineHeight > numericUpDownLineSpacing.Maximum) numericUpDownLineSpacing.Value = numericUpDownLineSpacing.Maximum; } subtitleListView1_SelectedIndexChanged(null, null); }
/// <summary> /// The make 3 d top bottom. /// </summary> /// <param name="parameter"> /// The parameter. /// </param> /// <param name="nbmp"> /// The nbmp. /// </param> /// <returns> /// The <see cref="NikseBitmap"/>. /// </returns> private static NikseBitmap Make3DTopBottom(MakeBitmapParameter parameter, NikseBitmap nbmp) { Bitmap singleBmp = nbmp.GetBitmap(); Bitmap singleHalfBmp = ScaleToHalfHeight(singleBmp); singleBmp.Dispose(); var topBottomBmp = new Bitmap(parameter.ScreenWidth, parameter.ScreenHeight - parameter.BottomMargin); int singleHeight = parameter.ScreenHeight / 2; int leftM = (parameter.ScreenWidth / 2) - (singleHalfBmp.Width / 2); using (Graphics gTopBottom = Graphics.FromImage(topBottomBmp)) { gTopBottom.DrawImage(singleHalfBmp, leftM + parameter.Depth3D, singleHeight - singleHalfBmp.Height - parameter.BottomMargin); gTopBottom.DrawImage(singleHalfBmp, leftM - parameter.Depth3D, parameter.ScreenHeight - parameter.BottomMargin - singleHalfBmp.Height); } nbmp = new NikseBitmap(topBottomBmp); if (parameter.BackgroundColor == Color.Transparent) { nbmp.CropTop(2, Color.Transparent); nbmp.CropTransparentSidesAndBottom(2, false); } else { nbmp.CropTop(4, parameter.BackgroundColor); nbmp.CropSidesAndBottom(4, parameter.BackgroundColor, false); } return nbmp; }
/// <summary> /// The write paragraph. /// </summary> /// <param name="width"> /// The width. /// </param> /// <param name="sb"> /// The sb. /// </param> /// <param name="border"> /// The border. /// </param> /// <param name="height"> /// The height. /// </param> /// <param name="imagesSavedCount"> /// The images saved count. /// </param> /// <param name="vobSubWriter"> /// The vob sub writer. /// </param> /// <param name="binarySubtitleFile"> /// The binary subtitle file. /// </param> /// <param name="param"> /// The param. /// </param> /// <param name="i"> /// The i. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> private int WriteParagraph(int width, StringBuilder sb, int border, int height, int imagesSavedCount, VobSubWriter vobSubWriter, FileStream binarySubtitleFile, MakeBitmapParameter param, int i) { if (param.Bitmap != null) { if (this._exportType == "BLURAYSUP") { if (!param.Saved) { binarySubtitleFile.Write(param.Buffer, 0, param.Buffer.Length); } param.Saved = true; } else if (this._exportType == "VOBSUB") { if (!param.Saved) { vobSubWriter.WriteParagraph(param.P, param.Bitmap, param.Alignment); } param.Saved = true; } else if (this._exportType == "FAB") { if (!param.Saved) { string numberString = string.Format("IMAGE{0:000}", i); string fileName = Path.Combine(this.folderBrowserDialog1.SelectedPath, numberString + "." + this.comboBoxImageFormat.Text.ToLower()); if (this.checkBoxFullFrameImage.Visible && this.checkBoxFullFrameImage.Checked) { var nbmp = new NikseBitmap(param.Bitmap); nbmp.ReplaceTransparentWith(this.panelFullFrameBackground.BackColor); using (var bmp = nbmp.GetBitmap()) { // param.Bitmap.Save(fileName, ImageFormat); imagesSavedCount++; // RACE001.TIF 00;00;02;02 00;00;03;15 000 000 720 480 // RACE002.TIF 00;00;05;18 00;00;09;20 000 000 720 480 int top = param.ScreenHeight - (param.Bitmap.Height + param.BottomMargin); int left = (param.ScreenWidth - param.Bitmap.Width) / 2; var b = new NikseBitmap(param.ScreenWidth, param.ScreenHeight); { b.Fill(this.panelFullFrameBackground.BackColor); using (var fullSize = b.GetBitmap()) { if (param.Alignment == ContentAlignment.BottomLeft || param.Alignment == ContentAlignment.MiddleLeft || param.Alignment == ContentAlignment.TopLeft) { left = param.LeftRightMargin; } else if (param.Alignment == ContentAlignment.BottomRight || param.Alignment == ContentAlignment.MiddleRight || param.Alignment == ContentAlignment.TopRight) { left = param.ScreenWidth - param.Bitmap.Width - param.LeftRightMargin; } if (param.Alignment == ContentAlignment.TopLeft || param.Alignment == ContentAlignment.TopCenter || param.Alignment == ContentAlignment.TopRight) { top = param.BottomMargin; } if (param.Alignment == ContentAlignment.MiddleLeft || param.Alignment == ContentAlignment.MiddleCenter || param.Alignment == ContentAlignment.MiddleRight) { top = param.ScreenHeight - (param.Bitmap.Height / 2); } using (var g = Graphics.FromImage(fullSize)) { g.DrawImage(bmp, left, top); g.Dispose(); } this.SaveImage(fullSize, fileName, this.ImageFormat); } } left = 0; top = 0; sb.AppendLine(string.Format("{0} {1} {2} {3} {4} {5} {6}", Path.GetFileName(fileName), FormatFabTime(param.P.StartTime, param), FormatFabTime(param.P.EndTime, param), left, top, left + param.ScreenWidth, top + param.ScreenHeight)); } } else { this.SaveImage(param.Bitmap, fileName, this.ImageFormat); imagesSavedCount++; // RACE001.TIF 00;00;02;02 00;00;03;15 000 000 720 480 // RACE002.TIF 00;00;05;18 00;00;09;20 000 000 720 480 int top = param.ScreenHeight - (param.Bitmap.Height + param.BottomMargin); int left = (param.ScreenWidth - param.Bitmap.Width) / 2; if (param.Alignment == ContentAlignment.BottomLeft || param.Alignment == ContentAlignment.MiddleLeft || param.Alignment == ContentAlignment.TopLeft) { left = param.LeftRightMargin; } else if (param.Alignment == ContentAlignment.BottomRight || param.Alignment == ContentAlignment.MiddleRight || param.Alignment == ContentAlignment.TopRight) { left = param.ScreenWidth - param.Bitmap.Width - param.LeftRightMargin; } if (param.Alignment == ContentAlignment.TopLeft || param.Alignment == ContentAlignment.TopCenter || param.Alignment == ContentAlignment.TopRight) { top = param.BottomMargin; } if (param.Alignment == ContentAlignment.MiddleLeft || param.Alignment == ContentAlignment.MiddleCenter || param.Alignment == ContentAlignment.MiddleRight) { top = param.ScreenHeight - (param.Bitmap.Height / 2); } sb.AppendLine(string.Format("{0} {1} {2} {3} {4} {5} {6}", Path.GetFileName(fileName), FormatFabTime(param.P.StartTime, param), FormatFabTime(param.P.EndTime, param), left, top, left + param.Bitmap.Width, top + param.Bitmap.Height)); } param.Saved = true; } } else if (this._exportType == "STL") { if (!param.Saved) { string numberString = string.Format("IMAGE{0:000}", i); string fileName = Path.Combine(this.folderBrowserDialog1.SelectedPath, numberString + "." + this.comboBoxImageFormat.Text.ToLower()); this.SaveImage(param.Bitmap, fileName, this.ImageFormat); imagesSavedCount++; const string paragraphWriteFormat = "{0} , {1} , {2}\r\n"; const string timeFormat = "{0:00}:{1:00}:{2:00}:{3:00}"; double factor = TimeCode.BaseUnit / Configuration.Settings.General.CurrentFrameRate; string startTime = string.Format(timeFormat, param.P.StartTime.Hours, param.P.StartTime.Minutes, param.P.StartTime.Seconds, (int)Math.Round(param.P.StartTime.Milliseconds / factor)); string endTime = string.Format(timeFormat, param.P.EndTime.Hours, param.P.EndTime.Minutes, param.P.EndTime.Seconds, (int)Math.Round(param.P.EndTime.Milliseconds / factor)); sb.AppendFormat(paragraphWriteFormat, startTime, endTime, fileName); param.Saved = true; } } else if (this._exportType == "SPUMUX") { if (!param.Saved) { string numberString = string.Format("IMAGE{0:000}", i); string fileName = Path.Combine(this.folderBrowserDialog1.SelectedPath, numberString + "." + this.comboBoxImageFormat.Text.ToLower()); foreach (var encoder in ImageCodecInfo.GetImageEncoders()) { if (encoder.FormatID == ImageFormat.Png.Guid) { var parameters = new EncoderParameters(); parameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 8); var nbmp = new NikseBitmap(param.Bitmap); var b = nbmp.ConverTo8BitsPerPixel(); b.Save(fileName, encoder, parameters); b.Dispose(); break; } } imagesSavedCount++; const string paragraphWriteFormat = "\t\t<spu start=\"{0}\" end=\"{1}\" image=\"{2}\" />"; const string timeFormat = "{0:00}:{1:00}:{2:00}:{3:00}"; double factor = TimeCode.BaseUnit / Configuration.Settings.General.CurrentFrameRate; string startTime = string.Format(timeFormat, param.P.StartTime.Hours, param.P.StartTime.Minutes, param.P.StartTime.Seconds, (int)Math.Round(param.P.StartTime.Milliseconds / factor)); string endTime = string.Format(timeFormat, param.P.EndTime.Hours, param.P.EndTime.Minutes, param.P.EndTime.Seconds, (int)Math.Round(param.P.EndTime.Milliseconds / factor)); sb.AppendLine(string.Format(paragraphWriteFormat, startTime, endTime, fileName)); param.Saved = true; } } else if (this._exportType == "FCP") { if (!param.Saved) { string numberString = string.Format(Path.GetFileNameWithoutExtension(Path.GetFileName(param.SavDialogFileName)) + "{0:0000}", i); string fileName = numberString + "." + this.comboBoxImageFormat.Text.ToLower(); string fileNameNoPath = Path.GetFileName(fileName); string fileNameNoExt = Path.GetFileNameWithoutExtension(fileNameNoPath); string template = " <clipitem id=\"" + fileNameNoPath + "\">" + Environment.NewLine + // <pathurl>file://localhost/" + fileNameNoPath.Replace(" ", "%20") + @"</pathurl> @" <name>" + fileNameNoPath + @"</name> <duration>[DURATION]</duration> <rate> <ntsc>FALSE</ntsc> <timebase>25</timebase> </rate> <in>[IN]</in> <out>[OUT]</out> <start>[START]</start> <end>[END]</end> <pixelaspectratio>" + param.VideoResolution + @"</pixelaspectratio> <stillframe>TRUE</stillframe> <anamorphic>FALSE</anamorphic> <alphatype>straight</alphatype> <masterclipid>" + fileNameNoPath + @"1</masterclipid>" + Environment.NewLine + " <file id=\"" + fileNameNoExt + "\">" + @" <name>" + fileNameNoPath + @"</name> <pathurl>" + fileNameNoPath.Replace(" ", "%20") + @"</pathurl> <rate> <timebase>25</timebase> </rate> <duration>[DURATION]</duration> <width>" + param.ScreenWidth + @"</width> <height>" + param.ScreenHeight + @"</height> <media> <video> <duration>[DURATION]</duration> <stillframe>TRUE</stillframe> <samplecharacteristics> <width>" + param.ScreenWidth + @"</width> <height>" + param.ScreenHeight + @"</height> </samplecharacteristics> </video> </media> </file> <sourcetrack> <mediatype>video</mediatype> </sourcetrack> <fielddominance>none</fielddominance> </clipitem>"; fileName = Path.Combine(Path.GetDirectoryName(param.SavDialogFileName), fileName); if (this.comboBoxImageFormat.Text == "8-bit png") { foreach (var encoder in ImageCodecInfo.GetImageEncoders()) { if (encoder.FormatID == ImageFormat.Png.Guid) { var parameters = new EncoderParameters(); parameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 8); var nbmp = new NikseBitmap(param.Bitmap); var b = nbmp.ConverTo8BitsPerPixel(); b.Save(fileName, encoder, parameters); b.Dispose(); break; } } } else { this.SaveImage(param.Bitmap, fileName, this.ImageFormat); } imagesSavedCount++; int duration = (int)Math.Round(param.P.Duration.TotalSeconds * param.FramesPerSeconds); int start = (int)Math.Round(param.P.StartTime.TotalSeconds * param.FramesPerSeconds); int end = (int)Math.Round(param.P.EndTime.TotalSeconds * param.FramesPerSeconds); template = template.Replace("[DURATION]", duration.ToString(CultureInfo.InvariantCulture)); template = template.Replace("[IN]", start.ToString(CultureInfo.InvariantCulture)); template = template.Replace("[OUT]", end.ToString(CultureInfo.InvariantCulture)); template = template.Replace("[START]", start.ToString(CultureInfo.InvariantCulture)); template = template.Replace("[END]", end.ToString(CultureInfo.InvariantCulture)); sb.AppendLine(template); param.Saved = true; } } else if (this._exportType == "DOST") { if (!param.Saved) { string numberString = string.Format("{0:0000}", i); string fileName = Path.Combine(Path.GetDirectoryName(this.saveFileDialog1.FileName), Path.GetFileNameWithoutExtension(this.saveFileDialog1.FileName).Replace(" ", "_")) + "_" + numberString + ".png"; foreach (var encoder in ImageCodecInfo.GetImageEncoders()) { if (encoder.FormatID == ImageFormat.Png.Guid) { var parameters = new EncoderParameters(); parameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 8); var nbmp = new NikseBitmap(param.Bitmap); var b = nbmp.ConverTo8BitsPerPixel(); b.Save(fileName, encoder, parameters); b.Dispose(); break; } } imagesSavedCount++; const string paragraphWriteFormat = "{0}\t{1}\t{2}\t{4}\t{5}\t{3}\t0\t0"; int top = param.ScreenHeight - (param.Bitmap.Height + param.BottomMargin); int left = (param.ScreenWidth - param.Bitmap.Width) / 2; if (param.Alignment == ContentAlignment.BottomLeft || param.Alignment == ContentAlignment.MiddleLeft || param.Alignment == ContentAlignment.TopLeft) { left = param.LeftRightMargin; } else if (param.Alignment == ContentAlignment.BottomRight || param.Alignment == ContentAlignment.MiddleRight || param.Alignment == ContentAlignment.TopRight) { left = param.ScreenWidth - param.Bitmap.Width - param.LeftRightMargin; } if (param.Alignment == ContentAlignment.TopLeft || param.Alignment == ContentAlignment.TopCenter || param.Alignment == ContentAlignment.TopRight) { top = param.BottomMargin; } if (param.Alignment == ContentAlignment.MiddleLeft || param.Alignment == ContentAlignment.MiddleCenter || param.Alignment == ContentAlignment.MiddleRight) { top = param.ScreenHeight - (param.Bitmap.Height / 2); } string startTime = this.BdnXmlTimeCode(param.P.StartTime); string endTime = this.BdnXmlTimeCode(param.P.EndTime); sb.AppendLine(string.Format(paragraphWriteFormat, numberString, startTime, endTime, Path.GetFileName(fileName), left, top)); param.Saved = true; } } else if (this._exportType == "IMAGE/FRAME") { if (!param.Saved) { var imageFormat = this.ImageFormat; int lastFrame = imagesSavedCount; int startFrame = (int)Math.Round(param.P.StartTime.TotalMilliseconds / (TimeCode.BaseUnit / param.FramesPerSeconds)); var empty = new Bitmap(param.ScreenWidth, param.ScreenHeight); if (imagesSavedCount == 0 && this.checkBoxSkipEmptyFrameAtStart.Checked) { } else { // Save empty picture for each frame up to start frame for (int k = lastFrame + 1; k < startFrame; k++) { string numberString = string.Format("{0:00000}", k); string fileName = Path.Combine(this.folderBrowserDialog1.SelectedPath, numberString + "." + this.comboBoxImageFormat.Text.ToLower()); empty.Save(fileName, imageFormat); imagesSavedCount++; } } int endFrame = (int)Math.Round(param.P.EndTime.TotalMilliseconds / (TimeCode.BaseUnit / param.FramesPerSeconds)); var fullSize = new Bitmap(param.ScreenWidth, param.ScreenHeight); Graphics g = Graphics.FromImage(fullSize); g.DrawImage(param.Bitmap, (param.ScreenWidth - param.Bitmap.Width) / 2, param.ScreenHeight - (param.Bitmap.Height + param.BottomMargin)); g.Dispose(); if (imagesSavedCount > startFrame) { startFrame = imagesSavedCount; // no overlapping } // Save sub picture for each frame in duration for (int k = startFrame; k <= endFrame; k++) { string numberString = string.Format("{0:00000}", k); string fileName = Path.Combine(this.folderBrowserDialog1.SelectedPath, numberString + "." + this.comboBoxImageFormat.Text.ToLower()); fullSize.Save(fileName, imageFormat); imagesSavedCount++; } fullSize.Dispose(); param.Saved = true; } } else if (this._exportType == "DCINEMA_INTEROP") { if (!param.Saved) { string numberString = string.Format("{0:0000}", i); string fileName = Path.Combine(Path.GetDirectoryName(this.saveFileDialog1.FileName), numberString + ".png"); param.Bitmap.Save(fileName, ImageFormat.Png); imagesSavedCount++; param.Saved = true; sb.AppendLine("<Subtitle FadeDownTime=\"" + 0 + "\" FadeUpTime=\"" + 0 + "\" TimeOut=\"" + DCSubtitle.ConvertToTimeString(param.P.EndTime) + "\" TimeIn=\"" + DCSubtitle.ConvertToTimeString(param.P.StartTime) + "\" SpotNumber=\"" + param.P.Number + "\">"); if (param.Depth3D == 0) { sb.AppendLine("<Image VPosition=\"9.7\" VAlign=\"bottom\" HAlign=\"center\">" + numberString + ".png" + "</Image>"); } else { sb.AppendLine("<Image VPosition=\"9.7\" ZPosition=\"" + param.Depth3D + "\" VAlign=\"bottom\" HAlign=\"center\">" + numberString + ".png" + "</Image>"); } sb.AppendLine("</Subtitle>"); } } else if (this._exportType == "EDL") { if (!param.Saved) { // 001 7M6C7986 V C 14:14:55:21 14:15:16:24 01:00:10:18 01:00:31:21 var fileName1 = "IMG" + i.ToString(CultureInfo.InvariantCulture).PadLeft(5, '0'); var fullSize = new Bitmap(param.ScreenWidth, param.ScreenHeight); using (var g = Graphics.FromImage(fullSize)) { g.DrawImage(param.Bitmap, (param.ScreenWidth - param.Bitmap.Width) / 2, param.ScreenHeight - (param.Bitmap.Height + param.BottomMargin)); } var fileName2 = Path.Combine(Path.GetDirectoryName(param.SavDialogFileName), fileName1 + ".PNG"); fullSize.Save(fileName2, ImageFormat.Png); fullSize.Dispose(); string line = string.Format("{0:000} {1} V C {2} {3} {4} {5}", i, fileName1, new TimeCode(0).ToHHMMSSFF(), param.P.Duration.ToHHMMSSFF(), param.P.StartTime.ToHHMMSSFF(), param.P.EndTime.ToHHMMSSFF()); sb.AppendLine(line); sb.AppendLine(); imagesSavedCount++; param.Saved = true; } } else { // BDNXML if (!param.Saved) { string numberString = string.Format("{0:0000}", i); string fileName = Path.Combine(this.folderBrowserDialog1.SelectedPath, numberString + ".png"); if (this.comboBoxImageFormat.Text == "Png 8-bit") { foreach (var encoder in ImageCodecInfo.GetImageEncoders()) { if (encoder.FormatID == ImageFormat.Png.Guid) { var parameters = new EncoderParameters(); parameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 8); var nbmp = new NikseBitmap(param.Bitmap); var b = nbmp.ConverTo8BitsPerPixel(); b.Save(fileName, encoder, parameters); b.Dispose(); break; } } } else { param.Bitmap.Save(fileName, ImageFormat.Png); } imagesSavedCount++; // <Event InTC="00:00:24:07" OutTC="00:00:31:13" Forced="False"> // <Graphic Width="696" Height="111" X="612" Y="930">subtitle_exp_0001.png</Graphic> // </Event> sb.AppendLine("<Event InTC=\"" + this.BdnXmlTimeCode(param.P.StartTime) + "\" OutTC=\"" + this.BdnXmlTimeCode(param.P.EndTime) + "\" Forced=\"" + param.Forced.ToString().ToLower() + "\">"); int x = (width - param.Bitmap.Width) / 2; int y = height - (param.Bitmap.Height + param.BottomMargin); switch (param.Alignment) { case ContentAlignment.BottomLeft: x = border; y = height - (param.Bitmap.Height + param.BottomMargin); break; case ContentAlignment.BottomRight: x = height - param.Bitmap.Width - border; y = height - (param.Bitmap.Height + param.BottomMargin); break; case ContentAlignment.MiddleCenter: x = (width - param.Bitmap.Width) / 2; y = (height - param.Bitmap.Height) / 2; break; case ContentAlignment.MiddleLeft: x = border; y = (height - param.Bitmap.Height) / 2; break; case ContentAlignment.MiddleRight: x = width - param.Bitmap.Width - border; y = (height - param.Bitmap.Height) / 2; break; case ContentAlignment.TopCenter: x = (width - param.Bitmap.Width) / 2; y = border; break; case ContentAlignment.TopLeft: x = border; y = border; break; case ContentAlignment.TopRight: x = width - param.Bitmap.Width - border; y = border; break; } sb.AppendLine(" <Graphic Width=\"" + param.Bitmap.Width.ToString(CultureInfo.InvariantCulture) + "\" Height=\"" + param.Bitmap.Height.ToString(CultureInfo.InvariantCulture) + "\" X=\"" + x.ToString(CultureInfo.InvariantCulture) + "\" Y=\"" + y.ToString(CultureInfo.InvariantCulture) + "\">" + numberString + ".png</Graphic>"); sb.AppendLine("</Event>"); param.Saved = true; } } } return imagesSavedCount; }
/// <summary> /// The make blu ray sup image. /// </summary> /// <param name="param"> /// The param. /// </param> private static void MakeBluRaySupImage(MakeBitmapParameter param) { var brSub = new Logic.BluRaySup.BluRaySupPicture { StartTime = (long)param.P.StartTime.TotalMilliseconds, EndTime = (long)param.P.EndTime.TotalMilliseconds, Width = param.ScreenWidth, Height = param.ScreenHeight, IsForced = param.Forced }; if (param.FullFrame) { var nbmp = new NikseBitmap(param.Bitmap); nbmp.ReplaceTransparentWith(param.FullFrameBackgroundcolor); using (var bmp = nbmp.GetBitmap()) { int top = param.ScreenHeight - (param.Bitmap.Height + param.BottomMargin); int left = (param.ScreenWidth - param.Bitmap.Width) / 2; var b = new NikseBitmap(param.ScreenWidth, param.ScreenHeight); { b.Fill(param.FullFrameBackgroundcolor); using (var fullSize = b.GetBitmap()) { if (param.Alignment == ContentAlignment.BottomLeft || param.Alignment == ContentAlignment.MiddleLeft || param.Alignment == ContentAlignment.TopLeft) { left = param.LeftRightMargin; } else if (param.Alignment == ContentAlignment.BottomRight || param.Alignment == ContentAlignment.MiddleRight || param.Alignment == ContentAlignment.TopRight) { left = param.ScreenWidth - param.Bitmap.Width - param.LeftRightMargin; } if (param.Alignment == ContentAlignment.TopLeft || param.Alignment == ContentAlignment.TopCenter || param.Alignment == ContentAlignment.TopRight) { top = param.BottomMargin; } if (param.Alignment == ContentAlignment.MiddleLeft || param.Alignment == ContentAlignment.MiddleCenter || param.Alignment == ContentAlignment.MiddleRight) { top = param.ScreenHeight - (param.Bitmap.Height / 2); } using (var g = Graphics.FromImage(fullSize)) { g.DrawImage(bmp, left, top); g.Dispose(); } param.Buffer = Logic.BluRaySup.BluRaySupPicture.CreateSupFrame(brSub, fullSize, param.FramesPerSeconds, 0, 0, ContentAlignment.BottomCenter); } } } } else { param.Buffer = Logic.BluRaySup.BluRaySupPicture.CreateSupFrame(brSub, param.Bitmap, param.FramesPerSeconds, param.BottomMargin, param.LeftRightMargin, param.Alignment); } }
/// <summary> /// The format fab time. /// </summary> /// <param name="time"> /// The time. /// </param> /// <param name="param"> /// The param. /// </param> /// <returns> /// The <see cref="string"/>. /// </returns> private static string FormatFabTime(TimeCode time, MakeBitmapParameter param) { if (param.Bitmap.Width == 720 && param.Bitmap.Width == 480) { // NTSC return string.Format("{0:00};{1:00};{2:00};{3:00}", time.Hours, time.Minutes, time.Seconds, SubtitleFormat.MillisecondsToFramesMaxFrameRate(time.Milliseconds)); } // drop frame if (Math.Abs(param.FramesPerSeconds - 24 * (999 / 1000)) < 0.01 || Math.Abs(param.FramesPerSeconds - 29 * (999 / 1000)) < 0.01 || Math.Abs(param.FramesPerSeconds - 59 * (999 / 1000)) < 0.01) { return string.Format("{0:00}:{1:00}:{2:00}:{3:00}", time.Hours, time.Minutes, time.Seconds, SubtitleFormat.MillisecondsToFramesMaxFrameRate(time.Milliseconds)); } return string.Format("{0:00};{1:00};{2:00};{3:00}", time.Hours, time.Minutes, time.Seconds, SubtitleFormat.MillisecondsToFramesMaxFrameRate(time.Milliseconds)); }
/// <summary> /// The make make bitmap parameter. /// </summary> /// <param name="index"> /// The index. /// </param> /// <param name="screenWidth"> /// The screen width. /// </param> /// <param name="screenHeight"> /// The screen height. /// </param> /// <returns> /// The <see cref="MakeBitmapParameter"/>. /// </returns> private MakeBitmapParameter MakeMakeBitmapParameter(int index, int screenWidth, int screenHeight) { var parameter = new MakeBitmapParameter { Type = this._exportType, SubtitleColor = this._subtitleColor, SubtitleFontName = this._subtitleFontName, SubtitleFontSize = this._subtitleFontSize, SubtitleFontBold = this._subtitleFontBold, BorderColor = this._borderColor, BorderWidth = this._borderWidth, SimpleRendering = this.checkBoxSimpleRender.Checked, AlignLeft = this.comboBoxHAlign.SelectedIndex == 0, AlignRight = this.comboBoxHAlign.SelectedIndex == 2, ScreenWidth = screenWidth, ScreenHeight = screenHeight, VideoResolution = this.comboBoxResolution.Text, Bitmap = null, FramesPerSeconds = this.FrameRate, BottomMargin = this.comboBoxBottomMargin.SelectedIndex, LeftRightMargin = this.comboBoxLeftRightMargin.SelectedIndex, Saved = false, Alignment = ContentAlignment.BottomCenter, Type3D = this.comboBox3D.SelectedIndex, Depth3D = (int)this.numericUpDownDepth3D.Value, BackgroundColor = Color.Transparent, SavDialogFileName = this.saveFileDialog1.FileName, ShadowColor = this.panelShadowColor.BackColor, ShadowWidth = this.comboBoxShadowWidth.SelectedIndex, ShadowAlpha = (int)this.numericUpDownShadowTransparency.Value, LineHeight = (int)this.numericUpDownLineSpacing.Value, FullFrame = this.checkBoxFullFrameImage.Checked, FullFrameBackgroundcolor = this.panelFullFrameBackground.BackColor, }; if (index < this._subtitle.Paragraphs.Count) { parameter.P = this._subtitle.Paragraphs[index]; parameter.Alignment = GetAlignmentFromParagraph(parameter, this._format, this._subtitle); parameter.Forced = this.subtitleListView1.Items[index].Checked; if (this._format.HasStyleSupport && !string.IsNullOrEmpty(parameter.P.Extra)) { if (this._format.GetType() == typeof(SubStationAlpha)) { var style = AdvancedSubStationAlpha.GetSsaStyle(parameter.P.Extra, this._subtitle.Header); parameter.SubtitleColor = style.Primary; parameter.SubtitleFontBold = style.Bold; parameter.SubtitleFontSize = style.FontSize; parameter.SubtitleFontName = style.FontName; if (style.BorderStyle == "3") { parameter.BackgroundColor = style.Background; } } else if (this._format.GetType() == typeof(AdvancedSubStationAlpha)) { var style = AdvancedSubStationAlpha.GetSsaStyle(parameter.P.Extra, this._subtitle.Header); parameter.SubtitleColor = style.Primary; parameter.SubtitleFontBold = style.Bold; parameter.SubtitleFontSize = style.FontSize; parameter.SubtitleFontName = style.FontName; if (style.BorderStyle == "3") { parameter.BackgroundColor = style.Outline; } } } if (this.comboBoxBorderWidth.SelectedItem.ToString() == Configuration.Settings.Language.ExportPngXml.BorderStyleBoxForEachLine) { parameter.BoxSingleLine = true; parameter.BackgroundColor = this.panelBorderColor.BackColor; parameter.BorderWidth = 0; } else if (this.comboBoxBorderWidth.SelectedItem.ToString() == Configuration.Settings.Language.ExportPngXml.BorderStyleOneBox) { parameter.BoxSingleLine = true; parameter.BackgroundColor = this.panelBorderColor.BackColor; parameter.BorderWidth = 0; } else { this._borderWidth = float.Parse(Utilities.RemoveNonNumbers(this.comboBoxBorderWidth.SelectedItem.ToString())); } } else { parameter.P = null; } return parameter; }
private static int CalcButtomCropping(string text, MakeBitmapParameter parameter) { var nbmp = GenereateBitmapForCalc(text, parameter); return nbmp.CalcBottomCropping(parameter.BorderColor); }