Aller au contenu
getnextpdf.com

Pro édition

Optimizer — référence détaillée

Cette page est la référence détaillée de la surface publique de NextPDF\Pro\Optimizer. Elle couvre l’orchestrateur d’analyse, les niveaux d’optimisation, les deux scanneurs et les objets valeur de résultat. Elle précise les paramètres, les valeurs par défaut, l’arithmétique d’estimation et les modes de défaillance. L’analyse est en lecture seule : elle estime les gains et ne produit aucun document de sortie. Lis d’abord la page de capacité Optimizer pour des conseils sur le flux de travail.

Cette capacité est livrée dans NextPDF Pro (nextpdf/pro) et s’active avec une enveloppe de licence de niveau Pro. Un déploiement dépourvu de ce droit ne charge pas les classes de la capacité. Compare les éditions et obtiens une licence.

Optimizer n’a pas de drapeau de licence par fonctionnalité. C’est une capacité de l’édition Pro. Le niveau d’optimisation est un paramètre d’exécution, pas un commutateur de licence.

Fenêtre de terminal
composer require nextpdf/pro:^3

Le métapaquet nextpdf/premium installe le code nextpdf/pro ; ce module réside dans l’espace de noms NextPDF\Pro\Optimizer.

SymboleParamètresComportement par défautRetourneLève ou échoue avecNotes
PdfOptimizer::__constructOptimizationLevel $level = OptimizationLevel::BalancedConstruit un optimiseur au niveau donnéPdfOptimizerRien de déclaréConstruit ses propres instances de scanneur
PdfOptimizer::analyzestring $pdfDataAnalyse en lecture seule au niveau configuréOptimizationResultOverflowException si l’entrée dépasse 100,000,000 octets ; InvalidArgumentException depuis les scanneurs sur des données PDF invalidesEstimation seulement ; ne produit aucun document de sortie
PdfOptimizer::withLevelOptimizationLevel $levelRetourne un nouvel optimiseur au niveau demandéselfRien de déclaréL’instance réceptrice reste inchangée
OptimizationLevelcas Lossless, Balanced, AggressiveEnum à valeur chaîne des niveaux d’agressivitéValeurs sous-jacentes lossless, balanced, aggressive
OptimizationLevel::labelaucunLibellé de niveau lisiblestringRien de déclaréPour l’affichage
OptimizationLevel::imageQualityaucunQualité d’image cible pour le niveauintRien de déclaré100, 75 ou 50
OptimizationLevel::deduplicateStreamsaucunIndique si le niveau active le dédoublonnageboolRien de déclaréfalse pour Lossless uniquement
OptimizationResult::__constructint $originalSize, int $optimizedSize, int $objectsRemoved, int $imagesBefore, int $imagesAfter, float $processingTimeMsRésultat d’analyse immuableOptimizationResultRien de déclaréToutes les propriétés sont publiques et readonly
OptimizationResult::savedBytesaucunTaille d’origine moins la taille optimisée estiméeintRien de déclaréOctets
OptimizationResult::savedPercentaucunRéduction de taille en pourcentagefloatRien de déclaré0.0 quand la taille d’origine est nulle
OptimizationResult::summaryaucunRapport lisible sur plusieurs lignesstringRien de déclaréTailles formatées en B, KB ou MB
ObjectDeduplicator::findDuplicatesstring $pdfDataRegroupe les corps d’objets identiques par hachage SHA-256list<DuplicateGroup>InvalidArgumentException en l’absence d’en-tête %PDF, si l’entrée dépasse 268,435,456 octets, ou au-delà de 500,000 marqueurs d’objetNe retourne que les groupes d’au moins deux membres
ObjectDeduplicator::estimateSavingslist<DuplicateGroup> $groupsSomme, par groupe, du nombre de doublons multiplié par la taille d’objetintRien de déclaréOctets
ImageRecompressor::analyzeImagesstring $pdfDataExtrait les métadonnées de chaque XObject imagelist<ImageAnalysis>InvalidArgumentException en l’absence d’en-tête %PDFIgnore les objets sans largeur et hauteur explicites
ImageRecompressor::suggestCompressionImageAnalysis $image, OptimizationLevel $levelRecommande un filtre et estime les gainsImageCompressionSuggestionRien de déclaréHeuristiques dépendantes du niveau ; voir le contrat de comportement
DuplicateGroup::__constructstring $contentHash, list<int> $objectNumbers, int $objectSizeEnregistrement immuable de groupe de doublonsDuplicateGroupRien de déclaréLe premier numéro d’objet est l’objet canonique conservé
DuplicateGroup::duplicateCountaucunTaille du groupe moins l’objet canoniqueintRien de déclaréObjets supprimables par fusion
ImageAnalysis::__constructint $objectNumber, int $width, int $height, string $colorSpace, int $bitsPerComponent, string $filter, int $streamSizeEnregistrement immuable de métadonnées par imageImageAnalysisRien de déclaréLes champs reflètent les entrées du dictionnaire d’image
ImageAnalysis::estimatedDpifloat $displayWidthPtDPI effectif à la largeur d’affichage donnéefloatRien de déclaré0.0 quand la largeur d’affichage est nulle ou négative
ImageAnalysis::isOverResolutionfloat $displayWidthPt, int $targetDpi = 300Signale les candidats au sous-échantillonnage au-dessus du DPI cibleboolRien de déclaréComparaison strictement supérieure
ImageCompressionSuggestion::__constructint $objectNumber, string $currentFilter, string $suggestedFilter, int $estimatedSavings, string $reasonEnregistrement immuable de recommandationImageCompressionSuggestionRien de déclaréreason est un texte explicatif lisible
final class PdfOptimizer
{
public function __construct(
private OptimizationLevel $level = OptimizationLevel::Balanced,
)
public function analyze(string $pdfData): OptimizationResult
public function withLevel(OptimizationLevel $level): self
}
enum OptimizationLevel: string
{
case Lossless = 'lossless';
case Balanced = 'balanced';
case Aggressive = 'aggressive';
public function label(): string
public function imageQuality(): int
public function deduplicateStreams(): bool
}
final readonly class OptimizationResult
{
public function __construct(
public int $originalSize,
public int $optimizedSize,
public int $objectsRemoved,
public int $imagesBefore,
public int $imagesAfter,
public float $processingTimeMs,
)
public function savedBytes(): int
public function savedPercent(): float
public function summary(): string
}
final class ObjectDeduplicator
{
public function findDuplicates(string $pdfData): array
public function estimateSavings(array $groups): int
}
final class ImageRecompressor
{
public function analyzeImages(string $pdfData): array
public function suggestCompression(
ImageAnalysis $image,
OptimizationLevel $level,
): ImageCompressionSuggestion
}

PdfOptimizer::analyze accepte des octets PDF bruts et est en lecture seule. Il borne d’abord l’entrée non fiable à 100,000,000 octets ; une entrée trop volumineuse lève OverflowException avant l’exécution de tout scan. Il exécute ensuite l’analyse de dédoublonnage lorsque le niveau l’autorise, exécute toujours l’analyse des images, et agrège les deux dans un seul OptimizationResult. withLevel retourne un nouvel optimiseur ; les instances ne sont jamais mutées.

NiveauQualité d’image cibleDédoublonnageIntention
Lossless100%DésactivéAucune perte de qualité ; sortie visée octet-stable
Balanced75%ActivéCompromis de qualité modéré ; le niveau par défaut
Aggressive50%ActivéRéduction maximale ; sous-échantillonnage ; perte de qualité visible

Lossless ignore le dédoublonnage afin que la sortie reste octet-stable. La qualité cible alimente l’arithmétique de suggestion d’image ci-dessous.

Le dédoublonneur analyse les définitions d’objet indirect de génération zéro (N 0 obj jusqu’à endobj). Chaque corps est débarrassé des espaces qui l’entourent, haché en SHA-256 et regroupé par hachage. Les définitions ne différant que par le remplissage correspondent donc quand même. Seuls les groupes d’au moins deux membres sont retournés. Les gains estimés par groupe valent le nombre de doublons multiplié par la taille d’un corps unique, puisque tous les objets sauf le canonique peuvent être supprimés.

Un objet est traité comme une image lorsque son corps contient /Subtype /Image (avec ou sans espace interne). La largeur et la hauteur sont requises ; un objet auquel l’une manque est ignoré. L’espace colorimétrique vaut DeviceRGB par défaut, les bits par composante 8, et le filtre une chaîne vide en son absence. La taille du flux est mesurée entre les marqueurs stream et endstream ; lorsqu’aucun flux en ligne n’est trouvé, la valeur /Length est utilisée à la place.

  • Au niveau Lossless, le filtre courant est conservé et les gains estimés sont nuls.
  • Pour les sources DCTDecode, la suggestion réencode à la qualité du niveau. L’estimation vaut la taille du flux multipliée par (1 − qualité/100) multipliée par 0.5.
  • Pour les sources FlateDecode, la suggestion convertit en DCTDecode. L’estimation vaut 40% de la taille du flux en Balanced et 60% en Aggressive.
  • Pour tout autre filtre, ou aucun filtre, la suggestion convertit en FlateDecode. L’estimation vaut 20% de la taille du flux.
  • Le nombre d’objets supprimés vaut la somme, sur tous les groupes de doublons, des membres au-delà du premier canonique.
  • Les gains totaux valent les gains de dédoublonnage plus les estimations de suggestion par image.
  • La taille optimisée estimée est la taille d’origine moins les gains totaux, avec un plancher à zéro. Les gains sont non négatifs, donc l’estimation n’excède jamais la taille d’origine.
  • Le nombre d’images après soustrait, pour chaque groupe de doublons contenant une image analysée, le nombre de membres en double de ce groupe. Le compte a un plancher à zéro.
  • Le temps de traitement est mesuré avec une horloge monotone et reporté en millisecondes.

L’estimateur de DPI divise la largeur en pixels par la largeur d’affichage en pouces (72 points par pouce). Une largeur d’affichage nulle ou négative donne 0.0. Le prédicat de sur-résolution compare l’estimation à une cible, 300 DPI par défaut.

  • analyze ne rapporte que le potentiel. Produis la sortie optimisée avec le module Writer.
  • Une entrée vide, ou une entrée ne commençant pas par l’en-tête %PDF, échoue avec InvalidArgumentException.
  • Une entrée dépassant 100,000,000 octets échoue avec OverflowException à la porte d’entrée de l’orchestrateur, avant tout scan.
  • Le dédoublonneur rejette indépendamment une entrée dépassant 268,435,456 octets et plus de 500,000 marqueurs d’objet. Les deux rejettent en échec fermé avec InvalidArgumentException ; rien n’est tronqué ni scanné partiellement.
  • Seules les définitions d’objet de génération zéro participent. Les objets ayant un numéro de génération non nul ne sont pas scannés.
  • Une définition sans marqueur endobj de fermeture est ignorée.
  • Les objets image sans largeur et hauteur explicites sont exclus du rapport d’images.
  • Tous les chiffres de gains sont des heuristiques dérivées des métadonnées d’objet, pas des résultats de recompression mesurés.
  • Le niveau lossless rapporte intentionnellement de faibles réductions ; il préserve la qualité et ignore le dédoublonnage.
  • L’analyse ne décode, n’exécute ni ne rend jamais le contenu embarqué. Elle ne lit que la structure des objets et les métadonnées.
  • La seule primitive cryptographique utilisée est SHA-256, pour le regroupement de contenu en double. Le module ne définit aucun comportement spécifique à FIPS.

Les deux scanneurs opèrent sur le modèle d’objet et d’image PDF d’ISO 32000-2:2020. Le dédoublonnage cible les définitions d’objet indirect ; la structure de leur identifiant est définie dans ISO 32000-2:2020, 7.3.10, citée dans l’enregistrement de citations de cette page. L’analyse des images lit les paramètres qu’un dictionnaire d’image indique explicitement — largeur, hauteur et bits par composante — selon ISO 32000-2:2020, 8.9.4, également citée.

Ces déclarations décrivent la capacité au regard des clauses citées. NextPDF ne détient aucune certification de conformité, et la prise en charge d’une clause n’est pas une allégation de certification.

  • Le code source du module porte @since 1.9.0 ; cette référence documente la surface telle que livrée dans nextpdf/pro 3.1.0.
  • Toutes les classes sont final ; les enregistrements de résultat et d’analyse sont des objets valeur readonly. Construis de nouvelles instances plutôt que de muter.
  • Le niveau par défaut est Balanced. Sélectionne un autre niveau via le constructeur ou la méthode de style with.
  • La borne d’entrée de la porte d’entrée est appliquée par un garde de taille d’entrée Core partagé entre les surfaces d’entrée de NextPDF.
  • L’analyse est basée sur des chaînes portant sur des octets déjà en mémoire. Le module n’effectue aucun accès au système de fichiers ni au réseau.
  • Le détail des mécanismes internes reste dans la documentation interne du dépôt source et sort du périmètre de ce manuel.

Cette page documente uniquement le comportement observable de l’extérieur et la surface d’API publique prise en charge. Les chemins d’espaces de noms internes, les classes d’aide, les tables de mécanismes, les noms de fichiers de runbook et les préfixes de tickets sortent du périmètre.