Étant donné un ensemble de fichiers PDF dont certaines pages sont en couleur et le reste en noir et blanc, est-il un programme pour trouver chez les pages sont en couleur et qui sont en noir et blanc? Ce serait utile, par exemple, dans l'impression d'une thèse, et seules les dépenses supplémentaires pour l'impression de la couleur des pages. Les points Bonus pour quelqu'un qui tient compte de l'impression recto verso, et envoie un approprié de page noir et blanc à la couleur de l'imprimante si elle est suivie d'une page de couleur sur le côté opposé.
Réponses
Trop de publicités?C'est l'une des questions les plus intéressantes que j'ai vu! Je suis d'accord avec certains des autres postes que le rendu d'une image et d'analyser l'image bitmap sera la solution la plus fiable. Pour de simples fichiers Pdf, ici, est plus rapide mais moins complète de l'approche.
- Analyser chaque page PDF
- Recherchez les directives de couleur (g, rg, k, sc, scn, etc)
- Regardez pour les images incorporées, analyser pour la couleur
Ma solution ci-dessous n' #1 et la moitié de #2. L'autre moitié du n ° 2 serait de suivi avec la couleur définie par l'utilisateur, ce qui implique la recherche de la /Palette des entrées dans la page et de décodage -- me contacter en mode hors connexion si ce qui est intéressant pour vous, car il est très faisable, mais pas dans les 5 minutes.
D'abord le programme principal:
use CAM::PDF;
my $infile = shift;
my $pdf = CAM::PDF->new($infile);
PAGE:
for my $p (1 .. $pdf->numPages) {
my $tree = $pdf->getPageContentTree($p);
if (!$tree) {
print "Failed to parse page $p\n";
next PAGE;
}
my $colors = $tree->traverse('My::Renderer::FindColors')->{colors};
my $uncertain = 0;
for my $color (@{$colors}) {
my ($name, @rest) = @{$color};
if ($name eq 'g') {
} elsif ($name eq 'rgb') {
my ($r, $g, $b) = @rest;
if ($r != $g || $r != $b) {
print "Page $p is color\n";
next PAGE;
}
} elsif ($name eq 'cmyk') {
my ($c, $m, $y, $k) = @rest;
if ($c != 0 || $m != 0 || $y != 0) {
print "Page $p is color\n";
next PAGE;
}
} else {
$uncertain = $name;
}
}
if ($uncertain) {
print "Page $p has user-defined color ($uncertain), needs more investigation\n";
} else {
print "Page $p is grayscale\n";
}
}
Et puis voici l'aide de moteur de rendu, qui gère les directives de couleur sur chaque page:
package My::Renderer::FindColors;
sub new {
my $pkg = shift;
return bless { colors => [] }, $pkg;
}
sub clone {
my $self = shift;
my $pkg = ref $self;
return bless { colors => $self->{colors}, cs => $self->{cs}, CS => $self->{CS} }, $pkg;
}
sub rg {
my ($self, $r, $g, $b) = @_;
push @{$self->{colors}}, ['rgb', $r, $g, $b];
}
sub g {
my ($self, $gray) = @_;
push @{$self->{colors}}, ['rgb', $gray, $gray, $gray];
}
sub k {
my ($self, $c, $m, $y, $k) = @_;
push @{$self->{colors}}, ['cmyk', $c, $m, $y, $k];
}
sub cs {
my ($self, $name) = @_;
$self->{cs} = $name;
}
sub cs {
my ($self, $name) = @_;
$self->{CS} = $name;
}
sub _sc {
my ($self, $cs, @rest) = @_;
return if !$cs; # syntax error
if ($cs eq 'DeviceRGB') { $self->rg(@rest); }
elsif ($cs eq 'DeviceGray') { $self->g(@rest); }
elsif ($cs eq 'DeviceCMYK') { $self->k(@rest); }
else { push @{$self->{colors}}, [$cs, @rest]; }
}
sub sc {
my ($self, @rest) = @_;
$self->_sc($self->{cs}, @rest);
}
sub SC {
my ($self, @rest) = @_;
$self->_sc($self->{CS}, @rest);
}
sub scn { sc(@_); }
sub SCN { SC(@_); }
sub RG { rg(@_); }
sub G { g(@_); }
sub K { k(@_); }
Il est possible d'utiliser l' Image Magick outil identify
. S'il est utilisé sur les pages de PDF convertit la première page d'une image raster. Si la page contient la couleur peut être testé à l'aide de l' -format "%[colorspace]"
option, qui pour mon PDF imprimer Gray
ou RGB
. À mon humble avis, identify
(ou ce que jamais l'outil qu'il utilise dans l'arrière-plan; Ghostscript?) ne choisissez la couleur en fonction de la présence de la couleur.
Un exemple est:
identify -format "%[colorspace]" $FILE.pdf[$PAGE]
lorsque la PAGE est la page à partir de 0 et non pas 1. Si la page de sélection n'est pas utilisé toutes les pages doivent être ramenés à un seul, ce qui n'est pas ce que vous voulez.
J'ai écrit ce script BASH qui utilise pdfinfo
pour obtenir le nombre de pages et puis des boucles au-dessus d'eux. De la sortie des pages qui sont en couleur. J'ai également ajouté une fonctionnalité pour les double faces d'un document où vous pourriez avoir besoin d'une non-couleur du verso de la page.
À l'aide de la sortie liste séparée par des espaces, la couleur des pages PDF peuvent être extraites à l'aide d' pdftk
:
pdftk $FILE cat $PAGELIST output color_${FILE}.pdf
#!/bin/bash
FILE=$1
PAGES=$(pdfinfo ${FILE} | grep 'Pages:' | sed 's/Pages:\s*//')
GRAYPAGES=""
COLORPAGES=""
DOUBLECOLORPAGES=""
echo "Pages: $PAGES"
N=1
while (test "$N" -le "$PAGES")
do
COLORSPACE=$( identify -format "%[colorspace]" "$FILE[$((N-1))]" )
echo "$N: $COLORSPACE"
if [[ $COLORSPACE == "Gray" ]]
then
GRAYPAGES="$GRAYPAGES $N"
else
COLORPAGES="$COLORPAGES $N"
# For double sided documents also list the page on the other side of the sheet:
if [[ $((N%2)) -eq 1 ]]
then
DOUBLECOLORPAGES="$DOUBLECOLORPAGES $N $((N+1))"
#N=$((N+1))
else
DOUBLECOLORPAGES="$DOUBLECOLORPAGES $((N-1)) $N"
fi
fi
N=$((N+1))
done
echo $DOUBLECOLORPAGES
echo $COLORPAGES
echo $GRAYPAGES
#pdftk $FILE cat $COLORPAGES output color_${FILE}.pdf
Le script de Martin Scharrer est grande. Il contient un bug mineur: Il compte deux pages qui contiennent des couleurs et sont directement consécutives, à deux reprises. J'ai corrigé ça. En outre, le script en compte aujourd'hui les pages et les listes de niveaux de gris des pages pour la double page de l'impression. Aussi, il imprime les pages séparées par des virgules, de sorte que la sortie peut être directement utilisé pour l'impression à partir d'une visionneuse de PDF. J'ai ajouté le code, mais vous pouvez le télécharger ici, trop.
Cheers, timeshift
#!/bin/bash
if [ $# -ne 1 ]
then
echo "USAGE: This script needs exactly one paramter: the path to the PDF"
kill -SIGINT $$
fi
FILE=$1
PAGES=$(pdfinfo ${FILE} | grep 'Pages:' | sed 's/Pages:\s*//')
GRAYPAGES=""
COLORPAGES=""
DOUBLECOLORPAGES=""
DOUBLEGRAYPAGES=""
OLDGP=""
DOUBLEPAGE=0
DPGC=0
DPCC=0
SPGC=0
SPCC=0
echo "Pages: $PAGES"
N=1
while (test "$N" -le "$PAGES")
do
COLORSPACE=$( identify -format "%[colorspace]" "$FILE[$((N-1))]" )
echo "$N: $COLORSPACE"
if [[ $DOUBLEPAGE -eq -1 ]]
then
DOUBLEGRAYPAGES="$OLDGP"
DPGC=$((DPGC-1))
DOUBLEPAGE=0
fi
if [[ $COLORSPACE == "Gray" ]]
then
GRAYPAGES="$GRAYPAGES,$N"
SPGC=$((SPGC+1))
if [[ $DOUBLEPAGE -eq 0 ]]
then
OLDGP="$DOUBLEGRAYPAGES"
DOUBLEGRAYPAGES="$DOUBLEGRAYPAGES,$N"
DPGC=$((DPGC+1))
else
DOUBLEPAGE=0
fi
else
COLORPAGES="$COLORPAGES,$N"
SPCC=$((SPCC+1))
# For double sided documents also list the page on the other side of the sheet:
if [[ $((N%2)) -eq 1 ]]
then
DOUBLECOLORPAGES="$DOUBLECOLORPAGES,$N,$((N+1))"
DOUBLEPAGE=$((N+1))
DPCC=$((DPCC+2))
#N=$((N+1))
else
if [[ $DOUBLEPAGE -eq 0 ]]
then
DOUBLECOLORPAGES="$DOUBLECOLORPAGES,$((N-1)),$N"
DPCC=$((DPCC+2))
DOUBLEPAGE=-1
elif [[ $DOUBLEPAGE -gt 0 ]]
then
DOUBLEPAGE=0
fi
fi
fi
N=$((N+1))
done
echo " "
echo "Double-paged printing:"
echo " Color($DPCC): ${DOUBLECOLORPAGES:1:${#DOUBLECOLORPAGES}-1}"
echo " Gray($DPGC): ${DOUBLEGRAYPAGES:1:${#DOUBLEGRAYPAGES}-1}"
echo " "
echo "Single-paged printing:"
echo " Color($SPCC): ${COLORPAGES:1:${#COLORPAGES}-1}"
echo " Gray($SPGC): ${GRAYPAGES:1:${#GRAYPAGES}-1}"
#pdftk $FILE cat $COLORPAGES output color_${FILE}.pdf
ImageMagick intègre des méthodes de comparaison d'images.
http://www.imagemagick.org/Usage/compare/#type_general
Il y a quelques Perl Api pour ImageMagick, alors peut-être si vous habilement de les combiner avec un PDF en Image convertisseur vous pouvez trouver un moyen de le faire en noir et blanc de test.
Je voudrais essayer de le faire comme ça, même s'il pourrait y avoir d'autres solutions plus simples, et je suis curieux de les entendre, j'ai juste envie de l'essayer:
- Boucle sur toutes les pages
- Extraire les pages à une image
- De vérifier la gamme de couleurs de l'image
Pour le nombre de pages, vous pouvez probablement traduire que sans trop d'effort, Perl. En gros, c'est une regex. Il est également dit que:
r"(/Type)\s?(/Page)[/>\s]"
Il vous suffit de compter le nombre de fois cette expression régulière se produit dans le fichier PDF, moins le temps de vous rechercher la chaîne "<>" (vide des âges qui ne sont pas rendus).
Pour extraire l'image, vous pouvez utiliser ImageMagick pour faire que. Ou voir à cette question.
Enfin, pour obtenir qu'il est noir et blanc, ça dépend si tu veux dire littéralement en noir et blanc ou en niveaux de gris. Pour le noir et blanc, vous ne devriez avoir, bien, le noir et le blanc dans toute l'image. Si vous voulez voir en niveaux de gris, maintenant, c'est vraiment pas ma spécialité, mais je suppose que vous pourriez voir si les moyennes de le rouge, le vert et le bleu sont proches les uns des autres ou si l'image d'origine et un converti en niveaux de gris sont proches les uns des autres.
Espérons qu'il donne quelques conseils pour vous aider à aller plus loin.