2009-03-13 12 views
55

一部のページがカラーで、残りが黒色の&白である場合、指定されたページの中で色が黒であることを見つけるプログラムはありますか?&白ですか?これは、例えば、論文を印刷し、カラーページを印刷するために余分に費やす場合に有用である。両面印刷を考慮し、適切な白黒ページをカラープリンタに送る場合は、反対側にカラーページが続くもののボーナスポイント。PDFページがカラーか白黒かを知る方法は?

+0

TeXのstackexchange http://tex.stackexchange.com/questions/53493/d​​etecting-allに、この同様の問題で利用可能な他の提案-pages-containing-contains-color – Gareth

+0

恐ろしい質問です。ありがとう。 – Geoff

答えて

27

これは私が見た中で最も興味深い質問の一つです!私はビットマップへのレンダリングとビットマップの解析が最も信頼性の高いソリューションになるという、他の投稿のいくつかに同意します。簡単なPDFの場合は、ここでは速くても完全ではないアプローチです。色指示用

  1. 解析各PDFページ
  2. ルック(G、RG、K、SC、SCNなど)
  3. 埋め込みイメージを探し、以下マイ溶液色
  4. ため

を分析#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(@_); } 
2

ImageMagickには画像比較のためのいくつかの組み込みメソッドがあります。

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

はので、多分あなたが巧みに画像変換器へのPDFでこれらを組み合わせた場合、あなたはあなたの黒&白のテストを行うための方法を見つけることができ、ImageMagickのためのいくつかのPerlのAPIがあります。

2

他のより容易な解決策があるかもしれませんが、私は、そのようにそれを行うにしようと、私はそれを聞いて興味が、私はちょうどしようと、それを与えたい:

  1. ループをすべてのページを
  2. は画像ページ数については

の色の範囲を確認し、画像

  • にページを抽出し、あなたはおそらくPerlのにあまりにも多くの努力なしthatを翻訳することができます。基本的には正規表現です。またsaidだこと:

    R "(/タイプ)\ S(/ページ)[/> \ s]は?" あなたは単に 回、この正規表現は中 を発生するどのように多くカウントする必要があり

    文字列 "<>" (レンダリングされていない空の年齢)を除いたPDFファイル。

    画像を抽出するには、ImageMagickを使用してthatを使用します。またはthis questionを参照してください。

    最後に、白黒かどうかは、文字通り白黒またはグレースケールを意味するかどうかによって決まります。黒と白の場合は、すべての画像に白黒があります。グレースケールを見たいのであれば、それは本当に私の専門ではありませんが、赤、緑、青の平均値が近いかどうか、または元のイメージとgrayscale convertedがそれぞれ近くにあるかどうかを確認できますその他。

    さらに進んでいただくためのヒントをご希望の場合は、

  • +1

    ページ数を取得するには:perl -le'use CAM :: PDF; CAM :: PDF-> new( "my.pdf") - > numPages ' –

    15

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

    例は次のとおりです。

    ページの選択は、すべてのページは、あなたが望むものではありませんこれは、一つに崩壊されます使用されていない場合は、ページが0から始まるページではなく、1です。
    identify -format "%[colorspace]" $FILE.pdf[$PAGE] 
    

    私はpdfinfoを使用してページ数を取得し、それをループする次のBASHスクリプトを作成しました。色付きのページを出力する。また、両面原稿のための機能を追加しました。色付きの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 
    
    +2

    このTeXファイルを考えてみましょう: 'hello world \ bye'。 '' -formed "%color spaces" "" $ FILE.pdf [0] "'の出力は 'sRGB'であり、' gs -o - -sDEVICE = inkcov $ FILE.pdf ''(ここでは示唆されている) (http://tex.stackexchange.com/a/61216/31416))私は '0.00000 0.00000 0.00000 0.00020 CMYK OK'を得てより合理的です – giordano

    +0

    ' pdfinfo'の依存性を避けるには ' (それが起こると、それはページカウントを教えてくれるでしょう) –

    +0

    ...それはページ "-1"にもあります。 –

    3

    マーティンScharrerからスクリプトが素晴らしいです。それはマイナーなバグを含んでいます:それは、色を含み、直接2回連続する2つのページを数えます。私はそれを修正した。さらに、スクリプトはページ数をカウントし、両面印刷のグレースケールページを表示します。また、カンマ区切りのページを印刷するので、出力を直接PDFビューアからの印刷に使用できます。コードを追加しましたが、hereもダウンロードできます。

    乾杯、 タイムシフトGhostscript(バージョン9.05以降)の

    #!/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 
    
    12

    新しいバージョンはinkcovいわゆる "デバイス" を含みます。シアン(C)、マゼンタ(M)、イエロー(Y)、ブラック(K)の各値(0.00000は0%を意味し、1.00000は100%を意味する)における各ページのインクカバレッジを計算する(Detecting all pages which contain color)。例えば

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

    それは私にさせてくれないタイプミスがありますこのメソッドは必ずしも期待どおりに動作するわけではなく、たとえイメージが純粋にグレースケールであっても、inkscで作成されたpdfファイルは常に0以外のCMY値を持つことになります –

    +0

    ありがとうIタイプミスを修正 – Matteo

    関連する問題