PDF (Portable Document Format) is a widely used open electronic document format which can be easily used in all your cross platform apps. It is really convenient thanks to its compatibility with numerous programs. As a result, it is possible to view PDF documents using different software. And regardless of the device used, the page configuration remains the same. That’s why PDF is often chosen for creating different reports, including the cases when programs written in Delphi are used. For working with this format with the Delphi tools, there are various components, including free and commercial ones. As the format is rather flexible and has a lot of capacities, components for working with it are rather complex and quite often they add excessive information to created files. But in some cases, it is possible to use a minimum set of functionalities for creating PDF files. Though a detailed description of the PDF file structure can take several hundreds of pages, we will focus on key points.
Table of Contents
What is in the internals of a PDF File?
A PDF file consists of objects of different types connected with each other. The set of object types is limited. Each object has its unique number that allows objects to refer to each other (it is called indirect links). There are also direct links to objects – shifts in bytes from the beginning of a file. At the end of the file, there are usually a table of direct links to objects, a link to the beginning of this table, information about a number of objects and an indirect link to the first object. When you are viewing a document, it is being read from the end. Objects of parameters’ names and values are separated from each other with spaces and a #10 (“new line”) character. For positioning graphical objects on the page, a two-dimensional coordinate system with the beginning in the lower-left page corner is used. Relative points that equal 1/72 inches are used. The dimensions of the page are indicated in these units. The simplest file can have at least one page and its content will look the following way:
A table with direct links can be absent and the majority of programs will be able to read a file without it. The order of objects in the table should correspond to the object numeration but the objects themselves can be placed in the file with no particular order. It is convenient when you are creating a file but do not know the number of pages in advance – a parent object Pages with a page list can be placed at the end of the file. But you need to book a number for it.
Let’s have a look at what we need to have for creating the simplest PDF document with an unknown number of pages. Some invariant lines can be taken as a sample from a finished file and manage only direct and indirect links. It is convenient to use TStream for creating a document body as, for example, images have means for recording data into a stream. TList is suitable for counters of direct links. A minimum set of announced variables can look the following way:
The Pages object with the list of pages will be placed at the end of the file. And we need to take it into account when we are adding indirect links for new objects. For our convenience, let’s announce a constant and we will add it to the counter.
How to create the PDF file header using Delphi?
Here’s an example of creating a beginning of a document:
How to add an empty page with the set dimentions:
How to correctly close the PDF file contents?
And we can end the document the following way:
A document with empty pages has little sense. That’s why let’s have a look at how we can add images to the pages. If a page has some content, we should add the keyword “Contents” into its description as well as links to the contents. When you are inserting an image, it is necessary to add the keyword “XObject “ and indicate links to the image data. Each image should get its conditional inner name.
Is there an example of a PDF file created in Delphi with images?
Example of a page object with three images:
Example of graphics image output on the page (object coordinates are indicated for a lower left corner)
For describing graphics output, operators q, Q, cm are used. Their detailed description can be found in the documentation of the PDF format.
The same object can be output on different pages in different places and in different sizes. For example, if you need to place a logo on all pages, it is enough just to add to the file one copy of an image and to indicate the same indirect link in the /XObject section and the relevant names of images in the description of graphics output for each page.
Data (“bodies”) of JPEG images are stored in a document practically just in the same way as if they were saved as a separate file. That’s why it is convenient to work with them. The description is placed before image data, for example:
Parameters /Width and /Height are image dimensions in pixels, /Length points to the objects where the size of image data will be saved (the length of the block in bytes). The length can be indicated directly if you know it before recording image data into the stream. Image data should be placed between the keywords “stream” and “endstream”.
How to set the correct data types for an image in the PDF document
For creating a PDF document with images, we need to announce a data type:
In addition to what we’ve already had, we need to announce new variables (consequently, we will need to create TList objects before their use and a variable ImageCount should be initialized):
The procedure of adding a page to the document should be upgraded as we need to take into account the number of images:
After creating pages, we need to create a list of image positions and then to add the description of graphics output into the PDF stream.
Adding image data to the PDF file stream
After this preparation, we can add the image data to the stream. Let’s have a look at the way to record a JPEG image (or an image of any other format converted into JPEG) during the VCL app development (below you can see a fragment of procedure code):
With this method, it is possible to add contents of a standard component TImage into PDF documents, using TImage.Picture.Graphic as an input parameter. JPEG images can be recorded in the stream without additional transformations by copying data from the image file.
How to save a PDF image to a stream?
During the development of an FMX app, it is more convenient to use FMX.Graphics.TBitmap as a procedure parameter. Have a look at the following procedure code fragment:
Quite often there can be a necessity to create a PDF document from images (for example, from those that you get after scanning a paper document). The examples that we’ve considered above will be enough for solving this task. The algorithm of actions is the following one:
- To create a list of images.
- To calculate the necessary sizes of the pages based on the required resolution by sequentially loading images into the VCL.Graphics TGraphics or FMX.Graphics.TBitmap object. If an image occupies the whole page, it can be calculated the following way:
- To add a page with a calculated size.
- To add an image to the page with 0,0 coordinates and the sizes that are equal to those of the page.
- After adding all objects, to save the file.
Example of a procedure for creating a page from an image (using a previously written code):
So, in this article, we’ve considered the simplest way to create a PDF document with images. It’s worth noting that for using this method in real projects, it will be more comfortable to use not just separate procedures and variables but a class with a correspondent set of fields and methods.
Further reading on PDF file creation in RAD Studio with Delphi
You can read more about creating and using PDF files in your Delphi and C++ programs in the following articles.
- Gnostice – Programming with PDF and Office Documents – Delphi and C++Builder
- Creating PDF Reports in RAD Server
- Use the PdfBox-Android Library in Your Delphi/C++ Builder FireMonkey Applications
- Quick And Easy Way To Create And Manage PDF Documents Programmatically
This article was written by Embarcadero Tech Partner Softacom. Softacom specialize in all sorts of software development focused on Delphi. Read more about their services on the Softacom website.