begin process at 2013 05 21 21:08:02
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Fichiers / Disque

 > COMPTER LE NOMBRE DE PAGES D'UN FICHIER PDF

COMPTER LE NOMBRE DE PAGES D'UN FICHIER PDF


 Information sur la source

Note :
Aucune note
Catégorie :Fichiers / Disque Classé sous :pdf, pages, compter, pagecount Niveau :Débutant Date de création :13/02/2012 Date de mise à jour :16/02/2012 09:34:16 Vu :2 890

Auteur : Renfield

Ecrire un message privé
Site perso
Ce membre participe au partage de revenus publicitaires
Commentaire sur cette source (5)
Ajouter un commentaire et/ou une note


 Description

Ce petit code source permet de compter le nombre de pages dans un fichier PDF.
Fonctionne au moins avec les PDF jusqu'au 1.4

les spécifications 1.5 voient entrer la compression de la table XRef... du coup, pour ce simple comptage, le code se voit allongé de deux a trois fois sa taille actuelle, d'après mes premières estimations.

vu que j'ai écrit ce code rapidement, pour un cadre précis, avec des fichiers 1.4...

Source

  • #if defined(WIN32)
  • #define _CRT_SECURE_NO_WARNINGS
  • #endif
  • #include <stdio.h>
  • #include <stdlib.h>
  • #include <string.h>
  • int CountPDFPage(char *Fichier) {
  • FILE *pdf;
  • unsigned int count = 0;
  • int offset;
  • int len;
  • int i;
  • int refCount;
  • char *p;
  • char buf[1024];
  • unsigned int *XRef;
  • if ((pdf = fopen(Fichier, "rb")) == NULL) {
  • printf("Impossible d'ouvrir le fichier PDF.\n");
  • return -1;
  • }
  • fread(buf, 1, 5, pdf);
  • if (strncmp(buf, "%PDF-", 5)) {
  • printf("fichier non PDF.\n");
  • return -2;
  • }
  • fseek(pdf, 0, SEEK_END);
  • offset = ftell(pdf)-60;
  • fseek(pdf, offset, SEEK_SET);
  • len = fread(buf, 1, 60, pdf);
  • if (len!=60) {
  • printf("fichier PDF corrompu\n");
  • return -3;
  • }
  • buf[60] = 0;
  • for(;;) {
  • len = strlen(buf);
  • if (len==60)
  • break;
  • else
  • buf[len] = 32;
  • }
  • p = strstr(buf, "startxref");
  • if (p==0) {
  • printf("Erreur dans l'analyse du pdf. Impossible de trouver le StartXRef\n");
  • return -4;
  • }
  • p+=10;
  • while (*p==32 || *p==10 || *p==13) p++;
  • offset = atoi(p);
  • if (offset<=0) {
  • printf("Erreur dans l'analyse du pdf. StartXRef==%d\n", offset);
  • return -5;
  • }
  • fseek(pdf, offset, SEEK_SET);
  • /* On récupère le nombre d'entree de la XRef */
  • fread(buf, 1, 40, pdf);
  • if (strncmp(buf, "xref", 4)) {
  • printf("XRef incompatible. Peut être s'agit il d'un fichier PDF 1.5 ou superieur\n");
  • return -6;
  • }
  • p=buf+4;
  • while (*p==32 || *p==10 || *p==13) p++;
  • while (*p>='0' && *p<='9') p++;
  • while (*p==32) p++;
  • refCount = atoi(p);
  • if (refCount<=0) {
  • printf("Erreur dans l'analyse du pdf. XRef==%d\n", refCount);
  • return -7;
  • }
  • /* On va conserver la XRef en memoire. */
  • XRef = malloc(sizeof(unsigned int)*--refCount);
  • fseek(pdf, offset+32, SEEK_SET);
  • for (i=0; i<refCount;) {
  • len = fread(buf, 1, 1024, pdf);
  • for(p=buf; i<refCount && p<(buf+len); p+=20) {
  • XRef[i] = atoi(p);
  • i++;
  • }
  • }
  • /* Pour chaque object de la XRef... */
  • for (i=0; i<refCount; i++) {
  • fseek(pdf, XRef[i], SEEK_SET);
  • fread(buf, 1, 1024, pdf);
  • p = strstr(buf, "/Type ");
  • if (p) {
  • if (strncmp(p, "/Type /Pages", 12))
  • break; /* Seuls les /Pages nous interessent... */
  • p = strstr(buf, ">>");
  • if (p)
  • *p=0; /* Permet de ne pas tenir compte du 'trop-lu' du fichier */
  • /* Un fichier PDF peut contenir n groupes de pages. */
  • /* Seul l'element racine nous interesse : celui qui n'a pas de Parent */
  • if (strstr(buf, "/Parent ") == NULL) {
  • p = strstr(buf, "/Count ");
  • if (p) {
  • count = atoi(p+7); /* Voila notre nombre de pages */
  • break;
  • }
  • }
  • }
  • }
  • free(XRef);
  • fclose(pdf);
  • return count;
  • }
  • int main(int argc, char *argv[]) {
  • int rc;
  • if (argc!=2) {
  • printf("Compte le nombre de pages d'un fichier PDF dont le chemin est donne en parametre.\n");
  • return 1;
  • }
  • rc = CountPDFPage(argv[1]);
  • if (rc>0) {
  • printf("%d\n", rc);
  • return 0;
  • }
  • printf("%d\n", rc);
  • return rc;
  • }
#if defined(WIN32)
	#define _CRT_SECURE_NO_WARNINGS
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int CountPDFPage(char *Fichier) {
	FILE *pdf;
	unsigned int count = 0;
	int offset;
	int len;
	int i;
	int refCount;
	char *p;
	char buf[1024];
	unsigned int *XRef;
	if ((pdf = fopen(Fichier, "rb")) == NULL) {
		printf("Impossible d'ouvrir le fichier PDF.\n");
		return -1;
	}

	fread(buf, 1, 5, pdf);
	if (strncmp(buf, "%PDF-", 5)) {
		printf("fichier non PDF.\n");
		return -2;
	}

	fseek(pdf, 0, SEEK_END);	
	offset = ftell(pdf)-60;
	fseek(pdf, offset, SEEK_SET);
	len = fread(buf, 1, 60, pdf);
	if (len!=60) {
		printf("fichier PDF corrompu\n");
		return -3;
	}

	buf[60] = 0;
	for(;;) {
		len = strlen(buf);
		if (len==60)
			break;
		else
			buf[len] = 32;
	}

	p = strstr(buf, "startxref");
	if (p==0) {
		printf("Erreur dans l'analyse du pdf. Impossible de trouver le StartXRef\n");
		return -4;			
	}
	
	p+=10;
	while (*p==32 || *p==10 || *p==13) p++;
	offset = atoi(p);
	if (offset<=0) {
		printf("Erreur dans l'analyse du pdf. StartXRef==%d\n", offset);
		return -5;
	}
	fseek(pdf, offset, SEEK_SET);
	
	/* On récupère le nombre d'entree de la XRef */
	fread(buf, 1, 40, pdf);	

	if (strncmp(buf, "xref", 4)) {
		printf("XRef incompatible. Peut être s'agit il d'un fichier PDF 1.5 ou superieur\n");
		return -6;
	}

	p=buf+4;
	while (*p==32 || *p==10 || *p==13) p++;
	while (*p>='0' && *p<='9') p++;
	while (*p==32) p++;

	refCount = atoi(p);
	if (refCount<=0) {
		printf("Erreur dans l'analyse du pdf. XRef==%d\n", refCount);
		return -7;
	}

	/* On va conserver la XRef en memoire. */
	XRef = malloc(sizeof(unsigned int)*--refCount);
	fseek(pdf, offset+32, SEEK_SET);
	for (i=0; i<refCount;) {
		len = fread(buf, 1, 1024, pdf);
		for(p=buf; i<refCount && p<(buf+len); p+=20) {
			XRef[i] = atoi(p);
			i++;
		}
	}

	/* Pour chaque object de la XRef... */
	for (i=0; i<refCount; i++) {
		fseek(pdf, XRef[i], SEEK_SET);	
		fread(buf, 1, 1024, pdf);
		p = strstr(buf, "/Type ");
		if (p) {
			if (strncmp(p, "/Type /Pages", 12))
				break; /* Seuls les /Pages nous interessent... */
			p = strstr(buf, ">>");
			if (p) 
				*p=0; /* Permet de ne pas tenir compte du 'trop-lu' du fichier */
			/* Un fichier PDF peut contenir n groupes de pages.                    */
			/* Seul l'element racine nous interesse : celui qui n'a pas de Parent  */
			if (strstr(buf, "/Parent ") == NULL) {
				p = strstr(buf, "/Count ");
				if (p) {
					count = atoi(p+7);	/* Voila notre nombre de pages */
					break;
				}
			}
		}
	}
		
	free(XRef);

	fclose(pdf);
	return count;
}

int main(int argc, char *argv[]) {
int rc;
	if (argc!=2) {
		printf("Compte le nombre de pages d'un fichier PDF dont le chemin est donne en parametre.\n");	
		return 1;
	}          
	rc = CountPDFPage(argv[1]);
	if (rc>0) {
		printf("%d\n", rc);
		return 0;
	}            
	printf("%d\n", rc);
	return rc;
}

 Conclusion

Rien de bien sorcier, mais outil bien utile au quotidien (enfin, dans mon quotidien en tous cas)


 Historique

14 février 2012 08:42:10 :
J'ai utilisé la commande gcc -W -Wall -ansi -pedantic pdf_pagecount.c -g sur mon AIX cible, afin de voir plus de Warnings, et de les corriger. (Merci CptPingu) J'en ai profité pour ajouter un test: vérifier que le fichier commence bien par %PDF-
14 février 2012 11:20:43 :
Ajout de davantage de controles sur le Pdf
14 février 2012 11:21:38 :
Erreur de mise a jour
16 février 2012 09:34:16 :
Ajout de commentaires

 Sources du même auteur

CALCUL DE CLEF RIB
Source avec Zip HOOK DLL - LE HOOK FACILE (POUR VB6)

 Sources de la même categorie

Source avec Zip Source avec une capture GENERE BMP par lajouad
Source avec Zip Source avec une capture GETIONNAIRE D'UNE BIBLIOTHÉQUE EN C par benzarabel
FONCTION D'ÉDITION DE FICHIER BIT À BIT [C-MULTIPLATEFORME] par lynxtyle
Source avec Zip Source avec une capture UN GESTIONNAIRE DU FICHIER par benzarabel
Source avec Zip COPIE DE FICHIERS PAR RESEAU LOCAL par cczerty

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture [WIN32][CB]CRÉATION DIRECTE DE PDF par omnia
Source avec Zip Source avec une capture CREATION DE FICHIER PDF par Arnotic
Source avec Zip Source avec une capture WIN COURRIER par lann
Source avec Zip Source avec une capture PDFGEN- CREATION DE FICHIERS PDF par xtremejames183

Commentaires et avis

Commentaire de CptPingu le 13/02/2012 17:24:33 administrateur CS

C'est un outil très intéressant, et qui peut se réveler pratique !

J'ai néanmoins quelques petit soucis:

- Pourrais-tu vérifier le type mime ? Si l'on met un fichier qui n'est pas de type pdf, que se passe-t-il ?
- Chez moi, ton binaire plante (Arch Linux + gcc 4.6).
gdb --args ./a.out monpdf.pdf
Reading symbols from /tmp/a.out...done.
gdb$ r

Program received signal SIGSEGV, Segmentation fault.
0x00000000004009c7 in CountPDFPage (Fichier=0x7fffffffe358 "monpdf.pdf") at toto.c:47
47       {        XRef[i] = atoi(p);
gdb$ bt
#0  0x00000000004009c7 in CountPDFPage (Fichier=0x7fffffffe358 "monpdf.pdf") at toto.c:47
#1  0x0000000000400b7f in main (argc=2, argv=0x7fffffffdf08) at toto.c:88
gdb$ quit


- J'ai *beaucoup* de warning à la compilation.
gcc -W -Wall -ansi -pedantic toto.c -g
toto.c: In function 'CountPDFPage':
toto.c:28:9: warning: pointer targets in assignment differ in signedness [-Wpointer-sign]
toto.c:28:3: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
toto.c:32:5: warning: pointer targets in passing argument 1 of 'atoi' differ in signedness [-Wpointer-sign]
/usr/include/stdlib.h:148:12: note: expected 'const char *' but argument is of type 'unsigned char *'
toto.c:36:7: warning: pointer targets in assignment differ in signedness [-Wpointer-sign]
toto.c:39:5: warning: pointer targets in passing argument 1 of 'atoi' differ in signedness [-Wpointer-sign]
/usr/include/stdlib.h:148:12: note: expected 'const char *' but argument is of type 'unsigned char *'
toto.c:46:12: warning: pointer targets in assignment differ in signedness [-Wpointer-sign]
toto.c:46:32: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
toto.c:46:48: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
toto.c:47:7: warning: pointer targets in passing argument 1 of 'atoi' differ in signedness [-Wpointer-sign]
/usr/include/stdlib.h:148:12: note: expected 'const char *' but argument is of type 'unsigned char *'
toto.c:56:13: warning: pointer targets in assignment differ in signedness [-Wpointer-sign]
toto.c:56:7: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
toto.c:58:9: warning: pointer targets in passing argument 1 of 'strncmp' differ in signedness [-Wpointer-sign]
/usr/include/string.h:146:12: note: expected 'const char *' but argument is of type 'unsigned char *'
toto.c:60:15: warning: pointer targets in assignment differ in signedness [-Wpointer-sign]
toto.c:60:9: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
toto.c:66:17: warning: pointer targets in assignment differ in signedness [-Wpointer-sign]
toto.c:66:11: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
toto.c:68:13: warning: pointer targets in passing argument 1 of 'atoi' differ in signedness [-Wpointer-sign]
/usr/include/stdlib.h:148:12: note: expected 'const char *' but argument is of type 'unsigned char *'
toto.c:13:16: warning: variable 'len' set but not used [-Wunused-but-set-variable]
toto.c: At top level:
toto.c:80:5: warning: first argument of 'main' should be 'int' [-Wmain]

Commentaire de Renfield le 14/02/2012 08:44:17 administrateur CS

Corrigé.

Je cible aussi un systeme unix, avec cet outil, mes settings semblent etre plus laxistes que les tiens...
Je mets de coté cette -W -Wall   pratique

Je m'en sert au boulot, dans des chaines de traitement (je sais donc que j'ai des pdf en entrée)

les xref compressées que proposent les specs pdf 1.5 ne sont pas prises en compte, ca peut etre une evolution a prévoir.

quand au fait que le fichier ne soit pas un pdf, il ne se passera pas grand chose, on ne trouvera pas de startxref en fin de fichier, so...
j'ai ajouté un test supplémentaire néanmoins

Commentaire de CptPingu le 14/02/2012 10:39:58 administrateur CS

Il reste encore un tout petit peu de warnings :)

toto.c: In function 'CountPDFPage':
toto.c:48:32: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
toto.c:48:48: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] (p et buf étant de même type (char*), les cast en unsigned int, sont-ils nécessaires pour effectuer "p < buf" ?)
toto.c:11:16: warning: variable 'len' set but not used [-Wunused-but-set-variable] (ligne 47, len est remplie mais jamais utilisé, peut être p<(buf+len); plutôt que p<(buf+1024) ?)

Autre question:
- Pourquoi avoir "casté" le retour du malloc ligne 44 ? En C, ce n'est pas nécessaire (uniquement en C++).
- refCount = atoi(p)-1; => Peut être tester le atoi(p) avant de faire un -1 dans un unsigned ? (Chez moi le atoi(p) renvoie 0 et j'ai alors une valeur de refCount gigantesque, d'où mon segfault).

>> les xref compressées que proposent les specs pdf 1.5 ne sont pas prises en compte, ca peut etre une evolution a prévoir.
Y aurait-il un moyen de voir si le fichier est compressé et avertir l'utilisateur plutôt qu'un segfault ?

En tout cas merci pour les modifications, c'est le genre de petit outil dont je n'ai pas encore l'utilité, mais que je vais garder sous le coude !

Commentaire de Renfield le 14/02/2012 11:22:48 administrateur CS

Je compilais sans le moindre Warning.... :(

c'est normalement corrigé, plus bavard et plus les pdf mieux controlés.
Merci pour ces tests rapides et efficaces.

Commentaire de CptPingu le 14/02/2012 11:48:59 administrateur CS

Plus de warning et exécution impeccable :)

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Retours à la ligne [ par Gerald ] Quelqu'un pourrait-il me dire comment faire pour compter le nombre de retours à la ligne dans un fichier texte?voici mon programme Dos:unsigned int n, Comment compter le nombre d'espaces [ par xabi62 ] Je voudrais savoir comment il faut faire pour compter le nombre de mots dans une phrase, je pense qu'en comptant le nombre d'espace, on doit pouvoir l API pour visualiser des pages HTML???????? [ par Tropdemalaveclesapi ] QQN connait une api pour afficher à l'écran une page HTML? merci à tous de réfléchir à la question! Compter les lignes d un fichier texte [ par DeepThroat ] Bonjour a tous !J'aimerai trouver une fontion simple qui retourne le nombre de lignes dans un fichier , ou bien qui affiche ce nombre de lignes.j'imag fichier pdf [ par llo ] l'losalut,je recherche le glossaire sur la syntaxe interne des fichiers pdf (acrobat).1 - objectif : générer par codes des pages non modifiables2 - ob COMPTER LE NOMBRES D'IMPRESSIONS [ par bilal ] VGTABONJOUR G cherché et essayé et toujour pas trouvé ou je dois attaquer pour faire mon petit soft.enfait je voudrai juste compter le nombre d'impres COMPTER le nbr d impression [ par bilal ] VGTAVGTABONJOUR G cherché et essayé et toujour pas trouvé ou je dois attaquer pour faire mon petit soft.enfait je voudrai juste compter le nombre d'im compter et extraire des mots : I NEED HELP !!!!! [ par ben01n ] salut j'ai une variable "buf" qui contient une phrase saisie par l'utilisateurje voudrais compter le nombre de mots puis les extraires un par un pour generer du pdf ou rtf en C++ -=help=- [ par cartouh ] voila, je suis en train de faire une appli qui travaille des images grace à la lib FreeImage (mici BruNews).une fois que j'ai ces images, je voudrais nombre de pages imprimés [ par revelata ] Salut,je dois compter les pages imprimés par utilisateur sur une imprimante! J'utilise IADS ou winspool.hµ? Si vous avez des exemples, merci...


Nos sponsors


Sondage...

CalendriCode

Mai 2013
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Photothèque

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 2,668 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales