Magick++ API: Get PDF page count? - c++

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?

If you're using ImageMagick-7, use the STL method.
std::list<Magick::Image> master;
Magick::pingImages(&master, "a-66-page-pdf.pdf");
std::cout << master.size() << std::endl;
The pingImages method is not available with ImageMagick-6, so you'll need to read all the images.
Magick::ReadOptions opts;
// Set dpi & depth, if needed
// opts.depth(8);
// opts.density(72);
std::list<Magick::Image> master;
Magick::readImages(&master, "a-66-page-pdf.pdf", opts);
std::cout << master.size() << std::endl;

You can try to initialize a counter and create that string with counter as the index. As long as you increment the counter in a while loop with your code inside a try-catch block, when the above exception is thown, your counter would indicate the number of pages.

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.

Related

Ubuntu Terminal C++ program being called in other program stuck, even though they separately work fine

Long story short:
I created a program to get the path to a model file, do something with that information and pass on a different set of information, then i tried to create a wrapper for another program that basically catches the command line arguments and funnels some of them to my program to do its thing.
Simplified program flow.
Software --> args[all] --> Wrapper --> args[some] --> Program --> Output
The problem i now have is, calling my program on its own with hard-coded information or command line arguments equal to what the Wrapper would pass on works both flawlessly. The same goes for the Wrapper it works independently.
It also works to have the Wrapper pass on arguments and call the Program if the model information is wrong, which results in a simple string warning. But if the path to the model is correct it gets stuck in an endless loop and i don't know why. Separate runtimes are 8-11s for the Program and maybe 2s for the Wrapper, but i let it run for about 10min and nothing happened after some dummy print code.
Wrapper:
int main(int argc, char* argv[]){
if(argc > 1){
string tmp0 = argv[1];
string tmp1 = "./program " + tmp0;
const char* model = tmp1.c_str();
int status = system(model);
}
else{
cout << "No Model Information.\n";
}
return 0;
}
Parameters would be: Path to a model file and some other stuff, but only the path to the model would be passed on to the program in this case.
Program:
#include "program.hpp"
int main(int argc, char* argv[]){
if(argc > 1){
string tmp = argv[1];
const char* model = tmp.c_str();
cout << program(model);
}
else{
cout << "At least one defined Argument for the Model needs to be given.\n";
}
return 0;
}
Program Function Pseudo Code:
#include <stdio.h>
string program(const char* model){
string tmp
read(model);
if(model has variables) do
tmp = "has variables";
return tmp
}
--- Edit ---
The program function code is in pseudo code because its too complex and specific to list here without a load of libraries and other stuff being listed. If thats necessary i can try to provide it, but as it is i dont have a small or simple example i can give.
--- End edit ---
I don't understand enough about command line arguments to write sophisticated code, so i know this is more or less shitty, but i only need to be able to execute the program from the wrapper somehow and need to be able to read and pass on specific command line arguments. This is just the best i came up with.
Executing the Program code alone, with correct model information: ~10s execution time
Executing the Program code alone, with wrong model information: ~2s execution time
Executing the Wrapper code alone: ~2s execution time
Executing the Wrapper code, calling the Program code with wrong model information: ~2s execution time
Executing the Wrapper code, calling the Program code with correct model information: endless wait
I just dont get why it doesnt progress even though each works separately.
You can use fork() and execvp() in the unistd.h API. Depending on the return of fork() you can have the wrapper wait or end after launching the command.
Save the source file as args.cpp and compile it with the following command:
$ g++ args.cpp -o args && ./args -l -h -a
#include <cstdio>
#include <unistd.h>
#define SPAWNCMD "ls"
int main(int argc, char* argv[])
{
if(argc > 1)
{
printf("Command to spawn: %s ", SPAWNCMD);
for (unsigned i = 1; i < argc; i++)
printf("%s ", argv[i]);
printf("\n");
if (fork())
if (execvp(SPAWNCMD, argv) == -1)
{
printf("Incorrect termination of SPAWNCMD\n");
return 1;
}
}
else
{
printf("No Model Information.\n");
}
printf("Wrapper program end\n");
return 0;
}

How to read a certain range of lines using systems calls

I am up a wall on an assignment that I have been hacking at for several days. Basically I need to make an executable program using C/C++ to take 3 queries from the user m,n and a file name.
The program will then output the text on those lines to the terminal. I must use read(), write(), open() and close() system calls to do it.
My approach is to go char by char (slow I know but everything else I tried seems to give segementation faults).
But it doesn't seem to work properly. When I use smaller parameters it just prints the whole thing, but if I use bigger parameters it doesn't print anything at all.
Can anyone tell me where I'm going wrong?
// Task 2 of Lab 3
#include<unistd.h> // required library for the system calls
#include<fcntl.h> // required for system calls usage
#include <stdlib.h> // required for the use of exit statement, and atoi
#include<stdio.h> // required for the use of perror
#include<string>
using namespace std;
int main(int argc,char *argv[]){
int m = atoi(argv[1]);
int n = atoi(argv[2]); // taking commmand line args by conversion with atoi
int file; // integer value for holding the file descriptor
ssize_t display;
char *buff[1];
int currentLine = 0;
// open the first file for reading
file = open(argv[3],O_RDONLY);
if(file == -1 ){ // error handler for system call 1: open()
perror("Did not open, exiting...");
exit (1);
}
while(((display = read(file,buff,1)) > 0)){
if(*buff[0] == '\n'){
currentLine++;
}
if((currentLine >= m) && (currentLine <= n)){
if(write(STDOUT_FILENO, buff,display) != display){ // if statement doubles as error handling for read()
perror("Problem with writing..."); // errror handling for write()
exit(-1);
}
}
else{
}
}
file = close(file); // Final system call close()
return 0;
}
Sample testfile:
I have some information in here.
Each line should print to the screen
3 lines total
make that 4
Wait? WHAT! I need 12 minimum???
Hm....
Wellp better start typing then. Let's see what can I write about?
Midterms are coming
They scare me
I hate exams, but I love code
woah i also need numbers in here uh 23
19 and lets do 100 and 400 just to add a couple more
maybe i should go ahead and add a 903 here
300
and that previous 300 got it's own line
with this file ...
I have a good mix of chars,numbers, and symbols
that's good enough
time to test!

fprintf() / std::cout doesn't print part of the string to stdout/stderr

I have this strange problem with stdout/stderr.
I want to apologize for not being able to put here the original code, it's too long / too many libraries dependent etc...
So please let me know if you ever encountered anything like it, or what may cause this issue without getting the original code, only the idea and examples of the simple things I tried to do:
I'm using g++ (GCC) 4.4.6 20120305 (Red Hat 4.4.6-4) on RHEL 6.3
I couldn't isolate the problem for putting it here, I'll give code examples of what I did.
fprintf() / printf() / std::cout stops working after a while.
I'm using boost::asio::io_service with deadline_timer in order to call a my_print() function.
This my_print() function prints to screen every 1 second some information.
In order to print, I use alignments, like the following:
fprintf(stdout, "%*s\n", -printWidth, someEnumToStr[i]);
fprintf(stdout, "%s\n", aString);
fprintf(stdout, "%u\n", num);
While aString is a std::string. Sometimes I construct aString from std::ostringstream.
Sometimes I construct it with snprintf().
I have an std::map with information, exactly 16 elements inside the map. I iterate over it, and for each element I try to print data with the example of fprintf() above.
For an unknown reason, the line of element 16 isn't printed.
If I call the executable, and redirect stdout to a file (./a.out > aaa.txt) the line of element 16 is getting printed.
If I open a new FILE* and fprintf() to this file, again, everything is getting printed (all lines, including line of element 16)
Before using fprintf() I tried to use std::cout (and alignments with std::cout.width(printWidth) << std::left...), The same behavior happened, but when line 16 wasn't drawn, stdout got stuck (I mean, the program still worked, but nothing was printed to stdout never again. I had to call std::cout.clear() for it to work again). Since a point in the code, which I couldn't lay my hands on, std::cout.failbit and badbit were 1.
If I run the code with valgrind this behavior doesn't happen. valgrind doesn't say anything wrong.
If I run it with gdb it happens, but gdb doesn't say anything wrong.
If I run it in an IDE (clion) in debug mode, it doesn't happen.
If I run it in IDE, without debug, it happens.
I figure it depends on the printWidth I give for the alignment in fprintf() - When printWidth is bigger, it happens sooner (when it's smaller, line 16 is randomly getting printed).
Another important thing: it happens more frequently when there is more to print.
I tried to give std::cout a bigger buffer (not his default) and it didn't work.
I tried to buffer all of the output into a buffer (instead of printing each line), then to only fprintf() once. Same behavior happens.
I didn't find anywhere in the code I try to print a NULL pointer.
I print with \n every couple of fprintf()s, and do fflush() in the end of my_print()
Please let me know if you know anything.
Illustration:
deadline_timer..... every 1 sec... my_print()
boost::asio::io_service.run
my_print() {
for(std::map<>::iterator... begin, end, ++it....) {
fprintf()s....
}
}
Non printable characters may be breaking terminal.
fprintf(stdout,"%s", astdstring.cstr() );
Is how to print std::string
I use boost::asio, I have a callback to read from stdin. this read is nonblocking - happens with async_read_some().
The problem was stdin was turned to be nonblocking, and it also caused stdout to be nonblocking as well because they point to the same file description (explanation).
It caused the fprintf() calls to fail (returned -1 with errno 11) and not all of the output got printed out on the screen.
It has no relation to boost.
I succeeded isolating the problem, the following code creates this problem:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
using namespace std;
int main(int argc, char *argv[]) {
const int problem = 8000;
const int myBuffSize = 32000;
char *myBuff = new char[myBuffSize];
int myoffset = 0;
memset(myBuff, '-', myBuffSize);
int flags;
bool toogle = true;
bool running = true;
// Comment from here
if ((flags = fcntl(STDIN_FILENO, F_GETFL, 0)) < 0) {
printf("error fcntl()\n");
return 0;
}
if (fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK) < 0) {
printf("error fcntl()\n");
return 0;
}
// Comment until here
while(running) {
toogle = toogle ? false : true;
if (toogle) {
snprintf(myBuff + problem, myBuffSize - problem, "fin\n\n");
} else {
snprintf(myBuff + problem, myBuffSize - problem, "end\n\n");
}
fprintf(stdout, "%s", myBuff);
sleep(1);
}
delete[] myBuff;
return 0;
}
If you'll comment the // Comment from here to // Comment untill here, it will print all of the output (fin and end will be printed).
One solution to this problem is to open another fd to the current tty using fopen(ttyname(STDOUT_FILENO), "w") and to print into it.
I believe another solution is to async_write() into screen.
The output might be stuck in a buffer, and not flushed before program termination.
Try adding exit(0) at the end of the program, and see if it helps.
http://www.cplusplus.com/reference/cstdlib/exit/
All C streams (open with functions in <cstdio>) are closed (and flushed, if buffered), and all files created with tmpfile are removed.

In Embedded Octave C++ how do I execute a script file? ("error: invalid call to script")

I am writing a c++ oct-file that I would like to use as a link between my c++ code and scripts that were written in Octave. I can build and execute with no problems, and as long as I am doing simple things, it seems to work. I can even call functions in a script file with feval()! I just can't seem to figure out how to execute an entire script file..
If I try this simple program, I get an error, but I'm not sure why
#include <octave/oct.h>
#include <octave/octave.h>
#include <octave/parse.h>
#include <octave/toplev.h> // for do_octave_atexit
#include <iostream>
#include <string>
using namespace std;
void runscript(const string &file) {
cout << "attempting to run: " << file << endl;
int parse_status = 0;
eval_string(file, false, parse_status);
cout << "parse_status: " << parse_status << endl;
eval_string(file, false, parse_status, 0); // I'm not sure what the difference here is or
// what the value 0 means, I can't find any documentation on
// what `hargout` is.. See Note {1} below
cout << "parse_status: " << parse_status << endl;
}
int main(int argc, char **argv) {
// Set-up
char *oct_argv[3] = {(char*)"embedded", (char*)"-q", (char*)"--interactive"};
octave_main(3, oct_argv, true);
// Attempt to run script
runscript("Script1");
runscript("Script1.m");
// `a` should be defined after running Script1.m..
octave_value_list a = get_top_level_value("a", false);
do_octave_atexit ();
return 0;
}
Script1.m is very simple and looks like this:
a = 1000;
a
When I run, I always get this output:
attempting to run: Script1
error: invalid call to script /Users/Daly/Documents/School/EECS/Labs/GitHub/deep/Octave/ Script1.m
parse_status: 0
parse_status: 0
attempting to run: Script1.m
parse_status: 0
parse_status: 0
error: get_top_level_value: undefined symbol 'a'
It only ever complains about the invalid call the first time, no matter how many times I try to eval_string or in what order.
Notes: {1} After searching for error: invalid call to script, I found this source code which at line 00155 raises this exact error if nargout isn't 0, so I thought they might be related?
But anyway, maybe this isn't the right way to be going about it. What is the correct way to execute an entire octave script from an octave-embedded c++ program? Thanks!
You should be using the function source_file() rather than eval_string(). Take a look into the parser.h file which unfortunately doesn't have a lot of comments. The names are quite self-explanatory so you shouldn't have a lot of problems.
Also, you're pretty much trying to reimplement Octave's source function. If you really want to implement it again, look into the oct-parse.cc file (generated during the build process with flex and bison).

C++ program to print counting numbers

In case the title is not precisely revealing what I want to do, the following is my problem.
I want to write a c++ program in a Linux or Mac terminal to print numbers that keeps counting from 1, 2, 3 ... at the same position under a command line mode. For example, it is like displaying the number of percentage when your work is progressing(e.g. downloading something, installing software...).
I wrote a simple for-loop to print numbers and use usleep(1000); for a delay of 1 second before printing next number. Then I use cout << "\b"; trying to move cursor back to display coming number at the same position. However I fail to create the effect that I want, the numbers are printed in a line.
I am not a skillful c++ programmer and know very limited on programming in a terminal environment. Can anyone help to give me hint or sample code for this function? Thanks!!
If you are in Linux Terminal you can also use the following code,
system("clear");
cout<<"\b";
cout<<Your_Number;
// Repeat this in a loop and call the delay function
This works in terminal for me (am using linux)
#include
#include
using namespace std;
int main(int argc, char *argv[]) {
int i;
for(i=1;i<100;i++)
{
cout<<"\b\b\b"<<i;
cout.flush();
sleep(1);
}
return 0;
}