سؤال

بالنظر إلى مجموعة من ملفات PDF التي تكون بعض الصفحات فيها ملونة والباقي بالأبيض والأسود، هل يوجد أي برنامج لمعرفة أي الصفحات الملونة وأيها أبيض وأسود من بين الصفحات المحددة؟قد يكون هذا مفيدًا، على سبيل المثال، في طباعة أطروحة، وإنفاق المزيد فقط على طباعة الصفحات الملونة.نقاط إضافية لمن يأخذ في الاعتبار الطباعة على الوجهين، ويرسل صفحة مناسبة بالأبيض والأسود إلى الطابعة الملونة إذا كانت متبوعة بصفحة ملونة على الجانب الآخر.

هل كانت مفيدة؟

المحلول

هذا أحد الأسئلة الأكثر إثارة للاهتمام التي رأيتها!وأنا أتفق مع بعض المنشورات الأخرى التي ترى أن عرض الصورة النقطية ثم تحليل الصورة النقطية سيكون الحل الأكثر موثوقية.بالنسبة لملفات PDF البسيطة، إليك طريقة أسرع ولكن أقل اكتمالًا.

  1. تحليل كل صفحة PDF
  2. ابحث عن توجيهات الألوان (g، rg، k، sc، scn، إلخ)
  3. ابحث عن الصور المضمنة، وقم بتحليل الألوان

الحل الخاص بي أدناه هو رقم 1 ونصف رقم 2.النصف الآخر من رقم 2 سيكون المتابعة باستخدام اللون المحدد من قبل المستخدم، والذي يتضمن البحث عن إدخالات /ColorSpace في الصفحة وفك تشفيرها - اتصل بي دون الاتصال بالإنترنت إذا كان هذا مثيرًا للاهتمام بالنسبة لك، لأنه ممكن جدًا ولكن ليس في 5 دقائق.

أولا البرنامج الرئيسي:

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";
   }
}

ثم إليك العارض المساعد الذي يتعامل مع توجيهات الألوان في كل صفحة:

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(@_); }

نصائح أخرى

وتشمل

غوستسكريبت (الإصدار 9.05 و في وقت لاحق) "جهاز" ودعا inkcov. وتحسب التغطية الحبر من كل صفحة (وليس لكل صورة) في سماوي (C) والأرجواني (M) والأصفر (Y) والأسود القيم (K)، حيث 0.00000 الوسائل 0٪، و1.00000 يعني 100٪ (انظر < م> الكشف عن الصفحات التي تحتوي على اللون ).

وعلى سبيل المثال:

$ gs -q -o - -sDEVICE=inkcov file.pdf 
0.11264  0.11605  0.11605  0.09364 CMYK OK
0.11260  0.11601  0.11601  0.09360 CMYK OK

وإذا كانت القيم CMY ليست 0 ثم تكون الصفحة اللون.

لإخراج عادل الصفحات التي تحتوي على ألوان تستخدم هذا oneliner يدوية:

$ gs -o - -sDEVICE=inkcov file.pdf |tail -n +4 |sed '/^Page*/N;s/\n//'|sed -E '/Page [0-9]+ 0.00000  0.00000  0.00000  / d'

ومن الممكن استخدام صورة ماغيك أداة identify. إذا ما استخدمت على صفحات PDF ذلك بتحويل الصفحة الأولى إلى صورة نقطية. إذا كان لون الصفحة الواردة يمكن اختبارها باستخدام الخيار -format "%[colorspace]"، التي لبلدي PDF طباعة إما Gray أو RGB. IMHO identify (أو ما من أي وقت مضى أداة يستخدم في الخلفية.؟ غوستسكريبت). لا اختيار فضاء لوني اعتمادا على هدايا من اللون

مثال:

identify -format "%[colorspace]" $FILE.pdf[$PAGE]

وحيث PAGE هي بداية الصفحة من 0، لا 1. إذا لم يتم استخدام اختيار الصفحة سيتم انهار كل الصفحات واحدة، وهي ليست على ما تريد.

وكتبت السيناريو BASH التالية التي تستخدم pdfinfo للحصول على عدد من الصفحات وثم حلقات عليها. إخراج الصفحات التي هي في اللون. أود أيضا أن أضيف ميزة للمستند مزدوجة من جانب حيث قد تحتاج إلى الصفحة المؤخر غير ملونة أيضا.

واستخدام الفضاء أنتج قائمة فصل صفحات PDF ملونة يمكن استخراجها باستخدام 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

والسيناريو من مارتن Scharrer كبيرة. أنه يحتوي على خلل بسيط: أنها تعول صفحتين التي تحتوي على اللون وتكون متتابعة مباشرة مرتين. أنا ثابت ذلك. وبالإضافة إلى ذلك بحساب النصي الآن في صفحة ويسرد الصفحات تدرج الرمادي للطباعة مقسم إلى صفحات مزدوجة. أيضا فإنه يطبع الصفحات مفصولة بفواصل، بحيث يمكن مباشرة إخراج استخدامها للطباعة من عارض PDF. واضاف لقد الرمز، ولكن يمكنك تحميل البرنامج هنا أيضا .

وابتهاج، الانتقال الزمني

#!/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 على بعض الطرق المضمنة لمقارنة الصور.

http://www.imagemagick.org/Usage/compare/#type_general

توجد بعض واجهات برمجة التطبيقات Perl لـ ImageMagick، لذا ربما إذا قمت بدمجها بذكاء مع محول PDF إلى صورة، يمكنك العثور على طريقة لإجراء اختبار الأبيض والأسود.

سأحاول أن أفعل ذلك بهذه الطريقة، على الرغم من أنه قد تكون هناك حلول أخرى أسهل، وأنا أشعر بالفضول لسماعها، أريد فقط تجربتها:

  1. حلقة من خلال جميع الصفحات
  2. استخراج الصفحات إلى صورة
  3. التحقق من نطاق الألوان للصورة

بالنسبة لعدد الصفحات، ربما يمكنك الترجمة الذي - التي دون بذل الكثير من الجهد لبيرل.انها في الأساس ريكس.انها أيضا قال الذي - التي:

r"(/النوع)\s?(/الصفحة)[/>\s]"

عليك ببساطة حساب عدد المرات التي يحدث فيها هذا التعبير العادي في ملف PDF ، ناقصًا الأوقات التي تجد فيها السلسلة "<>" (الأعمار الفارغة التي لم يتم تقديمها).

لاستخراج الصورة، يمكنك استخدام ImageMagick لكى يفعل الذي - التي.أو انظر هذا السؤال.

أخيرًا، لمعرفة ما إذا كان اللون أبيض وأسود، يعتمد الأمر على ما إذا كنت تعني حرفيًا أبيض وأسود أو تدرج رمادي.بالنسبة للأبيض والأسود، يجب أن يكون لديك فقط أبيض وأسود في الصورة بأكملها.إذا كنت تريد رؤية التدرج الرمادي، فهذا ليس تخصصي حقًا ولكن أعتقد أنه يمكنك معرفة ما إذا كانت متوسطات اللون الأحمر والأخضر والأزرق قريبة من بعضها البعض أو إذا كانت الصورة الأصلية و تم تحويل التدرج الرمادي أحدهما قريب من الآخر.

نأمل أن يعطي بعض التلميحات لمساعدتك على المضي قدمًا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top