public void WriteParagraph(Paragraph p, Bitmap bmp, ContentAlignment alignment) // inspired by code from SubtitleCreator { // timestamp: 00:00:33:900, filepos: 000000000 _idx.AppendLine(string.Format("timestamp: {0:00}:{1:00}:{2:00}:{3:000}, filepos: {4}", p.StartTime.Hours, p.StartTime.Minutes, p.StartTime.Seconds, p.StartTime.Milliseconds, _subFile.Position.ToString("X").PadLeft(9, '0').ToLower())); var nbmp = new NikseBitmap(bmp); _emphasis2 = nbmp.ConverToFourColors(_background, _pattern, _emphasis1, _useInnerAntialiasing); var twoPartBuffer = nbmp.RunLengthEncodeForDvd(_background, _pattern, _emphasis1, _emphasis2); var imageBuffer = GetSubImageBuffer(twoPartBuffer, nbmp, p, alignment); int bufferIndex = 0; byte vobSubId = (byte)_languageStreamId; var mwsub = new MemWriter(200000); byte[] subHeader = new byte[30]; byte[] ts = new byte[4]; // Lended from "Son2VobSub" by Alain Vielle and Petr Vyskocil // And also from Sup2VobSub by Emmel subHeader[0] = 0x00; // MPEG 2 PACK HEADER subHeader[1] = 0x00; subHeader[2] = 0x01; subHeader[3] = 0xba; subHeader[4] = 0x44; subHeader[5] = 0x02; subHeader[6] = 0xc4; subHeader[7] = 0x82; subHeader[8] = 0x04; subHeader[9] = 0xa9; subHeader[10] = 0x01; subHeader[11] = 0x89; subHeader[12] = 0xc3; subHeader[13] = 0xf8; subHeader[14] = 0x00; // PES subHeader[15] = 0x00; subHeader[16] = 0x01; subHeader[17] = 0xbd; int packetSize = imageBuffer.Length; long toWrite = packetSize; // Image buffer + control sequence length bool header0 = true; while (toWrite > 0) { long headerSize; if (header0) { header0 = false; // This is only for first packet subHeader[20] = 0x81; // mark as original subHeader[21] = 0x80; // first packet: PTS subHeader[22] = 0x05; // PES header data length // PTS (90kHz): //-------------- subHeader[23] = (byte)((ts[3] & 0xc0) >> 5 | 0x21); subHeader[24] = (byte)((ts[3] & 0x3f) << 2 | (ts[2] & 0xc0) >> 6); subHeader[25] = (byte)((ts[2] & 0x3f) << 2 | (ts[1] & 0x80) >> 6 | 0x01); subHeader[26] = (byte)((ts[1] & 0x7f) << 1 | (ts[0] & 0x80) >> 7); subHeader[27] = (byte)((ts[0] & 0x7f) << 1 | 0x01); const string pre = "0010"; // 0011 or 0010 ? (KMPlayer will not understand 0011!!!) long newPts = (long)(p.StartTime.TotalSeconds * 90000.0 + 0.5); string bString = Convert.ToString(newPts, 2).PadLeft(33, '0'); string fiveBytesString = pre + bString.Substring(0, 3) + "1" + bString.Substring(3, 15) + "1" + bString.Substring(18, 15) + "1"; for (int i = 0; i < 5; i++) { subHeader[23 + i] = Convert.ToByte(fiveBytesString.Substring((i * 8), 8), 2); } subHeader[28] = vobSubId; headerSize = 29; } else { subHeader[20] = 0x81; // mark as original subHeader[21] = 0x00; // no PTS subHeader[22] = 0x00; // header data length subHeader[23] = vobSubId; headerSize = 24; } if ((toWrite + headerSize) <= 0x800) { // write whole image in one 0x800 part long j = (headerSize - 20) + toWrite; subHeader[18] = (byte)(j / 0x100); subHeader[19] = (byte)(j % 0x100); // First Write header for (int x = 0; x < headerSize; x++) { mwsub.WriteByte(subHeader[x]); } // Write Image Data for (int x = 0; x < toWrite; x++) { mwsub.WriteByte(imageBuffer[bufferIndex++]); } // Pad remaining space long paddingSize = 0x800 - headerSize - toWrite; for (int x = 0; x < paddingSize; x++) { mwsub.WriteByte(0xff); } toWrite = 0; } else { // write multiple parts long blockSize = 0x800 - headerSize; long j = (headerSize - 20) + blockSize; subHeader[18] = (byte)(j / 0x100); subHeader[19] = (byte)(j % 0x100); // First Write header for (int x = 0; x < headerSize; x++) { mwsub.WriteByte(subHeader[x]); } // Write Image Data for (int x = 0; x < blockSize; x++) { mwsub.WriteByte(imageBuffer[bufferIndex++]); } toWrite -= blockSize; } } // Write whole memory stream to file long endPosition = mwsub.GetPosition(); mwsub.GotoBegin(); _subFile.Write(mwsub.GetBuf(), 0, (int)endPosition); }
// inspired by code from SubtitleCreator public void WriteParagraph(Paragraph p, Bitmap bmp, ContentAlignment alignment) { // timestamp: 00:00:33:900, filepos: 000000000 _idx.AppendLine(string.Format("timestamp: {0:00}:{1:00}:{2:00}:{3:000}, filepos: {4}", p.StartTime.Hours, p.StartTime.Minutes, p.StartTime.Seconds, p.StartTime.Milliseconds, _subFile.Position.ToString("X").PadLeft(9, '0').ToLower())); var nbmp = new NikseBitmap(bmp); _emphasis2 = nbmp.ConverToFourColors(_background, _pattern, _emphasis1, _useInnerAntialiasing); var twoPartBuffer = nbmp.RunLengthEncodeForDvd(_background, _pattern, _emphasis1, _emphasis2); var imageBuffer = GetSubImageBuffer(twoPartBuffer, nbmp, p, alignment); int bufferIndex = 0; byte vobSubId = (byte)_languageStreamId; var mwsub = new MemWriter(200000); byte[] subHeader = new byte[30]; byte[] ts = new byte[4]; // Lended from "Son2VobSub" by Alain Vielle and Petr Vyskocil // And also from Sup2VobSub by Emmel subHeader[0] = 0x00; // MPEG 2 PACK HEADER subHeader[1] = 0x00; subHeader[2] = 0x01; subHeader[3] = 0xba; subHeader[4] = 0x44; subHeader[5] = 0x02; subHeader[6] = 0xc4; subHeader[7] = 0x82; subHeader[8] = 0x04; subHeader[9] = 0xa9; subHeader[10] = 0x01; subHeader[11] = 0x89; subHeader[12] = 0xc3; subHeader[13] = 0xf8; subHeader[14] = 0x00; // PES subHeader[15] = 0x00; subHeader[16] = 0x01; subHeader[17] = 0xbd; int packetSize = imageBuffer.Length; long toWrite = packetSize; // Image buffer + control sequence length bool header0 = true; while (toWrite > 0) { long headerSize; if (header0) { header0 = false; // This is only for first packet subHeader[20] = 0x81; // mark as original subHeader[21] = 0x80; // first packet: PTS subHeader[22] = 0x05; // PES header data length // PTS (90kHz): //-------------- subHeader[23] = (byte)((ts[3] & 0xc0) >> 5 | 0x21); subHeader[24] = (byte)((ts[3] & 0x3f) << 2 | (ts[2] & 0xc0) >> 6); subHeader[25] = (byte)((ts[2] & 0x3f) << 2 | (ts[1] & 0x80) >> 6 | 0x01); subHeader[26] = (byte)((ts[1] & 0x7f) << 1 | (ts[0] & 0x80) >> 7); subHeader[27] = (byte)((ts[0] & 0x7f) << 1 | 0x01); const string pre = "0010"; // 0011 or 0010 ? (KMPlayer will not understand 0011!!!) long newPts = (long)(p.StartTime.TotalSeconds * 90000.0 + 0.5); string bString = Convert.ToString(newPts, 2).PadLeft(33, '0'); string fiveBytesString = pre + bString.Substring(0, 3) + "1" + bString.Substring(3, 15) + "1" + bString.Substring(18, 15) + "1"; for (int i = 0; i < 5; i++) { subHeader[23 + i] = Convert.ToByte(fiveBytesString.Substring((i * 8), 8), 2); } subHeader[28] = vobSubId; headerSize = 29; } else { subHeader[20] = 0x81; // mark as original subHeader[21] = 0x00; // no PTS subHeader[22] = 0x00; // header data length subHeader[23] = vobSubId; headerSize = 24; } if ((toWrite + headerSize) <= 0x800) { // write whole image in one 0x800 part long j = (headerSize - 20) + toWrite; subHeader[18] = (byte)(j / 0x100); subHeader[19] = (byte)(j % 0x100); // First Write header for (int x = 0; x < headerSize; x++) mwsub.WriteByte(subHeader[x]); // Write Image Data for (int x = 0; x < toWrite; x++) mwsub.WriteByte(imageBuffer[bufferIndex++]); // Pad remaining space long paddingSize = 0x800 - headerSize - toWrite; for (int x = 0; x < paddingSize; x++) mwsub.WriteByte(0xff); toWrite = 0; } else { // write multiple parts long blockSize = 0x800 - headerSize; long j = (headerSize - 20) + blockSize; subHeader[18] = (byte)(j / 0x100); subHeader[19] = (byte)(j % 0x100); // First Write header for (int x = 0; x < headerSize; x++) mwsub.WriteByte(subHeader[x]); // Write Image Data for (int x = 0; x < blockSize; x++) mwsub.WriteByte(imageBuffer[bufferIndex++]); toWrite -= blockSize; } } // Write whole memory stream to file long endPosition = mwsub.GetPosition(); mwsub.GotoBegin(); _subFile.Write(mwsub.GetBuf(), 0, (int)endPosition); }
/// <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; }
public void WriteParagraph(Paragraph p, Bitmap bmp) { // timestamp: 00:00:33:900, filepos: 000000000 _idx.AppendLine(string.Format("timestamp: {0:00}:{1:00}:{2:00}:{3:000}, filepos: {4}", p.StartTime.Hours, p.StartTime.Minutes, p.StartTime.Seconds, p.StartTime.Milliseconds, _subFile.Position.ToString("X").PadLeft(9, '0'))); // write binary vobsub file (duration + image) long start = _subFile.Position; _subFile.Write(Mpeg2PackHeaderBuffer, 0, Mpeg2PackHeaderBuffer.Length); NikseBitmap nbmp = new NikseBitmap(bmp); nbmp.ConverToFourColors(Color.Transparent, Color.White, Color.FromArgb(200, 0, 0, 0), Color.FromArgb(200, 25, 25, 25)); var outBmp = nbmp.GetBitmap(); outBmp.Save(@"D:\download\-_-" + p.Number.ToString() + ".bmp"); bmp.Save(@"D:\download\-__" + p.Number.ToString() + ".bmp"); outBmp.Dispose(); var twoPartBuffer = nbmp.RunLengthEncodeForDvd(Color.Transparent, Color.White, Color.FromArgb(200, 0, 0, 0), Color.FromArgb(200, 25, 25, 25)); // PES size int length = Mpeg2PackHeaderBuffer.Length + PacketizedElementaryStreamHeaderBufferFirst.Length + 10 + twoPartBuffer.Length; //block_size = 0x800 - header_size; //long j = (header_size - 20) + block_size; //SubHeader[18] = (byte)(j / 0x100); //SubHeader[19] = (byte)(j % 0x100); PacketizedElementaryStreamHeaderBufferFirst[4] = (byte)(length / 256); PacketizedElementaryStreamHeaderBufferFirst[5] = (byte)(length % 256); _subFile.Write(PacketizedElementaryStreamHeaderBufferFirst, 0, PacketizedElementaryStreamHeaderBufferFirst.Length); // PTS (timestamp) FillPTS(p.StartTime); _subFile.Write(PresentationTimeStampBuffer, 0, PresentationTimeStampBuffer.Length); _subFile.WriteByte(0x32); //sub-stream number if (twoPartBuffer.Length < 0x800 - (_subFile.Position - start)) { _subFile.Write(twoPartBuffer.Buffer1, 0, twoPartBuffer.Buffer1.Length); _subFile.Write(twoPartBuffer.Buffer2, 0, twoPartBuffer.Buffer2.Length); } else { System.Windows.Forms.MessageBox.Show("Too long for payload!!!"); } // HeaderDataLength = buffer[index + 8]; // language id // int id = buffer[9 + HeaderDataLength]; // if (id >= 0x20 && id <= 0x40) // x3f 0r x40 ? // SubPictureStreamId = id; //} for (long i = _subFile.Position - start; i < 0x800; i++) // 2048 packet size - pad with 0xff { _subFile.WriteByte(0xff); } }