PDF 一致性工具

PDF 一致性工具

是否有一个(免费提供的)工具可以检查 PDF 文件是否符合 PDF 标准?

我听说这被称为“飞行前检查”或类似的东西。

答案1

多价有一个免费的(如 beer)pdf 验证工具。它肯定不如 Acrobat preflight 那么强大,但对你来说可能已经足够了。

预检通常不仅仅包括验证是否符合 pdf 格式。它还包括确保字体嵌入、颜色空间正确、图像分辨率合适等。也许你不需要这类东西。

答案2

尝试这些:

  • 編輯是一个免费工具,可以对 PDF 进行一些检查,但这些检查主要是语法检查。
  • Adobe Acrobat 的预检工具。但它不是免费的。

答案3

有很多网站提供验证 pdf 的服务。请谷歌搜索 pdf、validate、online,你会得到类似这样的地址http://www.pdf-tools.com/pdf/validate-pdfa-online.aspx

缺点是,任何地方的其他人都可能使用你的 pdf 来达到你不喜欢的目的。对于我这个律师来说,这是绝对不行的。

答案4

正如 JorgeGT 指出的那样,pdflatex 输出的 pdf 可能存在错误,这并不是因为 pdflatex 本身存在错误,而是因为您包含的图形存在问题。我认为以下 perl 脚本可能对其他人有帮助。它在 Linux 上运行。它旨在对将包含在 LaTeX 文档中的图形进行预检,旨在捕捉过去给我带来麻烦的东西。我通常会在同一个目录中放置一个 Inkscape .svg 文件,并将该文件渲染为 .pdf、.jpg 或 .png,并且脚本是假设该组织而编写的。

当我有一个使用透明度的 Inkscape 文件时,我发现在发送 pdf 进行翻录之前消除透明度是最安全的。虽然它可能有效,但硬拷贝有时会出现乱码。最简单的方法是使用 Inkscape 将图形渲染为 png 文件,然后使用 imagemagick 从 png 中删除透明度。

我以前遇到过这样的问题:pdf 图形中嵌入了字体,而我却不知道。理论上这没什么大不了的,但在实践中,它导致了 rip 问题。如果您没有权限重新分发您没有意识到嵌入在 pdf 中的字体,您还可能会遇到法律问题。要解决 Inkscape 图形的这个问题,您可以在保存为 pdf 时执行“将文本转换为路径”。

#!/usr/bin/perl

use strict;

# usage:
#   preflight_one_fig.pl foo.svg
# Checks whether there is no rendered version of foo.svg.
# Checks whether it was rendered to foo.png. If so, complains if it has transparency.
# Checks whether there is also a foo.pdf. If there is, checks foo.svg and foo.pdf for problems:
#   transparency (checked for in the svg)
#   fonts embedded in pdf
#   bad pdf structure
#   pdf older than svg
# If there's a problem, prints a message to stdout and exits with nonzero error code.

# requires the following tools:
#   xml_grep (part of ubuntu package xml-twig-tools)
#   qpdf (ubuntu package qpdf)
#   pdffonts (ubuntu package poppler-utils)
#   identify and mogrify (ubuntu package imagemagick)

my $svg = $ARGV[0];

my $pdf = $svg;
$pdf =~ s/\.svg$/.pdf/;
if (-e $pdf) {
  my $err = check_pdf($svg,$pdf);
  if ($err) {err($err)}
  exit(0);
}
else {
  # There's no pdf, so there'd better be a .jpg or .png
  foreach my $e('jpg','png') {
    my $bitmap = $svg;
    $bitmap =~ s/\.svg$/.$e/;
    if (-e $bitmap) {
      if ($e eq 'png') {
        my $f = `identify -format '%[channels]' $bitmap`;
        if ($f=~/rgba/) {
          my $c = "mogrify -background white -flatten -alpha off $bitmap";
          # system($c);
          err("file $bitmap contains transparency; fix with\n  $c\nand then check visually");
        }
      }
      exit(0);
    }
  }
  err("file $svg does not exist as .pdf, .jpg, or .png");
}

sub err {
  my $message = shift;
  print $message,"\n";
  exit(-1);
}

sub check_pdf {
  my ($svg,$pdf) = @_;
  my $err = check_for_stale_pdf($svg,$pdf);
  return $err if $err;
  my $err = check_pdf_for_fonts($svg,$pdf);
  return $err if $err;
  my $err = check_pdf_for_transparency($svg,$pdf);
  return $err if $err;
  my $err = check_pdf_for_structure($svg,$pdf);
  return $err if $err;
  return undef;
}

sub check_for_stale_pdf {
  my ($svg,$pdf) = @_;
  # -M is relative age of file in days, floating point
  (-M $svg) > (-M $pdf) or return 
         "file $pdf is older than file $svg, ".(-M $svg)." < ".(-M $pdf);
  return undef;
}

sub check_pdf_for_structure {
  my ($svg,$pdf) = @_;
  system("qpdf --check $pdf 1>/dev/null 2>/dev/null")==0 or return "bad structure for $pdf detected by qpdf --check:\n";
  return undef;
}

sub check_pdf_for_fonts {
  my ($svg,$pdf) = @_;
  my $fonts = `pdffonts $pdf`;
  $fonts =~ /\A.*\n.*\n(.*)/; # strip header lines
  my $f = $1;
  if ($f ne '') {return "embedded fonts found in file $pdf, made from $svg"}
  return undef;
}

sub check_pdf_for_transparency {
  my ($svg,$pdf) = @_;

  # for efficiency, first do a rough check:
  return undef unless `grep -e "opacity:[^1]" $svg`;

  # Now do a more reliable check.
  # There are three types of opacity: fill-opacity, stroke-opacity, and opacity (applied to whole groups).
  my $transp = `xml_grep --cond='*[\@style]' $svg  | grep -e "opacity:[^1]"`;
  if ($transp ne '') {
    # Often we get something like this:
    #     style="fill:none;fill-opacity:0.75"
    # This is harmless because there is no fill, so the transparency of the fill is irrelevant.
    while ($transp=~/style\s*=\s*"([^"]*)"/gi) {
      my $style = $1;
      my %styles = ();
      foreach my $item(split /;/,$style) {
        if ($item=~/(.*):(.*)/) {$styles{lc($1)} = lc($2)}
      }
      if (defined $styles{'opacity'} && $styles{"opacity"}<1) {
        return report_transparency($svg,$style);
      }
      foreach my $sf('stroke','fill') {
        if (   $styles{$sf} ne 'none' # works correctly if undef
            && defined $styles{"${sf}-opacity"}
            && $styles{"${sf}-opacity"}<1 ) { 
          return report_transparency($svg,$style);
        }
      }
    }
  }
  return undef;
}

sub report_transparency {
  my ($svg,$style) = @_;
  $style =~ /(.{0,22}opacity:[^1].{0,10})/;
  my $shorter = $1;
  return "transparency found in file $svg : ...$shorter...";
}

相关内容