c++pdfimagemagickmagick++

Magick++ API: Get PDF page count?


I'm struggling to write a function to get the number of pages from a PDF without using external/additional (ie, other-than-Magick++) libraries for this purpose -- yet, when I execute something like this:

#include <Magick++.h> 
using namespace Magick; 
int main(int argc,char **argv) 
{ 
    InitializeMagick(*argv);

    Image master; 
    master.ping("a-66-page-pdf.pdf[999999]");

    return 0;
} 

(Where [999999] refers to the page requested)

It dumps an error like this:

Requested FirstPage is greater than the number of pages in the file: 66
   No pages will be processed (FirstPage > LastPage).
terminate called after throwing an instance of 'Magick::ErrorDelegate'
  what():  Magick: Postscript delegate failed (a-66-page-pdf.pdf) reported by coders/pdf.c:434 (ReadPDFImage)
Magick: abort due to signal 6 (SIGABRT) "Abort"...
Aborted (core dumped)

ie, It knows that the pdf has 66 pages -- yet I can't figure out how to get that information from it except by making it crash like this?

Is there a way?


Solution

  • The best I can come up with, if anyone's facing the same problem working with ImageMagick/GraphicsMagick, without including an entire extra library for this one function (PoDoFo, which is unstable, can do this, and poppler can also do it) is to use this based on the code written in the question:

    #include <Magick++.h> 
    #include <cstring>
    
    using namespace Magick; 
    int main(int argc,char **argv) 
    {
        if (argc < 2) {
            return 1;
        }
        InitializeMagick(*argv);
        
        try {
    
            Image master;
        
            char cmd[4096] = {""};
            strcat(cmd, argv[1]);
            strcat(cmd, "[99999999999]");
            master.ping(cmd);
        
        } catch( Exception &error_ )
        {
            // do nothing
            
        }
        return 0;
    } 
    

    And call it like this:

    ./compiled-program any-given-pdf.pdf 2>/dev/null | grep file: | awk {'print $13'}
    

    Maybe with popen() etc. Maybe you could redirect stdout to a string, I haven't tried yet.

    It's janky, it feels like a hack, but it's a hell of a lot faster (I mean almost infinitely faster) than trying to load a list/vector/array with ping() or readImages() and count the size of the list.

    It's endlessly frustrating that Magick++ offers no accessible method to retrieve a PDF's page count, and yet evidently not only is capable of getting a page count, but does so every time an image is pinged.

    If you're alright with including an entire library for just one function, poppler and PoDoFo can do this.

    Obviously this will fail on a 100-billion page PDF.