質問

いくつかのページがカラーで残りが黒であるPDFファイルのセットが与えられた<!> amp;白、与えられたページの中で色と黒の<!> amp;を見つけるプログラムはありますか?白?これは、たとえば、論文を印刷し、カラーページを印刷するためだけに余分な費用をかける場合に役立ちます。両面印刷を考慮に入れ、反対側にカラーページが続く場合に適切な白黒ページをカラープリンターに送信する人に対するボーナスポイント。

役に立ちましたか?

解決

これは私が見た中で最も興味深い質問の一つです!私は、ビットマップにレンダリングしてからビットマップを分析することが最も信頼できるソリューションになるという他の投稿のいくつかに同意します。シンプルな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(@_); }

他のヒント

Ghostscript (バージョン9.05以降)の新しいバージョンには、<!> quot; device <!> quot ; inkcovと呼ばれます。シアン(C)、マゼンタ(M)、イエロー(Y)、ブラック(K)の各ページ(各画像ではなく)のインク被覆率を計算します。0.00000は0%を意味し、1.000000は100%を意味します(< em> 色を含むすべてのページの検出 )。

例:

$ 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でない場合、ページはカラーです。

色を含むページを出力するには、次の便利なワンライナーを使用します。

$ 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'

Image Magick ツールidentifyを使用できます。 PDFページで使用する場合、最初にページをラスターイメージに変換します。ページに含まれている色が-format "%[colorspace]"オプションを使用してテストできる場合、PDFではGrayまたはRGBが印刷されます。私見pdfinfo(またはバックグラウンドで使用するツール; Ghostscript?)は、色の存在に応じて色空間を選択します。

例:

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

ここで、PAGEは1ではなく0から始まるページです。ページ選択を使用しない場合、すべてのページが1つに折りたたまれますが、これは意図したものではありません。

pdftkを使用してページ数を取得し、それらをループする次のBASHスクリプトを作成しました。カラーのページを出力します。また、両面印刷用の機能を追加しました。この機能では、色のない裏面ページも必要になる場合があります。

出力されたスペース区切りリストを使用して、色付きPDFページは<=>:

を使用して抽出できます。
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

Martin Scharrerのスクリプトは素晴らしいです。マイナーバグが含まれています。色が含まれ、2回連続して連続する2つのページをカウントします。私はそれを修正しました。さらに、スクリプトはページをカウントし、二重ページ印刷用のグレースケールページをリストします。また、コンマで区切られたページを印刷するため、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

ImageMagickにはいくつかのPerl APIがあります。したがって、これらをPDFから画像へのコンバーターと巧みに組み合わせれば、黒の<!> amp;を実行する方法を見つけることができます。ホワイトテスト。

他のもっと簡単な解決策があるかもしれませんが、そのようにしようと思います、そしてそれらを聞きたいのですが、私はそれを試してみたいです:

  1. すべてのページをループ
  2. ページを画像に抽出する
  3. 画像の色範囲を確認する

ページ数については、おそらく をPerlにあまり労力をかけずに翻訳できます。 。基本的には正規表現です。また、言った

>
  

r <!> quot;(/ Type)\ s?(/ Page)[/ <!> gt; \ s] <!> quot;

     

単に数を数える必要があります   この正規表現が発生する回数   PDFファイルで、マイナスの回数   文字列<!> quot; <!> lt; <!> gt; <!> quot;を見つけます。   (レンダリングされない空の年齢)。

画像を抽出するには、 ImageMagick を使用してそれ。または、この質問をご覧ください。

最後に、白黒かどうかを判断するには、文字通り白黒かグレースケールかを判断します。白黒の場合、すべての画像に白黒のみが含まれている必要があります。グレースケールを表示したい場合、それは本当に私の専門ではありませんが、赤、緑、青の平均が互いに近いか、元の画像とグレースケール変換のいずれかが互いに近い。

さらに先へ進むためのヒントを提供してください。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top