Working with PDF

PDF was developed by Adobe Systems, Inc. for secure and reliable distribution of electronic documents independent of software, hardware, and operating system. In general, a PDF file includes a complete description of a fixed-layout flat document, such as the text, fonts, graphics, and other information needed to display it.

Graphics Mill supports reading and writing to PDF files. A PDF document can be either a raster or vector file. This topic demonstrates how to create PDF documents and read their content in Graphics Mill.

Using Bitmap.Save

In the simplest case, you can create a single-page PDF document using the Bitmap.Save method. You just create a bitmap containing the desired data and save it in the PDF file format. Additionally, you can provide PDF compression parameters via the PdfSettings class.

The code below creates a PDF file with a single page containing a raster text string.

C#
using (var bitmap = new Bitmap(640, 480, PixelFormat.Format24bppRgb, RgbColor.White))
{
    using (var graphics = bitmap.GetGraphics())
    {
        var font = new Aurigma.GraphicsMill.Drawing.Font("Times New Roman", 20);
        var brush = new Aurigma.GraphicsMill.Drawing.SolidBrush(RgbColor.Black);

        graphics.DrawString("Graphics Mill", font, brush, 220, 200);

        bitmap.Save(@"Images\Output\out.pdf", new PdfSettings(CompressionType.Jpeg, 90));
    }
}

If you open the resulting PDF file, you will note that the text quality degrades while zooming in/out and selecting a text string does not work. The reason is that the text is stored in a raster structure. Therefore, if you want to draw high-quality vector text and graphics or create multipage documents, you should use the PdfWriter class.

Using PdfWriter

The PdfWriter class introduces a more flexible way to create PDF documents. Using this class, you can create PDF documents containing raster images and vector shapes. You can also draw vector text that has advantages compared to raster text - the text is scaled without distortion.

PdfWriter allows for creating multipage PDF documents. It provides the AddPage method that appends a new blank page to the document. For each page, you can create Graphics via the GetGraphics() method, which is necessary for drawing on a PDF. Note that you can draw only on the last created page. To learn in detail how to draw Graphics, read the Drawing section. The following snippet demonstrates how to create a single-page PDF document with the specified size, and how to get Graphics from it:

C#
using (var pdfWriter = new PdfWriter(@"Images\Output\out.pdf"))
{
    pdfWriter.AddPage(500, 500);
    using (var graphics = pdfWriter.GetGraphics())
    {
        //...
    }
}

PdfWriter provides a number of overloaded AddPage methods allowing you to specify the DPI of a new page, its background color, color profile, or boundaries. Let us discuss how to specify some of these settings in more detail.

Page Boundaries

Graphics Mill provides the following boundaries for PDF documents:

  • Crop Box is a rectangle defining the region surrounding the content which is to be clipped when the PDF page is displayed or printed. The Crop Box specifies the visible part of the content.
  • Bleed Box is a rectangle defining the region to which the contents of the page should be clipped when output in a production environment. By default, the Bleed Box equals the Crop Box.
  • Trim Box is the dimensions of the fulfilled page. In contrast with the Crop Box, the Trim Box is important because it defines the actual page size used for positioning pages on a press sheet.

The following snippet demonstrates how to add a new page to the PDF document with the specified DPI, background color, crop box, trim box, and bleed box:

C#
using (var pdfWriter = new PdfWriter(@"Images\Output\out.pdf"))
{
    var dpi = 300f;
    pdfWriter.AddPage(500, 500, dpi, dpi, RgbColor.LightCoral, new System.Drawing.RectangleF(10, 10, 480, 480), 
        new System.Drawing.RectangleF(30, 30, 380, 380), new System.Drawing.RectangleF(20, 20, 400, 400));
    using (var graphics = pdfWriter.GetGraphics())
    {
        //...
    }
}

Color Profile

A PDF document does not have a single color space for its pages. All graphic elements drawn on a PDF page have their own color spaces. For instance, you can draw a CMYK line and RGB bitmap on the same page and both of these elements will be displayed correctly according to their color spaces. However, you can specify a color profile that defines color characteristics and the color gamut of the resulting PDF page. If you are not familiar with concepts such as color management and color profiles, read the Color Management Basics article.

By default, the PDF page does not have a color profile, thus all graphic elements are drawn on the page without managing color. If the page was created with a profile, color management converts the colors of drawn graphics according to the specified profile. The following snippet illustrates how to add a new page to the PDF document with a CMYK profile:

C#
using (var pdfWriter = new PdfWriter(@"Images\Output\out.pdf"))
{
    pdfWriter.AddPage(500, 500, new ColorProfile(@"_Input\ColorProfiles\CoatedFOGRA27.icc"));
    using (var graphics = pdfWriter.GetGraphics())
    {
        //...
    }
}

Compression Type

The Compression property defines the compression of a PDF file. Its default value is Zip. It works well for text PDFs, but for PDFs containing images, Jpeg can be significantly more effective. Also, you can set the Quality of JPEG compression.

You can set compression type to Jpeg via PdfWriter.Compression:

C#
PdfWriter pdfWriter = new PdfWriter(@"Images\Output\out.pdf");
pdfWriter.Compression = CompressionType.Jpeg;
pdfWriter.Quality = 70;

or via PdfSettings.Compression:

C#
PdfSettings pdfSettings = new PdfSettings();
pdfSettings.Compression = CompressionType.Jpeg;
pdfSettings.Quality = 70;

Working with Device Independent Coordinates

When creating a PDF document, you may need to work with device independent coordinates (for example, inches) instead of pixels. However, the AddPage method only allows for specifying the size of a new page in pixels. In this case, you can use the UnitConverter.ConvertUnitsToPixels(Single, Single, Unit) method, which converts inches to pixels according to the given DPI. Assume that we need to create a 3.5"x2.5" PDF with 300 DPI. Here is the snippet showing how to do this:

C#
var dpi = 300f;
using (var pdfWriter = new PdfWriter(@"Images\Output\out.pdf"))
{
    pdfWriter.AddPage(UnitConverter.ConvertUnitsToPixels(dpi, 3.5f, Unit.Inch),
        UnitConverter.ConvertUnitsToPixels(dpi, 2.0f, Unit.Inch), dpi, dpi);
    using (var graphics = pdfWriter.GetGraphics())
    {
        //...
    }
}

Creating Multipage PDF

Now, let us discuss how to create a multipage PDF document. The following code snippet creates a PDF business card with two pages inside. The business card contains a raster logo, primitive vector graphics, and text strings.

C#
using (var writer = new PdfWriter(@"Images\Output\out.pdf"))
{
    writer.AddPage(350, 200);

    using (var page1 = writer.GetGraphics())
    {
        page1.DrawImage(new Bitmap(@"Images\logo.png"), 22, 8);
        
        var pen = new Pen(RgbColor.Gray, 1);
        page1.DrawRectangle(pen, new System.Drawing.RectangleF(324, 84, 26, 58));
        page1.DrawLine(pen, 24, 138, 174, 138);

        var font = page1.CreateFont("Verdana", "bold", 28);
        var brush = new SolidBrush(RgbColor.Gray);
        var point = new System.Drawing.PointF(115, 15);
        var plainText = new PlainText("Company", font, brush, point);
        page1.DrawText(plainText);

        font = page1.CreateFont("Verdana", 12);
        point = new System.Drawing.PointF(14, 116);
        plainText = new PlainText("Manager", font, brush, point);
        page1.DrawText(plainText);

        var boundedText = new BoundedText("Phone: 1.123.456.7890\nEmail: john@company.com", 
            font, brush, new System.Drawing.RectangleF(32, 150, 170, 40), TextAlignment.Left);
        page1.DrawText(boundedText);

        font = page1.CreateFont("Verdana", 18);
        brush = new SolidBrush(RgbColor.Black);
        point = new System.Drawing.PointF(14, 96);
        plainText = new PlainText("John Doe", font, brush, point);
        page1.DrawText(plainText);
    }

    writer.AddPage(350, 200);
    using (var page2 = writer.GetGraphics())
    {
        var font = page2.CreateFont("Times New Roman", 16);
        var brush = new SolidBrush(RgbColor.Blue);
        var point = new System.Drawing.PointF(82, 92);
        var plainText = new PlainText("http://company.com", font, brush, point);
        page2.DrawText(plainText);
    }
}

The resulting business card will look as follows:

PDF business card

Using PdfReader

The PdfReader class allows you to load PDF files. After you read a file, you can process it as a raster or vector graphics.

Let us look at the simplest use case, when you need to rasterize a one-page PDF file.

C#
var dpi = 90f;
var quality = 90;
using (var reader = new PdfReader(@"Images\in.pdf", dpi, dpi))
using (var writer = new JpegWriter(@"Images\Output\out.jpg", quality, false, true))
{
    Pipeline.Run(reader + writer);
}

In this example, you assign the reader and writer objects to set up the source and destination files. Then, you run the Pipeline to convert an image from PDF to JPG. In this case, implicit rasterization occurs in the pipeline.

When you work with vector graphics, GraphicsContainer is used to handle vector images without rasterization. Another image format of vector graphics that Graphics Mill supports is the SVG format. To illustrate how you can work with GraphicsContainer, let us convert a PDF to an SVG file.

C#
using (var reader = new PdfReader(@"Images\in.pdf", dpi, dpi))
using (var container = reader.Frames[0].GetContent())
using (var writer = new SvgWriter(@"Images\Output\out.svg", reader.Width, reader.Height))
using (var graphics = writer.GetGraphics())
{
    graphics.DrawContainer(container, 0, 0);
}

Here, PdfFrame.GetContent() returns GraphicsContainer with vector graphics that you then pass to the Graphics.DrawContainer() method to draw it on the writer object and save into the output file in the vector form. If you only want to rasterize the source image, you do not need to call the PdfFrame.GetContent() method; use Frame.GetBitmap() instead.

See Also

Reference

Manual