2016-09-05 92 views
3

下面的腳本能夠使用CAM::PDF一個PDF文件中刪除所有圖像。然而,輸出是腐敗的。 PDF閱讀器仍然可以打開它,但他們抱怨錯誤。例如,mupdf說:如何刪除從PDF的所有圖像,而無需使用CAM :: PDF破壞呢?

error: no XObject subtype specified 
error: cannot draw xobject/image 
warning: Ignoring errors during rendering 
mupdf: warning: Errors found on page 

現在,CAM::PDF一頁CPAN(here)列在「更深事業」的deleteObject()方法,想必這意味着它不能用於公共用途。此外,它警告:

此函數不負責依賴此對象。

我的問題是:什麼是使用CAM::PDF從PDF文件中刪除對象的正確方法?如果問題與依賴關係有關,那麼如何在處理依賴關係時移除對象?

有關拆除使用其他工具從PDF圖像,看到一個相關的問題here

use CAM::PDF;  
my $pdf = new CAM::PDF (shift) or die $CAM::PDF::errstr; 

foreach my $objnum (sort { $a <=> $b } keys %{ $pdf->{xref} }) { 
    my $xobj = $pdf->dereference ($objnum); 

    if ($xobj->{value}->{type} eq 'dictionary') { 
    my $im = $xobj->{value}->{value}; 
    if 
    (
     defined $im->{Type} and defined $im->{Subtype} 
     and $pdf->getValue ($im->{Type} ) eq 'XObject' 
     and $pdf->getValue ($im->{Subtype}) eq 'Image' 
    ) 
    { 
     $pdf->deleteObject ($objnum); 
    } 
    } 
} 

$pdf->cleanoutput ('-'); 
+0

你會有一個損壞的pdf,使mupdf錯誤可用嗎?我正在調試類似的問題,這將是很大的幫助:) – Darajan

回答

4

這使用CAM :: PDF,但採取了稍微不同的方法。與其試圖刪除非常困難的圖像,不如用透明圖像替換每個圖像。

首先,請注意,我們可以用難懂的生成包含只不過是一個透明圖像的空白PDF:

% convert -size 200x100 xc:none transparent.pdf 

如果我們在文本編輯器查看生成的PDF,我們可以發現在主圖像對象:

8 0 obj 
<< 
/Type /XObject 
/Subtype /Image 
/Name /Im0 
... 

這裏要注意的重要一點是,我們已經產生了透明圖像的對象編號8

然後它變成小鬼的事orting這個對象,並用它來代替PDF中的每個真實圖像,有效地消隱它們。

use warnings; use strict; 
use CAM::PDF;  
my $pdf = new CAM::PDF (shift) or die $CAM::PDF::errstr; 

my $trans_pdf = CAM::PDF->new("transparent.pdf") || die "$CAM::PDF::errstr\n"; 
my $trans_objnum = 8; # object number of transparent image 

foreach my $objnum (sort { $a <=> $b } keys %{ $pdf->{xref} }) { 
    my $xobj = $pdf->dereference ($objnum); 

    if ($xobj->{value}->{type} eq 'dictionary') { 
    my $im = $xobj->{value}->{value}; 
    if 
    (
     defined $im->{Type} and defined $im->{Subtype} 
     and $pdf->getValue ($im->{Type} ) eq 'XObject' 
     and $pdf->getValue ($im->{Subtype}) eq 'Image' 
    ) { 
     $pdf->replaceObject ($objnum, $trans_pdf, $trans_objnum, 1); 
    } 
    } 
} 

$pdf->cleanoutput ('-'); 

腳本現在在與進口透明圖像對象(從transparent.pdf對象號8)的PDF替換每個圖像。

+0

爲什麼8?它從何而來?我們不會在原始文檔中用透明圖像替換對象編號8,對嗎? –

+0

@ .n.r。 8是從'transparent.pdf'導入的圖像的對象編號。我爲答案增加了更多解釋。 – dwarring

2

另一種方法,從而真正刪除圖像,方法是:在資源列表

  1. 找到並刪除圖像XObject的,
  2. 保持一個數組名字刪除資源
  3. 替代相同長度空白爲相應的運營商Do在每個頁面的內容,
  4. 清理和打印。

請注意,矮人的方法更安全,因爲它不必在末尾叫$doc->cleanse。根據CAM::PDF文檔(here),cleanse方法

刪除未使用的對象。警告:此功能會破壞一些PDF文檔,因爲它刪除嚴格屬於頁面模型層次結構但仍是必需的對象(如某些字體定義對象)。

我不知道使用cleanse可以得到多少問題。

use CAM::PDF; 
my $doc = new CAM::PDF (shift) or die $CAM::PDF::errstr; 

# delete image XObjects among resources 
# but keep their names 

my @names; 

foreach my $objnum (sort { $a <=> $b } keys %{ $doc->{xref} }) { 
    my $obj = $doc->dereference($objnum); 
    next unless $obj->{value}->{type} eq 'dictionary'; 

    my $n = $obj->{value}->{value}; 

    my $resources = $doc->getValue ($n->{Resources}  ) or next; 
    my $resource = $doc->getValue ($resources->{XObject}) or next; 

    foreach my $name (sort keys $resource) { 
    my $im = $doc->getValue ($resource->{$name}) or next; 

    next unless defined $im->{Type} 
      and defined $im->{Subtype} 
      and $doc->getValue ($im->{Type} ) eq 'XObject' 
      and $doc->getValue ($im->{Subtype}) eq 'Image'; 

    delete $resource->{$name};                           
    push @names, $name;                             
    }                                  
}                                   


# delete the corresponding Do operators                               

if (@names) {                                        
    foreach my $p (1 .. $doc->numPages) {                                  
    my $content = $doc->getPageContent ($p); 
    my $s; 
    foreach my $name (@names) { 
     ++$s if $content =~ s{(/ \Q$name\E \s+ Do \b)} { ' ' x length $1 }xeg; 
    } 
    $doc->setPageContent ($p, $content) if $s; 
    } 
} 

$doc->cleanse; 
$doc->cleanoutput; 
相關問題