web-dev-qa-db-fra.com

Redimensionner un PDF en utilisant Ghostscript

J'essaie de mettre à l'échelle un PDF qui est par exemple juste petit de format A4 jusqu'à A4.

Cela fonctionne très bien avec les documents portrait. Le document est correctement mis à l'échelle, puis un remplissage est ajouté en haut.

Sur les documents paysage, le remplissage n'est pas ajouté. Par conséquent, le document finira par être la bonne hauteur pour A4 mais pas assez large, car le rembourrage n'est pas ajouté du côté du document (comme je l'espérais).

Voici ce que j'utilise pour le faire fonctionner pour les documents A4 portrait:

gs \
 -sOutputFile=output.pdf \
 -sDEVICE=pdfwrite \
 -sPAPERSIZE=a4 \
 -dCompatibilityLevel=1.4 \
 -dNOPAUSE \
 -dBATCH \
 -dPDFFitPage \
  input.pdf
37
Matt

Vous devez ajouter le -dFIXEDMEDIA commutateur:

gs \
 -o output.pdf \
 -sDEVICE=pdfwrite \
 -sPAPERSIZE=a4 \
 -dFIXEDMEDIA \
 -dPDFFitPage \
 -dCompatibilityLevel=1.4 \
  input.pdf

-dFIXEDMEDIA est toujours requis si vous devez forcer un format de papier/page/support spécifique et ignorer le format de papier/page/support spécifié dans le document. Parce que PDF a toujours une taille de papier/page/support définie (PostScript peut avoir ou non ...).

(Ma -o ... est plus court et vous évite d'ajouter -dBATCH -dNOPAUSE - mais ne fonctionne que pour les versions plus récentes de Ghostscript.)

52
Kurt Pfeifle

Tout d'abord, merci à tous ceux qui ont posté ici.

J'ai ce petit script appelé pdfScale qui a absorbé une partie des réponses publiées ici. J'ai donc décidé de remettre mes 2 cents. J'utilise un peu un mélange des réponses de Kurt et Tim. Plus semblable à Tim cependant. J'ai joué avec cela pendant quelques jours et voici ma conclusion partielle sur les méthodes affichées ici:

Définissez la taille du papier par son nom avec -sPAPERSIZE

  • Facile à simplement passer le nom du papier (ex. A4)
  • Peut ne pas produire une taille de points précise à 100%
  • Peut inverser le paysage <> Portrait

Définissez la taille du papier en points PS -dDEVICEWIDTHPOINTS, -dDEVICEHEIGHTPOINTS

  • S'assure que vous obtenez la taille souhaitée en points
  • Vous pouvez inverser la LARGEUR <> HAUTEUR vous-même
  • Vous devez connaître les tailles en points
  • Pas si facile à écrire autour de lui, car vous aurez besoin de la nouvelle taille de page en points et aurez également besoin des tailles de page de la source si vous voulez détecter le paysage/portrait.
  • Vous pouvez également définir des papiers personnalisés (n'importe quelle taille que vous voulez vraiment).
  • J'utilisais -dDEVICEWIDTH, -dDEVICEHEIGHT Au lieu de la version plus longue en points, mais ils semblent tous les deux faire la même chose (les deux obtiennent des points).

Étant donné que mon script bash est déjà capable d'obtenir des tailles de page source et que j'aimais l'idée de pouvoir définir des tailles de page personnalisées, j'ai décidé de me concentrer sur la définition de la taille de la page en points. J'avais également déjà inclus le GS Paper Sizes dans mon script (avec les noms et les tailles). Il était donc aussi facile d'obtenir ces informations.

L'utilisation de -dFIXEDMEDIA Semble être un must dans les deux cas, comme indiqué précédemment.

Voici donc comment s'est déroulée mon approche (de manière scriptée)

  1. Obtenir les tailles de page source PDF (pour la détection de retournement)
  2. Obtenez la taille de page de la cible en points (par exemple A4> 595x842)
  3. Vérifiez qu'ils ont la même orientation ou inversez la cible si nécessaire
  4. Exécutez GS avec des points ou des points inversés

Quand j'essayais de résoudre le problème de rotation automatique, j'ai trouvé cette autre réponse de Kurt . Il s'agit d'utiliser -dAutoRotatePages. Copie juste une partie de sa réponse ici:

  • -dAutoRotatePages=/None - conserve l'orientation de chaque page;
  • -dAutoRotatePages=/All - fait tourner toutes les pages (ou aucune) selon une sorte de "décision majoritaire";
  • -dAutoRotatePages=/PageByPage - fait tourner automatiquement les pages individuellement.

Par défaut, mon script est PageByPage mais cela est réglable. Cela a bien fonctionné dans mes tests. L'utilisation de -dAutoRotatePages Semble également réduire le besoin de pré-retourner la taille de la page, même si ce n'est pas la même chose. J'ai gardé les deux options.

Ma petite application a été créée à l'origine pour mettre à l'échelle des PDF (sans changer la taille de la page). Ensuite, j'ai ajouté maintenant la fonctionnalité pour faire l'un, l'autre ou les deux. Je ne pouvais toujours pas tout faire en un seul appel GS.

C'est ce que j'appelle pour le redimensionnement, en changeant les variables en valeurs réelles. C'est pour le format A4 Portrait avec PageByPage rotation automatique:

gs \
-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dSAFER \
-dCompatibilityLevel="1.5" -dPDFSETTINGS="/printer" \
-dColorConversionStrategy=/LeaveColorUnchanged \
-dSubsetFonts=true -dEmbedAllFonts=true \
-dDEVICEWIDTHPOINTS=595 -dDEVICEHEIGHTPOINTS=842 \
-dAutoRotatePages='/PageByPage' \
-dFIXEDMEDIA -dPDFFitPage \
-sOutputFile='../myOutputFile.pdf' \
-f '../input.pdf'

Veuillez noter que j'utilise également -dFIXEDMEDIA ET -dPDFFitPage. Parce que cela correspond à la page, l'autre partie de mon script peut être utile pour mettre à l'échelle le contenu à l'intérieur du PDF après le redimensionnement (surtout si la proportion du PDF a beaucoup changé). Et c'est l'une des raisons pour lesquelles je lance toujours la mise à l'échelle après le redimensionnement dans mon script (en mode mixte).

À propos des problèmes de fraction lors de l'utilisation du nom du papier, je m'en suis rendu compte avant d'arrondir les conversions de mm/pouces en points. Après avoir commencé à les arrondir, ils semblent toujours être ceux dont on a besoin. Cela semble bizarre que GS puisse plancher sur ces valeurs.

Ma conclusion est donc que le plus difficile est de trouver une solution qui fonctionne à tous les niveaux sur différents documents avec différentes tailles et orientations. Je ne suis toujours pas sûr d'utiliser la bonne solution. Mais en laissant l'utilisateur changer la détection de retournement et la rotation automatique GS, j'espère avoir une solution pour au moins la plupart des cas.

J'ai également reconstruit la plupart du code dans le processus et il est assez facile à lire maintenant. Il peut être utile de le vérifier si vous souhaitez automatiser une telle tâche vous-même. Bien sûr, il est également utile de simplement mettre à l'échelle/redimensionner les PDF:

https://github.com/tavinus/pdfScale

PS: pdfScale a ses origines sur ce fil StackOverflow .

8
Gus Neves

Votre commande ne fait aucune mise à l'échelle du tout, elle prend juste un fichier PDF et la convertit en un fichier PDF.

Je vous suggère d'essayer d'ajouter -dPDFFitPage qui redimensionnera la page dans le fichier PDF pour correspondre à la taille de la page actuelle (comme spécifié par -sPAPERSIZE dans ce cas).

Ceci est généralement destiné à fonctionner avec des imprimantes qui ont un format de papier défini, et peut donc ne pas fonctionner correctement avec le périphérique pdfwrite qui n'a pas un format de page fixe, mais c'est un essai.

7
KenS

Il semble que la taille de la sortie puisse être (mieux) forcée en spécifiant la taille en points et en n'utilisant pas -dPDFFitPage. J'obtenais des tailles de points fractionnaires, ce qui était mauvais. Ce qui suit concerne l'impression A5 à l'aide d'un service d'impression à la demande. Le "vrai" A5 correspond à 420x595 points. J'ai trouvé que l'utilisation de -sPAPERSIZE = a5 donnait des tailles de page en points fractionnaires, mais c'était peut-être parce que l'original était bancal.

gs \
 -o output.pdf \
 -sDEVICE=pdfwrite \
 -dDEVICEWIDTHPOINTS=419 -dDEVICEHEIGHTPOINTS=595 \
 -dFIXEDMEDIA \
 -dCompatibilityLevel=1.4 \
  input.pdf

Afin de tester cela, j'ai trouvé qu'en utilisant PDFshuffler j'ai pu exporter des pages individuelles, puis avec pdfinfo j'ai pu obtenir la taille précise de ces pages. Cela a confirmé que l'utilisation de paramètres de périphérique a explicitement aidé.

6
Tim B