Renders a page into a file.

 

   

Syntax
 

[C#]
virtual void Save(string path)

[Visual Basic]
Overridable Sub Save(path As String)

Throws Exceptions may throw Exception()

 

   

Params
 
Name Description
path The destination file path.

 

   

Notes
 

Renders a page to a file. The current page at the time the operation has been created is rendered.

This method is similar in functionality to XRendering.Save(), but it can be safely called on different instances of RenderOperation from different threads even for the same page of the same document provided the page is not modified while being rendered because the document rendering options and the page ID are local to the operation. In the example below we show how to render document pages using parallel threads.

Furthermore, this method generates the following events, allowing fine tuning of the rendering operations:
  1. Before rendering begins, a ProcessingObject event of ProcessingSourceType.PageContent is generated. Set the event arguments' Cancel property to true to skip rendering altogether.
  2. When a PDF path stroking or filling operator is found in the page content, a ProcessingObject event of ProcessingSourceType.Path is generated. Set the event arguments' Cancel property to true to skip this object. The stream length and position can be retrieved via the StreamPosition and StreamLength properties. Set the stream position to null to skip the remaining of the stream.
  3. When a text PDF operator is found, a ProcessingObject event of ProcessingSourceType.Text is generated. The Unicode text can be retrieved in the Text property of the event Info property. the event cancel property to true to skip this object. The stream length and position can be retrieved via the StreamPosition and StreamLength properties. Set the stream position to null to skip the remaining of the stream.
  4. When a shading PDF operator is found, a ProcessingObject event of ProcessingSourceType.Shading is generated. The same comments of point 2 above apply, for skipping the object or retrieving/setting the stream position and length.
  5. When an image is found (inline or XObject), a ProcessingObject event of ProcessingSourceType.Image is generated. If the image is XObject, the indirect object can be retrieved via the event arguments' Object property. the event cancel property to true to skip this object. The stream length and position can be retrieved via the StreamPosition and StreamLength properties. Set the stream position to null to skip the remaining of the stream.
  6. When a Form XObject is found, a ProcessingObject event of ProcessingSourceType.FormXObject is generated. The indirect object can be retrieved via the event arguments' Object property. Set the event arguments' Cancel property to true to skip this object. The stream length and position can be retrieved via the StreamPosition and StreamLength properties. Set the stream position to null to skip the remaining of the stream. In addition, because Forms contain streams, a ProcessingObject event of ProcessingSourceType.Stream will follow. You can set the stream position to null to skip the stream at any time. That is events for the objects contained in the Form stream will be generated, as described in points 2 to 5. Setting the stream position to null for Form objects will skip the Form stream, not the entire page content.
Every ProcessingObject event is followed by a corresponding ProcessedObject, event with the same source type. The PageContent ProcessedObject event will be the last event received, in that all the page objects events are sandwiched between a PageContent processing and processed events. Similarly for form streams, all the form objects events are sandwiched between a Stream processing and processed events, which in turn are sandwiched between the FormXObject processing and processed events.
 
Any event property or event Info property not mentioned here are ignored.
 
   

Example
 

Here we render all the pages of the doc using 10 threads at a time. We alternate rendering format between jpg and tiff. We also alternate resolution between 150 and 300 dpi. Note how the RenderingOperation is created in the constructor of TheRenderingWorker. This is because at this point a copy of the rendering options is made. Had we created the RenderingOperation in DoWork, we would have picked up only the last doc.Rendering.DotsPerInch, because the threads are started in the following loop. Also note how we dispose the operation in DoWork, to release resources stored on the native side (the copy of the rendering options basically).

[C#]class RenderingWorker
{
    private string mPath;
    private RenderOperation mOp;

    public RenderingWorker(Doc inDoc, string inPath)
    {
        mPath = inPath;
        mOp = new RenderOperation(inDoc);
    }
    public void DoWork()
    {
        mOp.Save(mPath);
        mOp.Dispose();
    }
}

Doc doc = new Doc();
doc.Read(Server.MapPath("ABCpdf.pdf"));
string[] theExts = { ".jpg", ".tif" };
int[] theDpis = { 150, 300 };
const int NUM_THREADS = 10;
Thread[] threadList = new Thread[NUM_THREADS];
while (doc.PageNumber < doc.PageCount)
{
    for (int i = 0; i < threadList.Length; ++i)
    {
        if (threadList[i] != null)
        {
            threadList[i] = null;
        }
    }
    for (int i = 0; i < threadList.Length; ++i)
    {
        doc.Rendering.DotsPerInch = (i % 2) == 0 ? theDpis[0] : theDpis[1];
        string ext = (i % 2) == 0 ? theExts[0] : theExts[1];
        string path = Server.MapPath("ABCpdf" + doc.PageNumber.ToString() + ext);
        threadList[i] = new Thread(new RenderingWorker(doc, path).DoWork);
        if (doc.PageNumber == doc.PageCount)
        {
            break;
        }
        else
        {
            doc.PageNumber++;
        }
    }
    for (int i = 0; i < threadList.Length; ++i)
    {
        if (threadList[i] != null)
        {
            threadList[i].Start();
        }
    }
    for (int i = 0; i < threadList.Length; ++i)
    {
        if (threadList[i] != null)
        {
            threadList[i].Join();
        }
    }
}
doc.Clear();

[Visual Basic]Class RenderingWorker
    Private mPath As String
    Private mOp As RenderOperation

    Public Sub New(ByVal inDoc As Doc, ByVal inPath As String)
        mPath = inPath
        mOp = New RenderOperation(inDoc)
    End Sub

    Public Sub DoWork()
        mOp.Save(mPath)
        mOp.Dispose()
    End Sub
End Class

Dim doc As Doc = new Doc()
doc.Read(Server.MapPath("ABCpdf.pdf"))
Dim theExts As String() = {".jpg", ".tif"}
Dim theDpis As Integer() = {150, 300}
Const NUM_THREADS As Integer = 10
Dim threadList(NUM_THREADS - 1) As Thread
While doc.PageNumber < doc.PageCount
    For i As Integer = 0 To threadList.Length - 1
        If threadList(i) IsNot Nothing Then
            threadList(i) = Nothing
        End If
    Next

    For i As Integer = 0 To threadList.Length - 1
        doc.Rendering.DotsPerInch = If((i Mod 2) = 0, theDpis(0), theDpis(1))

        Dim ext As String = If((i Mod 2) = 0, theExts(0), theExts(1))
        Dim path As String = Server.MapPath(("ABCpdf" & doc.PageNumber.ToString()) + ext)

        threadList(i) = New Thread(AddressOf New RenderingWorker(doc, path).DoWork)
        If doc.PageNumber = doc.PageCount Then
            Exit For
        Else
            doc.PageNumber += 1
        End If
    Next

    For i As Integer = 0 To threadList.Length - 1
        If threadList(i) IsNot Nothing Then
            threadList(i).Start()
        End If
    Next
    For i As Integer = 0 To threadList.Length - 1
        If threadList(i) IsNot Nothing Then
            threadList(i).Join()
        End If
    Next
End While
doc.Clear()