代码之家  ›  专栏  ›  技术社区  ›  Anil

如何知道PDF页面是彩色还是黑白?

  •  65
  • Anil  · 技术社区  · 17 年前

    给定一组PDF文件,其中一些页面是彩色的,其余的是黑色的;白色,有什么程序可以在给定的页面中找出哪些是彩色的,哪些是黑色的吗;白色?例如,这在打印论文时非常有用,只需额外花费打印彩色页面即可。考虑双面打印,并将适当的黑白页发送到彩色打印机(如果后面是另一面的彩色页)的人将获得加分。

    7 回复  |  直到 15 年前
        1
  •  29
  •   Chris Dolan    17 年前

    1. 查找颜色指令(g、rg、k、sc、scn等)
    2. 查找嵌入图像,分析颜色

    首先是主程序:

    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
  •  26
  •   Community Mohan Dere    8 年前

    较新版本的 Ghostscript (9.05及更高版本)包括一个名为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,则页面为彩色。

    要输出包含颜色的页面,请使用这个方便的单行线:

    $ 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'
    
        3
  •  16
  •   Martin Scharrer    14 年前

    可以使用 Image Magick 工具 identify -format "%[colorspace]" 选项,对于我的PDF打印 Gray RGB 依我拙见 (或者它在背景中使用什么工具;Ghostscript?)确实会根据颜色的呈现来选择颜色空间。

    一个例子是:

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

    其中PAGE是从0开始的页面,而不是1。如果不使用页面选择,所有页面都将折叠为一个页面,这不是您想要的。

    我编写了以下BASH脚本,该脚本使用 pdfinfo 获取页数,然后循环遍历。输出彩色页面。我还为双面文档添加了一个功能,您可能还需要一个无色的背面页面。

    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
    
        4
  •  3
  •   iamtimeshift    13 年前

    Martin Scharrer的剧本很棒。它包含一个小错误:它计算了两个包含颜色并且直接连续两次的页面。我修好了。此外,脚本现在对页面进行计数,并列出双页打印的灰度页面。此外,它还打印逗号分隔的页面,因此输出可以直接用于从PDF查看器进行打印。我已经添加了代码,但你可以下载 here

    时空飞梭

    #!/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
    
        5
  •  2
  •   Cᴏʀʏ bcherry    17 年前

    ImageMagick有一些内置的图像比较方法。

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

        6
  •  2
  •   Community Mohan Dere    9 年前

    我会尝试这样做,尽管可能有其他更简单的解决方案,我很想听听,我只是想试试:

    1. 循环浏览所有页面
    2. 将页面提取为图像

    that said

    r“(/Type)\ s?(/Page)[/>\ s]”

    你只需要数一下有多少 在PDF文件中,减去您的时间 找到字符串“<>” (未显示的空白年龄)。

    ImageMagick that 。或查看 this question .

    最后,要知道它是黑白的,这取决于你是指黑白还是灰度。对于黑白,你应该在所有图像中只有黑白。如果你想看灰度,现在,这真的不是我的专长,但我想你可以看看红色、绿色和蓝色的平均值是否彼此接近,或者原始图像和 grayscale converted

        7
  •  0
  •   Elarion    5 年前

    这是Windows的ghostscript解决方案,它需要GnuWin的grep( http://gnuwin32.sourceforge.net/packages/grep.htm ):

    单色(黑白)页面:

    gswin64c -q -o - -sDEVICE=inkcov DOCUMENT.pdf | grep "^ 0.00000 0.00000 0.00000" | find /c /v ""

    gswin64c -q -o - -sDEVICE=inkcov DOCUMENT.pdf | grep -v "^ 0.00000 0.00000 0.00000" | find /c /v ""

    总页数(您可以从任何pdf阅读器轻松获得此页):

    gswin64c -q -o - -sDEVICE=inkcov DOCUMENT.pdf | find /c /v ""

    推荐文章