Render multiple pages to a single bitmap

In this article, we will render multple pages to a single bitmap. The pages will be rendered as a horizontal strip. A margin of 5 pixels will be added around the edges of each page. Each page will be vertically aligned at the center. A black rectangle is drawn around each page.

Open the PDF document

The first step is to open a PDF document and retrieve the first page. Let's use the OpenFileDialog class to select a PDF document from disk.


// prompt the user to select a PDF document
OpenFileDialog openDialog = new OpenFileDialog();
openDialog.Filter = "PDF documents (*.pdf)|*.pdf";
if (DialogResult.OK == openDialog.ShowDialog())
{
  // open the selected PDF document
  string path = openDialog.FileName;
  using (FileStream pdfFile = new FileStream(
    path, FileMode.Open, FileAccess.Read))
  {
    Document pdfDocument = new Document(pdfFile);
 
    // more code follows
  }
}
 1 // prompt the user to select a PDF document
 2 OpenFileDialog openDialog = new OpenFileDialog();
 3 openDialog.Filter = "PDF documents (*.pdf)|*.pdf";
 4 if (DialogResult.OK == openDialog.ShowDialog())
 5 {
 6   // open the selected PDF document
 7   string path = openDialog.FileName;
 8   using (FileStream pdfFile = new FileStream(
 9     path, FileMode.Open, FileAccess.Read))
10   {
11     Document pdfDocument = new Document(pdfFile);
12  
13     // more code follows
14   }
15 }

Determine the width and height of the bitmap

Next we calculate the size of the bitmap to which we would like to render. The width is calculated by adding all page widths including left and right margins. The height is calculated as the maximum height of all pages including top and bottom margins. Note that we use 'scale' to calculate the width and height of the page in pixels. Scale follows from the resolution. If the resolution would be 72 dpi, then the scale would equal 1. This means that 1 point (1/72 inch) corresponds to 1 pixel.


float resolution = 18;
float scale = resolution / 72f;
 
// determine width and height - we create a horizontal strip...
int MARGIN = 5;
int totalWidth = 0;
int totalHeight = 0;
for (int i = 0; i < pdfDocument.Pages.Count; i++)
{
  Page pdfPage = pdfDocument.Pages[i];
  totalWidth += (int)(scale * pdfPage.Width + 2 * MARGIN);
  totalHeight = Math.Max(
    totalHeight, (int)(scale * pdfPage.Height) + 2 * MARGIN);
}
 1 float resolution = 18;
 2 float scale = resolution / 72f;
 3  
 4 // determine width and height - we create a horizontal strip...
 5 int MARGIN = 5;
 6 int totalWidth = 0;
 7 int totalHeight = 0;
 8 for (int i = 0; i < pdfDocument.Pages.Count; i++)
 9 {
10   Page pdfPage = pdfDocument.Pages[i];
11   totalWidth += (int)(scale * pdfPage.Width + 2 * MARGIN);
12   totalHeight = Math.Max(
13     totalHeight, (int)(scale * pdfPage.Height) + 2 * MARGIN);
14 }

Create the bitmap and render the pages

Now that we have calculated the size of the bitmap, we render the pages one by one using the following code:


using (Bitmap bitmap = new Bitmap(totalWidth, totalHeight))
using (Graphics graphics = Graphics.FromImage(bitmap))
using (Pen pen = new Pen(Color.Black))
{
  // we maintain a horizontal cursor to position the next page
  int x = 0;
 
  // draw each page
  for (int i = 0; i < pdfDocument.Pages.Count; i++)
  {
    GraphicsState state = graphics.Save();
 
    // get the next page
    Page pdfPage = pdfDocument.Pages[i];
 
    // draw the page at the given resolution and position
    graphics.TranslateTransform(
      (float) (x + MARGIN), 
      (float) (totalHeight - scale * pdfPage.Height) / 2);
    graphics.ScaleTransform(scale, scale);
    pdfPage.Draw(graphics);
       
    // draw a black rectangle around the page
    graphics.DrawRectangle(
      pen, 0, 0, (int)pdfPage.Width, (int)pdfPage.Height);
 
    // update the horizontal cursor 
    x += (int)(scale * pdfPage.Width);
    x += 2 * MARGIN;
 
    graphics.Restore(state);
  }
 
  // prompt the user to save the bitmap
  SaveFileDialog saveDialog = new SaveFileDialog();
  saveDialog.Filter = "PNG files (*.png)|*.png";
  if (DialogResult.OK == saveDialog.ShowDialog())
  {
    bitmap.Save(saveDialog.FileName);
  }
}
 1 using (Bitmap bitmap = new Bitmap(totalWidth, totalHeight))
 2 using (Graphics graphics = Graphics.FromImage(bitmap))
 3 using (Pen pen = new Pen(Color.Black))
 4 {
 5   // we maintain a horizontal cursor to position the next page
 6   int x = 0;
 7  
 8   // draw each page
 9   for (int i = 0; i < pdfDocument.Pages.Count; i++)
10   {
11     GraphicsState state = graphics.Save();
12  
13     // get the next page
14     Page pdfPage = pdfDocument.Pages[i];
15  
16     // draw the page at the given resolution and position
17     graphics.TranslateTransform(
18       (float) (x + MARGIN), 
19       (float) (totalHeight - scale * pdfPage.Height) / 2);
20     graphics.ScaleTransform(scale, scale);
21     pdfPage.Draw(graphics);
22        
23     // draw a black rectangle around the page
24     graphics.DrawRectangle(
25       pen, 0, 0, (int)pdfPage.Width, (int)pdfPage.Height);
26  
27     // update the horizontal cursor 
28     x += (int)(scale * pdfPage.Width);
29     x += 2 * MARGIN;
30  
31     graphics.Restore(state);
32   }
33  
34   // prompt the user to save the bitmap
35   SaveFileDialog saveDialog = new SaveFileDialog();
36   saveDialog.Filter = "PNG files (*.png)|*.png";
37   if (DialogResult.OK == saveDialog.ShowDialog())
38   {
39     bitmap.Save(saveDialog.FileName);
40   }
41 }