Module: PdfUtils

Extended by:
InTmpdir
Defined in:
lib/pdf_utils.rb,
lib/pdf_utils/info.rb,
lib/pdf_utils/color.rb

Defined Under Namespace

Classes: Color, Info

Constant Summary collapse

THUMBNAIL_DEFAULTS =
{ :density => 150, :size => '50%', :format => 'jpg', :quality => 85, :target => nil, :page => 1 }.freeze
SNAPSHOT_DEFAULTS =
{ :density => 150, :compress => 'JPEG', :quality => 85 }.freeze

Class Method Summary collapse

Class Method Details

.annotate(source, annotations, target, options = {}) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
# File 'lib/pdf_utils.rb', line 111

def annotate(source, annotations, target, options = {})
  options[:page_size] ||= info(source).page_dimensions
  with_tmpfile("annotate") do |annotated|
    Prawn::Document.generate(annotated, options) do |pdf|
      annotations.each do |annotation| 
        pdf.annotate(annotation)
      end
    end
    run_command(:pdftk, "#{annotated} background #{source} output #{target}")
  end
end

.annotate!(source, annotations, options = {}) ⇒ Object



123
124
125
126
127
# File 'lib/pdf_utils.rb', line 123

def annotate!(source, annotations, options = {})
  target = tmp_file_name("annotate_merge")
  annotate(source, annotations, target, options)
  FileUtils.mv(target, source)
end

.annotations(filename) ⇒ Object



29
30
31
# File 'lib/pdf_utils.rb', line 29

def annotations(filename)
  objects(filename, :Type => :Annot)
end

.burst(source, target) ⇒ Object



88
89
90
# File 'lib/pdf_utils.rb', line 88

def burst(source, target)
  run_command(:pdftk, "#{source} burst output #{target}")
end

.cat(source, target) ⇒ Object



92
93
94
# File 'lib/pdf_utils.rb', line 92

def cat(source, target)
  run_command(:pdftk, "#{source} cat output #{target}")
end

.info(filename) ⇒ Object



33
34
35
# File 'lib/pdf_utils.rb', line 33

def info(filename)
  PdfUtils::Info.new(filename)
end

.objects(filename, filter = {}) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/pdf_utils.rb', line 16

def objects(filename, filter={})
  uncompress(filename) do |uncompressed|
    PDF::Hash.new(uncompressed).values.select do |obj|
      if obj.kind_of?(Hash)
        if obj.has_key?(:Contents) && obj[:Contents].kind_of?(String)
          obj[:Contents] = Iconv.conv('utf-8', 'utf-16', obj[:Contents]) 
        end
        filter.detect {|k, v| obj[k] == v }
      end 
    end
  end
end

.run_command(command, args, reroute_errors = true) ⇒ Object



163
164
165
166
167
168
169
170
171
172
173
# File 'lib/pdf_utils.rb', line 163

def run_command(command, args, reroute_errors = true)
  command = [command, args]
  command << '2>&1' if reroute_errors
  command = command.join(' ')
  output = `#{command}`
  if $?.success?
    output
  else
    raise RuntimeError.new("Command failed: #{command}\n#{output}")
  end
end

.slice(source, from_page, to_page, target) ⇒ Object



78
79
80
# File 'lib/pdf_utils.rb', line 78

def slice(source, from_page, to_page, target)
  run_command(:pdftk, "#{source} cat #{from_page}-#{to_page} output #{target}")
end

.slice!(source, from_page, to_page) ⇒ Object



82
83
84
85
86
# File 'lib/pdf_utils.rb', line 82

def slice!(source, from_page, to_page)
  target = tmp_file_name("slice")
  slice(source, from_page, to_page, target)
  FileUtils.mv(target, source)
end

.snapshot(source, target, options = {}) ⇒ Object



151
152
153
154
155
156
157
# File 'lib/pdf_utils.rb', line 151

def snapshot(source, target, options = {})
  options.assert_valid_keys(SNAPSHOT_DEFAULTS.keys + [:page])
  page_number = (options.delete(:page) || 1).to_i
  source  = "#{source}[#{page_number-1}]"
  options = SNAPSHOT_DEFAULTS.merge(options).map{ |opt,val| "-#{opt} #{val}" } << "#{source} #{target}"
  run_command(:convert, options)
end

.snapshot!(source, options = {}) ⇒ Object



159
160
161
# File 'lib/pdf_utils.rb', line 159

def snapshot!(source, options = {})
  snapshot(source, source, options)
end

.thumbnail(source, options = {}) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/pdf_utils.rb', line 131

def thumbnail(source, options = {})
  options.assert_valid_keys(THUMBNAIL_DEFAULTS.keys)

  options = THUMBNAIL_DEFAULTS.merge(options)
  target  = options[:target] || source.sub(/(\.\w+)?$/, ".#{options[:format]}")
  source  = "#{source}[#{options[:page].to_i-1}]"
  
  run_command(:convert, [
    '-density'          , options[:density],
    source,
    '-colorspace'       , :rgb,
    '-thumbnail'        , options[:size],
    '-quality'          , options[:quality],
    target        
  ].join(' '))
  return target
end

.to_swf(source, target) ⇒ Object



62
63
64
# File 'lib/pdf_utils.rb', line 62

def to_swf(source, target)
  run_command(:pdf2swf, "-T 9 -f -s transparent -s detectspaces #{source} -o #{target}")
end

.to_text(filename, target = nil) ⇒ Object



58
59
60
# File 'lib/pdf_utils.rb', line 58

def to_text(filename, target = nil)
  run_command(:pdftotext, "-layout -enc UTF-8 #{filename} #{target || '-'}", !!target)
end

.toc(filename) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/pdf_utils.rb', line 37

def toc(filename)
  toc = []
  if  = run_command(:pdftk, "#{filename} dump_data")
    entry = nil
    .scan(/^Bookmark(\w+): (.*)$/) do |(key, value)|
      case key
        when "Title"
          entry = [value]
        when "Level"
          entry << value.to_i
        when "PageNumber"
          if value.to_i > 0
            entry << value.to_i
            toc << entry 
          end
      end
    end
  end
  toc
end

.uncompress(source, target = nil, &block) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
# File 'lib/pdf_utils.rb', line 66

def uncompress(source, target=nil, &block)
  target ||= tmp_file_name("uncompress")
  run_command(:pdftk, "#{source} output #{target} uncompress")
  if block_given?
    begin
      yield(target)
    ensure
      FileUtils.rm(target)
    end
  end
end

.watermark(source, target, options = {}, &block) ⇒ Object

Raises:

  • (ArgumentError)


96
97
98
99
100
101
102
103
# File 'lib/pdf_utils.rb', line 96

def watermark(source, target, options = {}, &block)
  raise ArgumentError.new("No block given") unless block_given?
  options[:page_size] ||= info(source).page_dimensions
  with_tmpfile("watermark") do |watermarked|
    Prawn::Document.generate(watermarked, options, &block)
    run_command(:pdftk, "#{source} background #{watermarked} output #{target}")
  end
end

.watermark!(source, options = {}, &block) ⇒ Object



105
106
107
108
109
# File 'lib/pdf_utils.rb', line 105

def watermark!(source, options = {}, &block)
  target = tmp_file_name("watermark_merge")
  watermark(source, target, options, &block)
  FileUtils.mv(target, source)      
end