libis-format 0.9.41 → 0.9.44

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +365 -0
  3. data/bin/droid +1 -1
  4. data/bin/fido +1 -1
  5. data/bin/pdf_copy +1 -1
  6. data/lib/libis/format/config.rb +1 -0
  7. data/lib/libis/format/converter/audio_converter.rb +1 -1
  8. data/lib/libis/format/converter/base.rb +2 -1
  9. data/lib/libis/format/converter/office_converter.rb +2 -2
  10. data/lib/libis/format/converter/pdf_converter.rb +6 -6
  11. data/lib/libis/format/converter/video_converter.rb +96 -2
  12. data/lib/libis/format/identifier.rb +12 -12
  13. data/lib/libis/format/tool/droid.rb +108 -0
  14. data/lib/libis/format/tool/extension_identification.rb +58 -0
  15. data/lib/libis/format/tool/ffmpeg.rb +43 -0
  16. data/lib/libis/format/tool/fido.rb +91 -0
  17. data/lib/libis/format/tool/file_tool.rb +78 -0
  18. data/lib/libis/format/tool/identification_tool.rb +175 -0
  19. data/lib/libis/format/tool/office_to_pdf.rb +54 -0
  20. data/lib/libis/format/tool/pdf_copy.rb +42 -0
  21. data/lib/libis/format/tool/pdf_merge.rb +43 -0
  22. data/lib/libis/format/tool/pdf_optimizer.rb +38 -0
  23. data/lib/libis/format/tool/pdf_split.rb +41 -0
  24. data/lib/libis/format/tool/pdf_to_pdfa.rb +78 -0
  25. data/lib/libis/format/tool/pdfa_validator.rb +63 -0
  26. data/lib/libis/format/tool.rb +23 -0
  27. data/lib/libis/format/version.rb +1 -1
  28. data/lib/libis/format.rb +1 -15
  29. data/libis-format.gemspec +1 -2
  30. data/spec/converter_audio_spec.rb +66 -0
  31. data/spec/converter_image_spec.rb +166 -0
  32. data/spec/converter_office_spec.rb +84 -0
  33. data/spec/converter_pdf_spec.rb +30 -0
  34. data/spec/converter_repository_spec.rb +91 -0
  35. data/spec/converter_video_spec.rb +97 -0
  36. data/spec/data/video/copyright.png +0 -0
  37. data/spec/identifier_spec.rb +3 -15
  38. metadata +32 -33
  39. data/lib/libis/format/droid.rb +0 -106
  40. data/lib/libis/format/extension_identification.rb +0 -55
  41. data/lib/libis/format/ffmpeg.rb +0 -41
  42. data/lib/libis/format/fido.rb +0 -89
  43. data/lib/libis/format/file_tool.rb +0 -76
  44. data/lib/libis/format/identification_tool.rb +0 -174
  45. data/lib/libis/format/office_to_pdf.rb +0 -52
  46. data/lib/libis/format/pdf_copy.rb +0 -40
  47. data/lib/libis/format/pdf_merge.rb +0 -41
  48. data/lib/libis/format/pdf_optimizer.rb +0 -36
  49. data/lib/libis/format/pdf_split.rb +0 -39
  50. data/lib/libis/format/pdf_to_pdfa.rb +0 -74
  51. data/lib/libis/format/pdfa_validator.rb +0 -61
  52. data/spec/converter_spec.rb +0 -433
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 52324c2a0a320c5a4e9940998515baf300186927
4
- data.tar.gz: 8a19e17da36919d97d9310663136a9b9d9889a31
3
+ metadata.gz: 22fe2305d1461bf58825e88933f215cd64fffdba
4
+ data.tar.gz: 454e2fc45afeae5b338723df845923c7f4364d10
5
5
  SHA512:
6
- metadata.gz: 1dd5dea124dfc761dc0b39f6a5810ac61424b29ff88ffcd17eb32a1bdb423625146c6b67a649eced61908b048b83f02f3fd9f53d0c3762a1f78889e770432cce
7
- data.tar.gz: 40369f9ea7ccdfc2e4b84e239d78e36952c87e0b3351e700a1ce2bd104ab446f1f5ff64816ea57c7faf9c71928f73721ed73b6bb4acbc83237531bb8aa621a5e
6
+ metadata.gz: ecf6f26241e61b34c6162c31ee1f55896a8d9bb67b01e2484db1714d1c5dfc75ce5666fad215dc8bc99d6e12d6f50fac3e81f92c9f47a5d8f26bdb43c0766d7b
7
+ data.tar.gz: 8743beb8af9bc17f9953e9488d0fc78ccb8e709a5fcbc551470926fea972e39560b6ab092faa52789109ff796b7309f45bba9844e395c1e2cc0f3c10d94b27b8
data/README.md CHANGED
@@ -30,6 +30,371 @@ Or install it yourself as:
30
30
 
31
31
  The type database is the core of the format services. It stores information about all the known formats.
32
32
 
33
+ ### ::Libis::Format::Identifier
34
+
35
+ This class enables support for format identification. It will use 3 external tools to identify a file format:
36
+ droid, fido and the unix file tool. Based on several criteria, the results of these tools will be given a
37
+ score and the result with the highest confidence is returned. The output of all tools can also be returned.
38
+ The format identification result contains a MIME-type and a PRONOM PUID if they are known. Also the calculated
39
+ score, the tool that produced the outcome and recognition method are listed. Some tools also return more
40
+ information like the format name and format version. If these are present on the most confident output, their
41
+ values will also be part of the result info.
42
+
43
+ Unidentified files will be listed with MIME-type 'application/octet-stream' and PUID 'fmt/unknown'.
44
+
45
+ The main method #get that performs the format identification takes two parameters:
46
+ - file: can be a string representing a file or directory path, but also an array of file paths.
47
+ - options: optional hash with parameters that influence the behaviour of the format identification process
48
+
49
+ The options has accespts the following keys (Symbol types):
50
+ - :droid
51
+ Boolean if set to false will not use the Droid tool. Default: true
52
+ - :fido
53
+ Boolean if set to false will not use the Fido tool. Default: true
54
+ - :file
55
+ Boolean if set to false will not use the Unix file tool. Default: true
56
+ - :tool
57
+ Symbol either :droid, :fido or :file. A shortcut option for setting only the given value to true.
58
+ - :xml_validation
59
+ Boolean if set to false will not perform XML validation (see below)
60
+ - :recursive
61
+ Boolean if set to true and a directory is passed as first argument, Identifier will parse the
62
+ directory tree recursively and will process all files found. Default: false
63
+ - :base_dir
64
+ String. Normally file will be referenced by their absolute path in the results. If a value is
65
+ supplied for this option, the given path will be stripped from the start of the file references in the
66
+ result. Default: nil.
67
+ - :keep_output
68
+ Boolean if set will store the output of each identification tool in the result structure. Default: false
69
+
70
+ The result of the identification is a Hash with the following keys:
71
+ - :messages
72
+ a list (Array) of error and warning messages that the Identifier or one of the tools used has generated.
73
+ Each entry is another Array with the first argument the severity of the message and the second one the
74
+ message itself.
75
+ - :output
76
+ optional output of each tool as an Array with an entry per tool and grouped into a Hash by file reference.
77
+ - :formats
78
+ a Hash with file references as key and the outcome of the identification as value.
79
+
80
+ The identification outcome is a Hash of key-value pairs for each property returned. Keys are lower-case
81
+ symbols. If the tools gave results that deffer in a significant part, their outcome will be added to a list as
82
+ :alternatives (see example).
83
+
84
+ #### XML Validation
85
+
86
+ None of the tools used is able to identify an XML file by its content. In our context this is especially
87
+ annoying for EAD XML files as we want to identify them in order to process them different from the other XML
88
+ files. The Identifier solves this by performing an extra check on files identified as XML files. It will
89
+ validate each XML file against a list of XML schemas and return the matching MIME-type in the result. If the
90
+ Type Database contains an entry for this format, the result will be extended with the information from the
91
+ Type Database.
92
+
93
+ With the :xml_validation option this behaviour can be turned off, for instance in cases where no EAD files are
94
+ to be expected or no further identification of XML files is needed. Note that if no XML files are present, the
95
+ Identifier will not spend any time on XML validation anyway.
96
+
97
+ The list of validation schemas can be extended with the class method #add_xml_validation which takes two
98
+ parameters: a MIME-type and the path to an XML schema (XSD). If you want to also assign a fictuous PUID to the
99
+ XML type you should add an entry to your Type Database with the same MIME-type.
100
+
101
+ ### Example
102
+
103
+ ```
104
+ ```
105
+
106
+ ```
107
+ {
108
+ :messages => [
109
+ [0] [
110
+ [0] :debug,
111
+ [1] "XML file validated against XML Schema: [...]/data/ead.xsd"
112
+ ],
113
+ [1] [
114
+ [0] :debug,
115
+ [1] "XML file validated against XML Schema: [...]/data/ead.xsd"
116
+ ],
117
+ [2] [
118
+ [0] :debug,
119
+ [1] "XML file validated against XML Schema: [...]/data/ead.xsd"
120
+ ]
121
+ ],
122
+ :output => {
123
+ "[...]/data/Cevennes2.bmp" => [
124
+ [0] {
125
+ :matchtype => "signature",
126
+ :ext_mismatch => "false",
127
+ :puid => "fmt/116",
128
+ :mimetype => "image/bmp",
129
+ :format_name => "Windows Bitmap",
130
+ :format_version => "3.0",
131
+ :source => :droid,
132
+ :TYPE => :BMP,
133
+ :GROUP => :IMAGE,
134
+ :score => 7
135
+ },
136
+ [1] {
137
+ :puid => "fmt/116",
138
+ :format_name => "Windows Bitmap",
139
+ :format_version => "Windows Bitmap 3.0",
140
+ :mimetype => "image/bmp",
141
+ :matchtype => "signature",
142
+ :source => :fido,
143
+ :TYPE => :BMP,
144
+ :GROUP => :IMAGE,
145
+ :score => 7
146
+ },
147
+ [2] {
148
+ :mimetype => "image/bmp",
149
+ :matchtype => "magic",
150
+ :source => :file,
151
+ :TYPE => :BMP,
152
+ :GROUP => :IMAGE,
153
+ :score => 2
154
+ }
155
+ ],
156
+ "[...]/data/Cevennes2.jp2" => [
157
+ [0] {
158
+ :matchtype => "signature",
159
+ :ext_mismatch => "false",
160
+ :puid => "x-fmt/392",
161
+ :mimetype => "image/jp2",
162
+ :format_name => "JP2 (JPEG 2000 part 1)",
163
+ :format_version => "",
164
+ :source => :droid,
165
+ :TYPE => :JP2,
166
+ :GROUP => :IMAGE,
167
+ :score => 7
168
+ },
169
+ [1] {
170
+ :puid => "x-fmt/392",
171
+ :format_name => "JP2 (JPEG 2000 part 1)",
172
+ :format_version => "JPEG2000",
173
+ :mimetype => "image/jp2",
174
+ :matchtype => "signature",
175
+ :source => :fido,
176
+ :TYPE => :JP2,
177
+ :GROUP => :IMAGE,
178
+ :score => 7
179
+ },
180
+ [2] {
181
+ :mimetype => "image/jp2",
182
+ :matchtype => "magic",
183
+ :source => :file,
184
+ :TYPE => :JP2,
185
+ :GROUP => :IMAGE,
186
+ :score => 2
187
+ }
188
+ ],
189
+ [...]
190
+ },
191
+ :formats => {
192
+ "[...]/data/Cevennes2.bmp" => {
193
+ :matchtype => "signature",
194
+ :ext_mismatch => "false",
195
+ :puid => "fmt/116",
196
+ :mimetype => "image/bmp",
197
+ :format_name => "Windows Bitmap",
198
+ :format_version => "3.0",
199
+ :source => :droid,
200
+ :TYPE => :BMP,
201
+ :GROUP => :IMAGE,
202
+ :score => 7
203
+ },
204
+ "[...]/data/Cevennes2.jp2" => {
205
+ :matchtype => "signature",
206
+ :ext_mismatch => "false",
207
+ :puid => "x-fmt/392",
208
+ :mimetype => "image/jp2",
209
+ :format_name => "JP2 (JPEG 2000 part 1)",
210
+ :format_version => "JPEG2000",
211
+ :source => :droid,
212
+ :TYPE => :JP2,
213
+ :GROUP => :IMAGE,
214
+ :score => 7
215
+ },
216
+ "[...]/data/NikonRaw-CameraRaw.TIF" => {
217
+ :matchtype => "signature",
218
+ :ext_mismatch => "false",
219
+ :puid => "fmt/353",
220
+ :mimetype => "image/tiff",
221
+ :format_name => "Tagged Image File Format",
222
+ :format_version => "TIFF generic (little-endian)",
223
+ :source => :droid,
224
+ :TYPE => :TIFF,
225
+ :GROUP => :IMAGE,
226
+ :score => 7
227
+ },
228
+ "[...]/data/NikonRaw-CaptureOne.tif" => {
229
+ :matchtype => "signature",
230
+ :ext_mismatch => "false",
231
+ :puid => "x-fmt/387",
232
+ :mimetype => "image/tiff",
233
+ :format_name => "Exchangeable Image File Format (Uncompressed)",
234
+ :format_version => "2.2",
235
+ :source => :droid,
236
+ :TYPE => :TIFF,
237
+ :GROUP => :IMAGE,
238
+ :score => 7,
239
+ :alternatives => [
240
+ [0] {
241
+ :puid => "fmt/353",
242
+ :format_name => "Tagged Image File Format",
243
+ :format_version => "TIFF generic (little-endian)",
244
+ :mimetype => "image/tiff",
245
+ :matchtype => "signature",
246
+ :source => :fido,
247
+ :TYPE => :TIFF,
248
+ :GROUP => :IMAGE,
249
+ :score => 7
250
+ },
251
+ [1] {
252
+ :matchtype => "signature",
253
+ :ext_mismatch => "false",
254
+ :puid => "x-fmt/387",
255
+ :mimetype => "image/tiff",
256
+ :format_name => "Exchangeable Image File Format (Uncompressed)",
257
+ :format_version => "2.2",
258
+ :source => :droid,
259
+ :TYPE => :TIFF,
260
+ :GROUP => :IMAGE,
261
+ :score => 7
262
+ }
263
+ ]
264
+ },
265
+ "[...]/data/test-ead.xml" => {
266
+ :matchtype => "signature",
267
+ :ext_mismatch => "false",
268
+ :puid => "fmt/101",
269
+ :mimetype => "archive/ead",
270
+ :format_name => "Encoded Archival Description (EAD)",
271
+ :format_version => "",
272
+ :source => :xsd_validation,
273
+ :TYPE => :EAD,
274
+ :GROUP => :ARCHIVE,
275
+ :score => 7,
276
+ :tool => :droid,
277
+ :match_type => "xsd_validation"
278
+ },
279
+ "[...]/data/test.doc" => {
280
+ :matchtype => "container",
281
+ :ext_mismatch => "false",
282
+ :puid => "fmt/40",
283
+ :mimetype => "application/msword",
284
+ :format_name => "Microsoft Word Document",
285
+ :format_version => "97-2003",
286
+ :source => :droid,
287
+ :TYPE => :MSDOC,
288
+ :GROUP => :TEXT,
289
+ :score => 9,
290
+ :alternatives => [
291
+ [0] {
292
+ :matchtype => "container",
293
+ :ext_mismatch => "false",
294
+ :puid => "fmt/40",
295
+ :mimetype => "application/msword",
296
+ :format_name => "Microsoft Word Document",
297
+ :format_version => "97-2003",
298
+ :source => :droid,
299
+ :TYPE => :MSDOC,
300
+ :GROUP => :TEXT,
301
+ :score => 9
302
+ },
303
+ [1] {
304
+ :puid => "fmt/111",
305
+ :format_name => "OLE2 Compound Document Format",
306
+ :format_version => "OLE2 Compound Document Format",
307
+ :mimetype => nil,
308
+ :matchtype => "signature",
309
+ :source => :fido,
310
+ :score => 3
311
+ }
312
+ ]
313
+ },
314
+ "[...]/data/test.docx" => {
315
+ :matchtype => "container",
316
+ :ext_mismatch => "false",
317
+ :puid => "fmt/412",
318
+ :mimetype => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
319
+ :format_name => "Microsoft Word for Windows",
320
+ :format_version => "2007 onwards",
321
+ :source => :droid,
322
+ :TYPE => :MSDOCX,
323
+ :GROUP => :TEXT,
324
+ :score => 9
325
+ },
326
+ "[...]/data/test.xlsx" => {
327
+ :matchtype => "container",
328
+ :ext_mismatch => "false",
329
+ :puid => "fmt/214",
330
+ :mimetype => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
331
+ :format_name => "Microsoft Excel for Windows",
332
+ :format_version => "2007 onwards",
333
+ :source => :droid,
334
+ :TYPE => :MSXLSX,
335
+ :GROUP => :TABULAR,
336
+ :score => 9,
337
+ :alternatives => [
338
+ [0] {
339
+ :matchtype => "container",
340
+ :ext_mismatch => "false",
341
+ :puid => "fmt/214",
342
+ :mimetype => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
343
+ :format_name => "Microsoft Excel for Windows",
344
+ :format_version => "2007 onwards",
345
+ :source => :droid,
346
+ :TYPE => :MSXLSX,
347
+ :GROUP => :TABULAR,
348
+ :score => 9
349
+ },
350
+ [1] {
351
+ :mimetype => "application/octet-stream",
352
+ :matchtype => "magic",
353
+ :source => :file,
354
+ :score => -2
355
+ }
356
+ ]
357
+ },
358
+ "[...]/data/test_pdfa.pdf" => {
359
+ :matchtype => "signature",
360
+ :ext_mismatch => "false",
361
+ :puid => "fmt/354",
362
+ :mimetype => "application/pdf",
363
+ :format_name => "Acrobat PDF/A - Portable Document Format",
364
+ :format_version => "1b",
365
+ :source => :droid,
366
+ :TYPE => :PDFA,
367
+ :GROUP => :TEXT,
368
+ :score => 7,
369
+ :alternatives => [
370
+ [0] {
371
+ :puid => "fmt/19",
372
+ :format_name => "Acrobat PDF 1.5 - Portable Document Format",
373
+ :format_version => "PDF 1.5",
374
+ :mimetype => "application/pdf",
375
+ :matchtype => "signature",
376
+ :source => :fido,
377
+ :TYPE => :PDF,
378
+ :GROUP => :TEXT,
379
+ :score => 7
380
+ },
381
+ [1] {
382
+ :matchtype => "signature",
383
+ :ext_mismatch => "false",
384
+ :puid => "fmt/354",
385
+ :mimetype => "application/pdf",
386
+ :format_name => "Acrobat PDF/A - Portable Document Format",
387
+ :format_version => "1b",
388
+ :source => :droid,
389
+ :TYPE => :PDFA,
390
+ :GROUP => :TEXT,
391
+ :score => 7
392
+ }
393
+ ]
394
+ }
395
+ }
396
+ }
397
+ ```
33
398
  ## Contributing
34
399
 
35
400
  1. Fork it ( https://github.com/Kris-LIBIS/LIBIS_Format/fork )
data/bin/droid CHANGED
@@ -5,7 +5,7 @@ require 'libis-tools'
5
5
 
6
6
  ::Libis::Tools::Config.logger.level = :WARN
7
7
 
8
- result = ::Libis::Format::Droid.run ARGV[0]
8
+ result = ::Libis::Format::Tool::Droid.run ARGV[0]
9
9
 
10
10
  result.each do |r|
11
11
  r.each do |key, value|
data/bin/fido CHANGED
@@ -5,7 +5,7 @@ require 'libis-tools'
5
5
 
6
6
  ::Libis::Tools::Config.logger.level = :WARN
7
7
 
8
- result = ::Libis::Format::Fido.run ARGV[0]
8
+ result = ::Libis::Format::Tool::Fido.run ARGV[0]
9
9
 
10
10
  result.each do |key, value|
11
11
  puts "#{key}: #{value}"
data/bin/pdf_copy CHANGED
@@ -9,5 +9,5 @@ source = ARGV.shift
9
9
  target = ARGV.shift
10
10
  options = ARGV
11
11
 
12
- ::Libis::Format::PdfCopy.run source, target, options
12
+ ::Libis::Format::Tool::PdfCopy.run source, target, options
13
13
 
@@ -22,6 +22,7 @@ module Libis
22
22
  Config[:xml_validations] = [['archive/ead', File.join(data_dir, 'ead.xsd')]]
23
23
  Config[:type_database] = File.join(data_dir, 'types.yml')
24
24
  Config[:raw_audio_convert_cmd] = 'sox %s -e signed -b 16 -t wav %s rate %d channels %d'
25
+ Config[:watermark_font] = '/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf'
25
26
 
26
27
  end
27
28
  end
@@ -168,7 +168,7 @@ module Libis
168
168
  opts[:output] << '-ar' << @options[:sampling_freq] if @options[:sampling_freq]
169
169
  opts[:output] << '-ac' << @options[:channels] if @options[:channels]
170
170
  opts[:output] << '-f' << @options[:format] if @options[:format]
171
- result = Libis::Format::FFMpeg.run(source, target, opts)
171
+ result = Libis::Format::Tool::FFMpeg.run(source, target, opts)
172
172
  info "FFMpeg output: #{result}"
173
173
  result
174
174
  target
@@ -3,6 +3,7 @@
3
3
  ### require 'tools/string'
4
4
  require 'tmpdir'
5
5
  require 'libis/tools/logger'
6
+ require 'libis/tools/temp_file'
6
7
  require 'libis/format/type_database'
7
8
 
8
9
  require_relative 'repository'
@@ -43,7 +44,7 @@ module Libis
43
44
  end
44
45
 
45
46
  def Base.using_temp(target)
46
- tempfile = File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname(['convert', File.extname(target)], File.basename(target, '.*').gsub(/\s/, '_')))
47
+ tempfile = Tools::TempFile.name("convert-#{File.basename(target, '.*').gsub(/\s/, '_')}", File.extname(target))
47
48
  result = yield tempfile
48
49
  return nil unless result
49
50
  FileUtils.move result, target
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative 'base'
4
4
 
5
- require 'libis/format/office_to_pdf'
5
+ require 'libis/format/tool/office_to_pdf'
6
6
  require 'libis/format/type_database'
7
7
 
8
8
  module Libis
@@ -38,7 +38,7 @@ module Libis
38
38
  def convert(source, target, format, opts = {})
39
39
  super
40
40
 
41
- return nil unless OfficeToPdf.run(source, target)
41
+ return nil unless Format::Tool::OfficeToPdf.run(source, target)
42
42
 
43
43
  target
44
44
 
@@ -3,9 +3,9 @@
3
3
  require_relative 'base'
4
4
 
5
5
  require 'libis/tools/extend/hash'
6
- require 'libis/format/pdf_copy'
7
- require 'libis/format/pdf_to_pdfa'
8
- require 'libis/format/pdf_optimizer'
6
+ require 'libis/format/tool/pdf_copy'
7
+ require 'libis/format/tool/pdf_to_pdfa'
8
+ require 'libis/format/tool/pdf_optimizer'
9
9
 
10
10
  module Libis
11
11
  module Format
@@ -126,7 +126,7 @@ module Libis
126
126
  def optimize_pdf(source, target, quality)
127
127
 
128
128
  using_temp(target) do |tmpname|
129
- result = Libis::Format::PdfOptimizer.run(source, tmpname, quality)
129
+ result = Libis::Format::Tool::PdfOptimizer.run(source, tmpname, quality)
130
130
  unless result[:status] == 0
131
131
  error("Pdf optimization encountered errors:\n%s", (result[:err] + result[:out]).join('\n'))
132
132
  next nil
@@ -138,7 +138,7 @@ module Libis
138
138
  def convert_pdf(source, target)
139
139
 
140
140
  using_temp(target) do |tmpname|
141
- result = Libis::Format::PdfCopy.run(
141
+ result = Libis::Format::Tool::PdfCopy.run(
142
142
  source, tmpname,
143
143
  @options.map { |k, v|
144
144
  if v.nil?
@@ -159,7 +159,7 @@ module Libis
159
159
  def pdf_to_pdfa(source, target)
160
160
 
161
161
  using_temp(target) do |tmpname|
162
- result = Libis::Format::PdfToPdfa.run source, tmpname
162
+ result = Libis::Format::Tool::PdfToPdfa.run source, tmpname
163
163
  unless result[:status] == 0
164
164
  error("Pdf/A conversion encountered errors:\n%s", result[:err].join('\n'))
165
165
  next nil
@@ -1,5 +1,5 @@
1
1
  require_relative 'base'
2
- require 'libis/format/ffmpeg'
2
+ require 'libis/format/tool/ffmpeg'
3
3
 
4
4
  require 'fileutils'
5
5
 
@@ -82,6 +82,49 @@ module Libis
82
82
  @options[:scale] = width_x_height
83
83
  end
84
84
 
85
+ # @param [String] file Image file path to use as watermark
86
+ def watermark_image(file)
87
+ @options[:watermark_image] = file
88
+ end
89
+
90
+ # @param [String] value text for watermark. No watermark if nil (default)
91
+ def watermark_text(value)
92
+ @options[:watermark_text] = value
93
+ end
94
+
95
+ # @param [Integer] value Font size for watermark text. Default: 10
96
+ # Note that the font is selected by the Config[:watermark_font] setting
97
+ def watermark_text_size(value)
98
+ @options[:watermark_text_size] = value.to_i
99
+ end
100
+
101
+ # @param [String] value Text color for the watermark text. Default: white
102
+ def watermark_text_color(value)
103
+ @options[:watermark_text_color] = value
104
+ end
105
+
106
+ # @param [String] value Text color for the watermark text shadow. Default: black
107
+ def watermark_text_shadow_color(value)
108
+ @options[:watermark_text_shadow_color] = value
109
+ end
110
+
111
+ # @param [Integer] value Offset of the watermark text shadow. Used for both x and y offset; default: 1
112
+ # If the offset is set to 0, no shadow will be printed
113
+ def watermark_text_shadow_offset(value)
114
+ @options[:watermark_text_offset] = value.to_i
115
+ end
116
+
117
+ # @param [String] value one of 'bottom_left' (default), 'top_left', 'bottom_right', 'top_right', 'center'
118
+ def watermark_position(value)
119
+ @options[:watermark_position] = value
120
+ end
121
+
122
+ # @param [Number] value watermark opacity (0-1) with 0 = invisible and 1 = 100% opaque. Default: 0.5
123
+ def watermark_opacity(value)
124
+ @options[:watermark_opacity] = value.to_f
125
+ end
126
+
127
+ # @param [Boolean] value If set to true automatically selects optimal format for web viewing. Default: false
85
128
  def web_stream(value)
86
129
  if value
87
130
  @options[:video_codec] = 'h264'
@@ -89,14 +132,17 @@ module Libis
89
132
  end
90
133
  end
91
134
 
135
+ # @param [String] name name of a preset. See FFMpeg documentation for more info
92
136
  def preset(name)
93
137
  @options[:preset] = name
94
138
  end
95
139
 
140
+ # @param [String] name name of an audio preset. See FFMpeg documentation for more info
96
141
  def audio_preset(name)
97
142
  @options[:audio_preset] = name
98
143
  end
99
144
 
145
+ # @param [String] name name of a video preset. See FFMpeg documentation for more info
100
146
  def video_preset(name)
101
147
  @options[:video_preset] = name
102
148
  end
@@ -163,6 +209,36 @@ module Libis
163
209
  opts = {global: [], input: [], filter: [], output: []}
164
210
  opts[:global] << '-hide_banner'
165
211
  opts[:global] << '-loglevel' << (@options[:quiet] ? 'fatal' : 'warning')
212
+
213
+ # Watermark info
214
+ @options[:watermark_opacity] ||= 0.5
215
+ if @options[:watermark_image]
216
+ opts[:filter] << '-i' << @options[:watermark_image] << '-filter_complex'
217
+ opts[:filter] << "[1:v]format=argb,colorchannelmixer=aa=%f[wm];[0:v][wm]overlay=%s" %
218
+ [@options[:watermark_opacity], watermark_position_text]
219
+ elsif @options[:watermark_text]
220
+ @options[:watermark_text_size] ||= 10
221
+ @options[:watermark_text_color] ||= 'white'
222
+ @options[:watermark_text_shadow_color] ||= 'black'
223
+ @options[:watermark_text_shadow_offset] ||= 1
224
+ filter_text = "drawtext=text='%s':%s:fontfile=%s:fontsize=%d:fontcolor=%s@%f" %
225
+ [
226
+ @options[:watermark_text],
227
+ watermark_position_text(true),
228
+ Config[:watermark_font],
229
+ @options[:watermark_text_size],
230
+ @options[:watermark_text_color],
231
+ @options[:watermark_opacity]
232
+ ]
233
+ filter_text += ':shadowcolor=%s@%f:shadowx=%d:shadowy=%d' %
234
+ [
235
+ @options[:watermark_text_shadow_color],
236
+ @options[:watermark_opacity],
237
+ @options[:watermark_text_shadow_offset],
238
+ @options[:watermark_text_shadow_offset]
239
+ ] if @options[:watermark_text_shadow_offset] > 0
240
+ opts[:filter] << '-vf' << filter_text
241
+ end
166
242
  opts[:output] << '-ac' << @options[:audio_channels] if @options[:audio_channels]
167
243
  opts[:output] << '-c:a' << @options[:audio_codec] if @options[:audio_codec]
168
244
  opts[:output] << '-c:v' << @options[:video_codec] if @options[:video_codec]
@@ -188,11 +264,29 @@ module Libis
188
264
  opts[:output] << '-pre' << @options[:preset] if @options[:preset]
189
265
  opts[:output] << '-apre' << @options[:audio_preset] if @options[:audio_preset]
190
266
  opts[:output] << '-vpre' << @options[:video_preset] if @options[:video_preset]
191
- result = Libis::Format::FFMpeg.run(source, target, opts)
267
+ info "FFMpeg options: #{opts}"
268
+ result = Libis::Format::Tool::FFMpeg.run(source, target, opts)
192
269
  info "FFMpeg output: #{result}"
193
270
  target
194
271
  end
195
272
 
273
+ def watermark_position_text(for_text = false, margin = 10)
274
+ w = for_text ? 'tw' : 'w'
275
+ h = for_text ? 'th' : 'h'
276
+ case @options[:watermark_position]
277
+ when 'bottom_left'
278
+ "x=#{margin}:y=H-#{h}-#{margin}"
279
+ when 'top_left'
280
+ "x=#{margin}:y=#{margin}"
281
+ when 'bottom_right'
282
+ "x=W-#{w}-#{margin}:y=H-#{h}-#{margin}"
283
+ when 'top_right'
284
+ "x=W-#{w}-#{margin}:y=#{margin}"
285
+ else
286
+ "x=#{margin}:y=H-#{h}-#{margin}"
287
+ end
288
+ end
289
+
196
290
  end
197
291
 
198
292
  end