//////////////////////////////////////////////////////////////////// // Write object to PDF file //////////////////////////////////////////////////////////////////// internal override void WriteObjectToPdfFile() { // shortcut PdfBinaryWriter PdfFile = Document.PdfFile; // add items to dictionary Dictionary.Add("/Subtype", "/Image"); Dictionary.AddInteger("/Width", Chart.Width); Dictionary.AddInteger("/Height", Chart.Height); Dictionary.Add("/Filter", "/DCTDecode"); Dictionary.Add("/ColorSpace", "/DeviceRGB"); Dictionary.Add("/BitsPerComponent", "8"); // write dictionary Dictionary.WriteToPdfFile(); // output stream PdfFile.WriteString("stream\n"); // save pdf file position Int64 streamStart = PdfFile.BaseStream.Position; // debug if (Document.Debug) { PdfFile.WriteString("*** CHART PLACE HOLDER ***"); } // copy image file to output file else { // create memory stream MemoryStream MS = new MemoryStream(); // save image to memory stream Chart.SaveImage(MS, ChartImageFormat.Jpeg); // image byte array Byte[] ByteContents = MS.GetBuffer(); // encryption if (Document.Encryption != null) { ByteContents = Document.Encryption.EncryptByteArray(ObjectNumber, ByteContents); } // write memory stream internal buffer to PDF file PdfFile.Write(ByteContents); // close and dispose memory stream MS.Close(); } // save stream length ImageLengthObject.ContentsString.Append(((Int32)(PdfFile.BaseStream.Position - streamStart)).ToString()); // output stream PdfFile.WriteString("\nendstream\nendobj\n"); return; }
//////////////////////////////////////////////////////////////////// // Initial Object Array //////////////////////////////////////////////////////////////////// private void ConstructorHelper ( Double Width, // page width Double Height, // page height Double ScaleFactor, // scale factor from user units to points (i.e. 72.0 for inch) String FileName ) { // set scale factor (user units to points) this.ScaleFactor = ScaleFactor; // save page default size PageSize = new SizeD(Width, Height); // PDF document root object the Catalog object CatalogObject = new PdfObject(this, ObjectType.Dictionary, "/Catalog"); // add viewer preferences CatalogObject.Dictionary.Add("/ViewerPreferences", "<</PrintScaling/None>>"); // Parent object for all pages PagesObject = new PdfObject(this, ObjectType.Dictionary, "/Pages"); // add indirect reference to pages within the catalog object CatalogObject.Dictionary.AddIndirectReference("/Pages", PagesObject); // document id DocumentID = RandomByteArray(16); // save file name this.FileName = FileName; // convert stream to binary writer PdfFile = new PdfBinaryWriter(new FileStream(FileName, FileMode.Create, FileAccess.Write, FileShare.None)); // write PDF version number PdfFile.WriteString("%PDF-1.7\n"); // add this comment to tell compression programs that this is a binary file PdfFile.WriteString("%\u00b5\u00b5\u00b5\u00b5\n"); // exit return; }
/// <summary> /// PDF embedded file class constructor /// </summary> /// <param name="Document">Current document</param> /// <param name="FileName">File name</param> /// <param name="PdfFileName">PDF file name (see remarks)</param> /// <remarks> /// <para> /// FileName is the name of the source file on the disk. /// PDFFileName is the name of the as saved within the PDF document file. /// If PDFFileName is not given or it is set to null, the class takes /// the disk's file name without the path. /// </para> /// </remarks> public PdfEmbeddedFile ( PdfDocument Document, String FileName, String PdfFileName = null ) : base(Document, ObjectType.Dictionary, "/Filespec") { // save file name this.FileName = FileName; // test exitance if (!File.Exists(FileName)) { throw new ApplicationException("Embedded file " + FileName + " does not exist"); } // get file length FileInfo FI = new FileInfo(FileName); if (FI.Length > Int32.MaxValue - 4095) { throw new ApplicationException("Embedded file " + FileName + " too long"); } Int32 FileLength = (Int32)FI.Length; // translate file extension to mime type string MimeType = ExtToMime.TranslateExtToMime(FI.Extension); // create embedded file object PdfObject EmbeddedFile = new PdfObject(Document, ObjectType.Stream, "/EmbeddedFile"); // save uncompressed file length EmbeddedFile.Dictionary.AddFormat("/Params", "<</Size {0}>>", FileLength); // file data content byte array Byte[] FileData = new Byte[FileLength]; // load all the file's data FileStream DataStream = null; try { // open the file DataStream = new FileStream(FileName, FileMode.Open, FileAccess.Read); // read all the file if (DataStream.Read(FileData, 0, FileLength) != FileLength) { throw new Exception(); } } // loading file failed catch (Exception) { throw new ApplicationException("Invalid media file: " + FileName); } // close the file DataStream.Close(); // compress the data Byte[] FileDataComp = CompressStream(FileData); if (FileDataComp != null) { FileData = FileDataComp; EmbeddedFile.Dictionary.Add("/Filter", "/FlateDecode"); } // encryption if (Document.Encryption != null) { FileData = Document.Encryption.EncryptByteArray(EmbeddedFile.ObjectNumber, FileData); } // add compressed file length EmbeddedFile.Dictionary.AddInteger("/Length", FileData.Length); // shortcut PdfBinaryWriter PdfFile = Document.PdfFile; // save file position for this object EmbeddedFile.FilePosition = PdfFile.BaseStream.Position; // write object header PdfFile.WriteFormat("{0} 0 obj\n", EmbeddedFile.ObjectNumber); // write dictionary EmbeddedFile.Dictionary.WriteToPdfFile(); // output stream PdfFile.WriteString("stream\n"); // debug if (Document.Debug) { PdfFile.WriteString("*** MEDIAFILE PLACE HOLDER ***"); } // output embedded font else { PdfFile.Write(FileData); } // output stream PdfFile.WriteString("\nendstream\n"); // output object trailer PdfFile.WriteString("endobj\n"); // file spec object type Dictionary.Add("/Type", "/Filespec"); // PDF file name if (String.IsNullOrWhiteSpace(PdfFileName)) { PdfFileName = FI.Name; } Dictionary.AddPdfString("/F", PdfFileName); Dictionary.AddPdfString("/UF", PdfFileName); // add reference Dictionary.AddFormat("/EF", "<</F {0} 0 R /UF {0} 0 R>>", EmbeddedFile.ObjectNumber); return; }
//////////////////////////////////////////////////////////////////// // Initial Object Array //////////////////////////////////////////////////////////////////// private void ConstructorHelper ( double Width, // page width double Height, // page height double ScaleFactor, // scale factor from user units to points (i.e. 72.0 for inch) string FileName, Stream OutputStream ) { // set scale factor (user units to points) this.ScaleFactor = ScaleFactor; // set epsilon (1/300 of an inch in user units) Epsilon = 72.0 / (300.0 * ScaleFactor); // save page default size PageSize = new SizeD(Width, Height); // PDF document root object the Catalog object CatalogObject = new PdfObject(this, ObjectType.Dictionary, "/Catalog"); // add viewer preferences CatalogObject.Dictionary.Add("/ViewerPreferences", "<</PrintScaling/None>>"); // Parent object for all pages PagesObject = new PdfObject(this, ObjectType.Dictionary, "/Pages"); // add indirect reference to pages within the catalog object CatalogObject.Dictionary.AddIndirectReference("/Pages", PagesObject); // create trailer dictionary TrailerDict = new PdfDictionary(this); // add /Root TrailerDict.AddIndirectReference("/Root", CatalogObject); // document id DocumentID = RandomByteArray(16); // add /ID TrailerDict.AddFormat("/ID", "[{0}{0}]", ByteArrayToPdfHexString(DocumentID)); // create file using file name if (FileName != null) { // save file name this.FileName = FileName; // constructor helper PdfFile = new PdfBinaryWriter(new FileStream(FileName, FileMode.Create, FileAccess.Write, FileShare.None)); } // write to caller's file or memory stream else { PdfFile = new PdfBinaryWriter(OutputStream); } // write PDF version number PdfFile.WriteString("%PDF-1.7\n"); // add this comment to tell compression programs that this is a binary file PdfFile.WriteString("%\u00b5\u00b5\u00b5\u00b5\n"); // exit }
//////////////////////////////////////////////////////////////////// // Write object to PDF file //////////////////////////////////////////////////////////////////// internal override void WriteObjectToPdfFile() { // shortcut PdfBinaryWriter PdfFile = Document.PdfFile; // add items to dictionary Dictionary.Add("/Subtype", "/Image"); Dictionary.AddInteger("/Width", WidthPix); Dictionary.AddInteger("/Height", HeightPix); Dictionary.Add("/Filter", "/DCTDecode"); Dictionary.Add("/ColorSpace", "/DeviceRGB"); Dictionary.Add("/BitsPerComponent", "8"); // write dictionary Dictionary.WriteToPdfFile(); // output stream PdfFile.WriteString("stream\n"); // save pdf file position Int64 streamStart = PdfFile.BaseStream.Position; // debug if (Document.Debug) { PdfFile.WriteString("*** IMAGE PLACE HOLDER ***"); } // copy image file to output file else { // create memory stream MemoryStream MS = new MemoryStream(); // image quality is not 100 if (ImageQuality != 100) { // build EncoderParameter object for image quality EncoderParameters EncoderParameters = new EncoderParameters(1); EncoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, ImageQuality); // save in jpeg format with specified quality Picture.Save(MS, GetEncoderInfo("image/jpeg"), EncoderParameters); } else { // save in jpeg format with 100% quality Picture.Save(MS, ImageFormat.Jpeg); } // image byte array Byte[] ByteContents = MS.GetBuffer(); // encryption if (Document.Encryption != null) { ByteContents = Document.Encryption.EncryptByteArray(ObjectNumber, ByteContents); } // write memory stream internal buffer to PDF file PdfFile.Write(ByteContents); // close and dispose memory stream MS.Close(); MS = null; // dispose of the image Dispose(); } // save stream length ImageLengthObject.ContentsString.Append(((Int32)(PdfFile.BaseStream.Position - streamStart)).ToString()); // output stream PdfFile.WriteString("\nendstream\nendobj\n"); return; }
//////////////////////////////////////////////////////////////////// /// <summary> /// Create PDF document file /// </summary> /// <remarks> /// The last step of document creation after all pages were constructed. /// FileName is the path and name of the output file. /// </remarks> //////////////////////////////////////////////////////////////////// public void CreateFile() { // create page array StringBuilder Kids = new StringBuilder("["); for (Int32 Index = 0; Index < PageArray.Count; Index++) { Kids.AppendFormat("{0} 0 R ", PageArray[Index].ObjectNumber); } if (Kids.Length > 1) { Kids.Length--; } Kids.Append("]"); PagesObject.Dictionary.Add("/Kids", Kids.ToString()); // page count PagesObject.Dictionary.AddInteger("/Count", PageArray.Count); // objects for (Int32 Index = 0; Index < ObjectArray.Count; Index++) { ObjectArray[Index].WriteObjectHeaderToPdfFile(); } // save cross reference table position Int32 XRefPos = (Int32)PdfFile.BaseStream.Position; // cross reference PdfFile.WriteFormat("xref\n0 {0}\n0000000000 65535 f \n", ObjectArray.Count + 1); foreach (PdfObject PO in ObjectArray) { PdfFile.WriteFormat("{0:0000000000} 00000 n \n", PO.FilePosition); } // trailer PdfFile.WriteFormat("trailer\n<</Size {0}/Root 1 0 R/ID [{1}{1}]{2}>>\nstartxref\n{3}\n", ObjectArray.Count + 1, ByteArrayToPdfHexString(DocumentID), Encryption == null ? String.Empty : String.Format("/Encrypt {0} 0 R", Encryption.ObjectNumber), XRefPos); // write PDF end of file marker PdfFile.WriteString("%%EOF\n"); // close file PdfFile.Close(); // dispose all FontApi resources foreach (PdfObject Obj in ObjectArray) { if (Obj.GetType() == typeof(PdfFont)) { ((PdfFont)Obj).FontInfo.Dispose(); } } // dispose encryption resources if (Encryption != null) { Encryption.Dispose(); Encryption = null; } // successful exit return; }
//////////////////////////////////////////////////////////////////// // Write object to PDF file // Called by PdfDocument.CreateFile(FileName) method // to output one indirect PDF object. // It is a virtual method. Derived classes can overwrite it. //////////////////////////////////////////////////////////////////// internal virtual void WriteObjectToPdfFile() { // shortcut PdfBinaryWriter PdfFile = Document.PdfFile; // we have contents stream if (ContentsString != null && ContentsString.Length > 0) { // contents in bytes Byte[] ByteContents = new Byte[ContentsString.Length]; // convert content from string to binary // do not use Encoding.ASCII.GetBytes(...) for (Int32 Index = 0; Index < ContentsString.Length; Index++) { ByteContents[Index] = (Byte)ContentsString[Index]; } // if we have contents and dictionary we have a stream if (Dictionary != null) { // for testing compression is disabled if (!Document.Debug) { // compress stream Byte[] CompContents = CompressStream(ByteContents); if (CompContents != null) { ByteContents = CompContents; Dictionary.Add("/Filter", "/FlateDecode"); } } // encryption if (Document.Encryption != null) { ByteContents = Document.Encryption.EncryptByteArray(ObjectNumber, ByteContents); } // stream length Dictionary.AddInteger("/Length", ByteContents != null ? ByteContents.Length : 0); // write dictionary Dictionary.WriteToPdfFile(); // write stream reserved word PdfFile.WriteString("stream\n"); // write content to pdf file if (ByteContents != null) { PdfFile.Write(ByteContents); } // write end of stream PdfFile.WriteString("\nendstream\n"); } // we have contents but no dictionary else { // write content to pdf file PdfFile.Write(ByteContents); // final terminator PdfFile.Write('\n'); } } // no contents else { // we have a dictionary if (Dictionary != null) { // write dictionary Dictionary.WriteToPdfFile(); } // no contents and no dictionary else { throw new ApplicationException("Empty object"); } } // output object trailer PdfFile.WriteString("endobj\n"); return; }