如何在打印前从PDF文本中删除黑色背景

wgp*_*ubs 6 printing pdf edit colors

我有一个黑色背景和白色/黄色文本的PDF.

如何在打印前删除黑色背景并反转文本的颜色?

Chr*_*lan 6

这通常很难解决,但如果你有一个可预测的PDF集合(例如,所有来自同一个来源),那么你可能能够像这样快速解决一个快速的解决方案:

  • 从CPAN 安装CAM :: PDF
  • 运行"getpdfpage.pl my.pdf 1> page1.txt"获取第1页的图形代码
  • 搜索"rg"以查找RGB文本颜色的位置(或"RG"表示背景,或者"g"或"G"表示灰度,"k"或"K"表示CMYK颜色"sc"或"SC" "对于特殊颜色空间)
  • 编辑page1.txt以设置您喜欢的颜色
  • 运行"setpdfpage.pl my.pdf 1 page1.txt out.pdf"

所有这些都可以通过编程方式完成,而不是通过命令行工具.getpdfpage.pl和setpdfpage.pl是围绕CAM :: PDF API的简单小包装器.

一般的解决方案是使用getPageContentTree()来解析PDF页面语法并搜索颜色更改操作符并更改它们.但是,如果您的PDF使用自定义颜色空间("sc"),这可能会非常棘手.并且搜索执行整页黑色填充的操作员也可能很难,具体取决于几何形状.

如果您提供示例PDF的URL,我可以提供一些更具体的建议.

更新:一时兴起,我写了一个基本的换色器脚本,可能适用于某些PDF.要使用它,请运行此示例,将任何红色元素变为绿色:

perl recolor.pl input.pdf '1 0 0 rg' '0 1 0 rg' out.pdf
Run Code Online (Sandbox Code Playgroud)

这需要您了解您尝试更改的颜色指令的PDF语法,因此可能仍需要类似上面推荐的getpdfpage.pl步骤.

和源代码:

#!/usr/bin/perl -w                      

use strict;
use CAM::PDF;
use CAM::PDF::Content;

my %COLOROPS = map {$_ => 1} qw(rg RG g G k K sc SC);

my $pdf = CAM::PDF->new(shift) || die $CAM::PDF::errstr;
my @oldcolors;
my @newcolors;
while (@ARGV >= 2) {
   push @oldcolors, parseColor(shift);
   push @newcolors, parseColor(shift);
}
my $out = shift || '-';

for my $p (1 .. $pdf->numPages) {
   my $page = $pdf->getPageContentTree($p);
   traverse($page->{blocks});
   $pdf->setPageContent($p, $page->toString());
}
$pdf->cleanoutput($out);

sub parseColor {
   my ($in) = @_;
   my $ops = CAM::PDF::Content->new($in);
   die 'Invalid color syntax in ' . $in if !$ops->validate();
   my @blocks = @{$ops->{blocks}};
   die 'Expected one color operator in ' . $in if @blocks != 1;
   my $color = $blocks[0];
   die 'Not a color operator in ' . $in if !exists $COLOROPS{$color->{name}};
   return $color;
}

sub traverse {
   my ($blocks) = @_;
   for my $op (@{$blocks}) {
      if ($op->{type} eq 'block') {
         traverse($op->{value});
      } elsif (exists $COLOROPS{$op->{name}}) {
       COLOR:
         for (my $i=0; $i < @oldcolors; ++$i) {
            my $old = $oldcolors[$i];
            if ($old->{name} eq $op->{name} && @{$old->{args}} == @{$op->{args}}) {
               for (my $v=0; $v < @{$op->{args}}; ++$v) {
                  next COLOR if $old->{args}->[$v]->{value} != $op->{args}->[$v]->{value};
               }
               # match! so we will replace                                                                                  
               $op->{name} = $newcolors[$i]->{name};
               @{$op->{args}} = @{$newcolors[$i]->{args}};
               last COLOR;
            }
         }
      }
   }
}
Run Code Online (Sandbox Code Playgroud)