Search code examples
c#pdfimage-resizingabcpdf

Resize page with ABCPdf before rendering (huge images in the pdf)


I have a problem with ABCPdf, when I try to convert a pdf files into seperate image files as fallbacks for old browsers.

I have some working code that perfectly renders the page and resizes the rendering into the wanted size. Now my problem occurs when the pdf page is huge w7681px x h10978px. It nearly kills my development machine and the deployment machine cannot even chew the file.

I normally just render the page 1-to-1 as the pdf page and then uses other algorithms to resize this image. This is not efficient since ABCPdf takes alot of power to output this image.

I have the following code:

    private byte[] GeneratePng(Doc pdfDoc, int dpi)
    {
        var useDpi = dpi;
        pdfDoc.Rendering.DotsPerInch = useDpi;
        pdfDoc.Rendering.SaveQuality = 100;
        pdfDoc.Rect.String = pdfDoc.CropBox.String;
        pdfDoc.Rendering.ResizeImages = true;

        int attemptCount = 0;

        for (;;)
        {
            try
            {
                return pdfDoc.Rendering.GetData("defineFileTypeDummyString.png");
            }
            catch
            {
                if (++attemptCount == 3) throw;
            }
        }
    }

I have tried the following solutions:

Resizing the page

pdfDoc.SetInfo(pdfDoc.Page, "/MediaBox:Rect", "0 0 200 300");

Resizing the page and outputting it. Which doesn't seem to make any changes at all.

Resizing the images before rendering it:

foreach (IndirectObject io in pdfDoc.ObjectSoup) {
  if (io is PixMap) {
    PixMap pm = (PixMap)io;
    pm.Realize(); // eliminate indexed color images
    pm.Resize(pm.Width / 4, pm.Height / 4);
  }
}

Didn't do anything either and still resulted in a long load time.

Running the reduzed size operation before rendering:

  using (ReduceSizeOperation op = new ReduceSizeOperation(pdfDoc))
    op.Compact(true);

Didn't do anything either. Just went directly to rendering and took a long time.

Can anyone help me here? Maybe point me to some ABCPdf resizing algorithm or something.


Solution

  • Ok so I talked to the customer support at ABCPdf and they gave me the following.

    doc1.Read(originalPDF);
    
    // Specify size of output page.  (This example scales the page, maintaining the aspect ratio,
    // but you could set the MediaBox Height and Width to any desired value.)
    doc2.MediaBox.Height = doc1.MediaBox.Height / 8;
    doc2.MediaBox.Width = doc1.MediaBox.Width / 8;
    doc2.Rect.SetRect(doc2.MediaBox);
    doc2.Page = doc2.AddPage();
    
    // Create the output image
    doc2.AddImageDoc(doc1, 1, null);
    doc2.Rendering.Save(savePath);
    

    Which is supposed to be used with single page PDFs, so if you have a pdf full of large pictures, then you should chop it up. Which you can do following my other Q/A: Chop PDFs into single pages

    The rendering algorithm they use in the above code is auto detected by ABCPdf and you cannot control it yourself (and they told me that I didn't want to). So I put my faith in their code. At least I did a test and the quality looks quite similar to a InterpolationMode.HighQualityBicubic and only differed when zoomed. So I wouldn't be too concerned with it either.

    At last the above code gave me a speed boost compared to rendering and then resizing of about 10x faster. So it is really worth something if you do this operation a lot.