libis-format 1.3.2 → 1.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/libis/format/converter/image_converter.rb +162 -70
- data/lib/libis/format/tool/pdf_merge.rb +54 -0
- data/lib/libis/format/tool/pdf_split.rb +20 -0
- data/lib/libis/format/version.rb +1 -1
- data/libis-format.gemspec +1 -1
- metadata +9 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5fb1b156976a67b10d6885880a0611ba8361671c24da8014e7e11d7840be6318
|
4
|
+
data.tar.gz: 1f5e6e9b1cd84031a5a1ae986a2d0de018bb021bb48d47d6d83c9feea1e8db59
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 364036443664fc6597d36456c554e25074926515c2b95c7475a93499a27389bc0a2d8749ba86f5cb29e47b50c41902780518b780abde202f0d69f2e3a550cf24
|
7
|
+
data.tar.gz: b7d5823c3da6b25a71b2d7c3a2b05a9b15042e562985775b357490ccadabc457e0784136c1e269030f7211c94e3926a2000857efa03472cb9ca05f013f25128c
|
@@ -9,10 +9,6 @@ require 'fileutils'
|
|
9
9
|
MiniMagick.logger.level = ::Logger::UNKNOWN
|
10
10
|
|
11
11
|
MiniMagick.configure do |config|
|
12
|
-
# config.cli = :graphicsmagick
|
13
|
-
config.validate_on_create = false
|
14
|
-
config.validate_on_write = false
|
15
|
-
config.whiny = false
|
16
12
|
config.tmpdir = Libis::Format::Config[:tempdir] || Dir.tmpdir
|
17
13
|
end
|
18
14
|
|
@@ -90,20 +86,15 @@ module Libis
|
|
90
86
|
|
91
87
|
# Create or use a watermark image.
|
92
88
|
#
|
93
|
-
# The watermark options are:
|
94
|
-
# - file: watermark image to use
|
89
|
+
# The watermark options are (use symbols):
|
95
90
|
# - text: text to create a watermark from
|
96
|
-
# -
|
97
|
-
# -
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
# - resize: fraction 0.0 - 1.0
|
104
|
-
# - gap: size of the gap between watermark instances. Fractions as percentage of widht/height. - default 0.2
|
105
|
-
# - opacity: opacity of the watermark (fraction 0.0 - 1.0) - default 0.1
|
106
|
-
# - gravity: center point of the overlay - default 'center'
|
91
|
+
# - file: watermark image to use
|
92
|
+
# - image: same as above
|
93
|
+
# - rotation: rotation of the watermark text (in degrees; integer number)
|
94
|
+
# - size: font size of the watermark text
|
95
|
+
# - opacity: opacity of the watermark (fraction 0.0 - 1.0)
|
96
|
+
# - gap: size of the gap between watermark instances. Integer value is absolute size in points (1/72 inch).
|
97
|
+
# Fractions are percentage of widht/height.
|
107
98
|
# If both options are given, the file will be used as-is if it exists and is a valid image file. Otherwise the
|
108
99
|
# file will be created or overwritten with a newly created watermark image.
|
109
100
|
#
|
@@ -111,44 +102,95 @@ module Libis
|
|
111
102
|
# slanted by 30 degrees counter-clockwise.
|
112
103
|
#
|
113
104
|
# @param [Hash] options Hash of options for watermark creation.
|
105
|
+
|
114
106
|
def watermark(options = {})
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
@wm_gap = ((options[:gap] || 0.2).to_f * 100).to_i
|
123
|
-
rotation = 360 - (options[:rotation] || 30).to_i
|
124
|
-
@wm_image = MiniMagick::Image.new(options[:file]) if options[:file]
|
125
|
-
return if @wm_image&.valid?
|
126
|
-
|
127
|
-
image = options[:file] || (Dir::Tmpname.create(%w[wm_image .png]) { |_| })
|
128
|
-
# noinspection RubyResolve
|
129
|
-
MiniMagick::Tool::Convert.new do |convert|
|
130
|
-
# noinspection RubyLiteralArrayInspection
|
131
|
-
convert.quiet
|
132
|
-
convert.background 'transparent'
|
133
|
-
convert.size('2000x2000')
|
134
|
-
convert.gravity 'Center'
|
135
|
-
convert.font('Helvetica').fill('black').pointsize(72) # .stroke('black').strokewidth(1)
|
136
|
-
convert << "label:#{text}"
|
137
|
-
convert.rotate rotation
|
138
|
-
convert.trim.repage.+ # rubocop:disable Lint/Void
|
139
|
-
convert << image
|
140
|
-
end
|
141
|
-
if options[:file]
|
142
|
-
@wm_image = MiniMagick::Image.new(image)
|
143
|
-
else
|
144
|
-
@wm_image = MiniMagick::Image.open(image)
|
145
|
-
File.delete(image)
|
107
|
+
options.key_strings_to_symbols!
|
108
|
+
if options[:file] || options[:image]
|
109
|
+
watermark_image(options)
|
110
|
+
elsif options[:text]
|
111
|
+
watermark_text(options)
|
112
|
+
elsif options[:banner]
|
113
|
+
watermark_banner(options)
|
146
114
|
end
|
147
|
-
|
148
|
-
return if @wm_image.valid?
|
115
|
+
end
|
149
116
|
|
150
|
-
|
151
|
-
|
117
|
+
# Use an image as watermark
|
118
|
+
#
|
119
|
+
# Next to the :file or :image option, this enables the following options:
|
120
|
+
# - tiles: number of tiles of the watermark - default 4
|
121
|
+
# 0: no tiling, so only 1 watermark will be placed with the original size
|
122
|
+
# 1: 1 tile, so the watermark will be scaled up to fill the image
|
123
|
+
# n > 1: minimum n tiles in both directions
|
124
|
+
# n < 0: tile without scaling the watermark
|
125
|
+
# - size: same as tiles - for backwards compatibility
|
126
|
+
# - resize: fraction 0.0 - 1.0
|
127
|
+
# - gap: size of the gap between watermark instances. Fractions as percentage of widht/height. - default 0.2
|
128
|
+
# - opacity: opacity of the watermark (fraction 0.0 - 1.0) - default 0.1
|
129
|
+
# - gravity: center point of the overlay - default 'center'
|
130
|
+
# - composition: algorithm to use to compose both images - default modulate
|
131
|
+
def watermark_image(options = {})
|
132
|
+
options.key_strings_to_symbols!
|
133
|
+
@options[:watermark] = {command: 'image'}
|
134
|
+
@options[:watermark][:data] = options[:file] || options[:image]
|
135
|
+
@options[:watermark][:tiles] = (options[:tiles] || options[:size] || 4).to_i
|
136
|
+
@options[:watermark][:resize] = ((options[:resize]).to_f * 100).to_i if options[:resize]
|
137
|
+
@options[:watermark][:gap] = ((options[:gap] || 0.2).to_f * 100).to_i
|
138
|
+
@options[:watermark][:opacity] = ((options[:opacity] || 0.1).to_f * 100).to_i
|
139
|
+
@options[:watermark][:gravity] = options[:gravity] || 'center'
|
140
|
+
@options[:watermark][:composition] = options[:composition] || 'modulate'
|
141
|
+
@options[:watermark][:rotation] = 360 - (options[:rotation] || 30).to_i
|
142
|
+
end
|
143
|
+
|
144
|
+
# Use text as watermark
|
145
|
+
#
|
146
|
+
# Next to the :text option, this enables the following options:
|
147
|
+
# - tiles: number of tiles of the watermark - default 4
|
148
|
+
# 0: no tiling, so only 1 watermark will be placed with the original size
|
149
|
+
# 1: 1 tile, so the watermark will be scaled up to fill the image
|
150
|
+
# n > 1: minimum n tiles in both directions
|
151
|
+
# n < 0: tile without scaling the watermark
|
152
|
+
# - size: same as tiles - for backwards compatibility
|
153
|
+
# - resize: fraction 0.0 - 1.0
|
154
|
+
# - gap: size of the gap between watermark instances. Fractions as percentage of widht/height. - default 0.2
|
155
|
+
# - opacity: opacity of the watermark (fraction 0.0 - 1.0) - default 0.1
|
156
|
+
# - gravity: center point of the overlay - default 'center'
|
157
|
+
# - composition: algorithm to use to compose both images - default modulate
|
158
|
+
# - rotation: rotation of the text
|
159
|
+
def watermark_text(options = {})
|
160
|
+
options.key_strings_to_symbols!
|
161
|
+
@options[:watermark] = {command: 'text'}
|
162
|
+
@options[:watermark][:data] = options[:text] || '© LIBIS'
|
163
|
+
@options[:watermark][:tiles] = (options[:tiles] || options[:size] || 4).to_i
|
164
|
+
@options[:watermark][:resize] = ((options[:resize]).to_f * 100).to_i if options[:resize]
|
165
|
+
@options[:watermark][:gap] = ((options[:gap] || 0.2).to_f * 100).to_i
|
166
|
+
@options[:watermark][:opacity] = ((options[:opacity] || 0.1).to_f * 100).to_i
|
167
|
+
@options[:watermark][:gravity] = options[:gravity] || 'center'
|
168
|
+
@options[:watermark][:composition] = options[:composition] || 'modulate'
|
169
|
+
@options[:watermark][:rotation] = 360 - (options[:rotation] || 30).to_i
|
170
|
+
end
|
171
|
+
|
172
|
+
# Create a vertical banner to the right side of each page
|
173
|
+
#
|
174
|
+
# The banner options are:
|
175
|
+
# - banner: text to put in the banner
|
176
|
+
# - add_filename: append filename to the text (use any value to enable)
|
177
|
+
# - fontsize: size of the font (in points) (default: autoscale)
|
178
|
+
# - width: width of the banner (default: 3% of image height). Not including a border of 30% of the banner width
|
179
|
+
# - background_color_(red|green|blue): color components of background (default: rgb(84,190,233))
|
180
|
+
# - text_color_(red|green|blue): color components of background (default: rgb(255,255,255))
|
181
|
+
def watermark_banner(options = {})
|
182
|
+
options.key_strings_to_symbols!
|
183
|
+
@options[:watermark] = {command: 'banner'}
|
184
|
+
@options[:watermark][:data] = options[:banner] || '© LIBIS'
|
185
|
+
@options[:watermark][:add_filename] = !!options[:add_filename]
|
186
|
+
@options[:watermark][:size] = options[:fontsize] if options[:fontsize]
|
187
|
+
@options[:watermark][:width] = options[:width] if options[:width]
|
188
|
+
@options[:watermark][:background_red] = options[:background_color_red] || 84
|
189
|
+
@options[:watermark][:background_green] = options[:background_color_green] || 190
|
190
|
+
@options[:watermark][:background_blue] = options[:background_color_blue] || 233
|
191
|
+
@options[:watermark][:text_red] = options[:text_color_red] || 255
|
192
|
+
@options[:watermark][:text_green] = options[:text_color_green] || 255
|
193
|
+
@options[:watermark][:text_blue] = options[:text_color_blue] || 255
|
152
194
|
end
|
153
195
|
|
154
196
|
def convert(source, target, format, opts = {})
|
@@ -195,7 +237,7 @@ module Libis
|
|
195
237
|
convert_image(path, converted.path, format)
|
196
238
|
list << converted
|
197
239
|
end
|
198
|
-
MiniMagick
|
240
|
+
MiniMagick.convert do |b|
|
199
241
|
b.append unless self.class.multipage?(format)
|
200
242
|
converted_pages.each { |page| b << page.path }
|
201
243
|
b << target
|
@@ -210,34 +252,84 @@ module Libis
|
|
210
252
|
|
211
253
|
def convert_image(source, target, format)
|
212
254
|
image_info = nil
|
213
|
-
image_info = MiniMagick::Image::Info.new(source) { |b| b.quiet } if @wm_image # rubocop:disable Style/SymbolProc
|
214
255
|
|
215
|
-
MiniMagick
|
256
|
+
MiniMagick.convert do |convert|
|
257
|
+
# Make converter silent
|
216
258
|
convert.quiet if @quiet
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
259
|
+
|
260
|
+
# Build watermark image in buffer
|
261
|
+
wm = @options.delete(:watermark)
|
262
|
+
if wm
|
263
|
+
image_info = MiniMagick::Image::Info.new(source) { |b| b.quiet }
|
264
|
+
case wm[:command]
|
265
|
+
when 'text'
|
266
|
+
convert.background 'transparent'
|
267
|
+
convert.size('2000x2000')
|
268
|
+
convert.gravity 'Center'
|
269
|
+
convert.font('Helvetica').fill('black').pointsize(72) # .stroke('black').strokewidth(1)
|
270
|
+
convert << "label:#{wm[:data]}"
|
271
|
+
convert.rotate wm[:rotation]
|
272
|
+
convert.trim.repage.+ # rubocop:disable Lint/Void
|
273
|
+
convert.bordercolor('transparent').border("#{wm[:gap]}%") if wm[:gap].positive?
|
274
|
+
convert.filter('Lagrange')
|
275
|
+
convert.resize("#{image_info['width'] / wm[:tiles]}x#{image_info['height'] / wm[:tiles]}") if wm[:tiles].positive?
|
276
|
+
convert.resize("#{wm[:resize]}%") if wm[:resize]
|
277
|
+
when 'image'
|
278
|
+
convert << wm[:data]
|
279
|
+
convert.background 'transparent'
|
280
|
+
convert.bordercolor('transparent').border("#{wm[:gap]}%") if wm[:gap].positive?
|
281
|
+
convert.rotate wm[:rotation]
|
282
|
+
convert.filter('Lagrange')
|
283
|
+
convert.resize("#{image_info['width'] / wm[:tiles]}x#{image_info['height'] / wm[:tiles]}") if wm[:tiles].positive?
|
284
|
+
convert.resize("#{wm[:resize]}%") if wm[:resize]
|
285
|
+
when 'banner'
|
286
|
+
banner_width = wm[:width] || [0.03 * image_info['height'], 20].max.round(0)
|
287
|
+
banner_border = banner_width / 3
|
288
|
+
convert.background "rgb(#{wm[:background_red]},#{wm[:background_green]},#{wm[:background_blue]})"
|
289
|
+
convert.size("#{image_info['height']}x#{banner_width}")
|
290
|
+
convert.bordercolor "rgb(#{wm[:background_red]},#{wm[:background_green]},#{wm[:background_blue]})"
|
291
|
+
convert.border "0x#{banner_border}"
|
292
|
+
convert.fill "rgb(#{wm[:text_red]},#{wm[:text_green]},#{wm[:text_blue]})"
|
293
|
+
convert.font "Liberation-Sans"
|
294
|
+
convert.pointsize wm[:size] if wm[:size]
|
295
|
+
convert.gravity 'Center'
|
296
|
+
convert << "label:#{wm[:data]}#{wm[:add_filename] ? File.basename(source, '.*') : ''}"
|
297
|
+
end
|
298
|
+
|
299
|
+
# Save watermark image to buffer
|
223
300
|
convert.write('mpr:watermark').delete.+
|
224
301
|
end
|
225
302
|
|
226
|
-
|
303
|
+
# load source image
|
227
304
|
convert << source
|
305
|
+
|
306
|
+
# force flatten image if necessary
|
228
307
|
convert.flatten if @options[:flatten].nil? && format == :JPG
|
229
|
-
|
230
|
-
|
308
|
+
|
309
|
+
# add watermark image
|
310
|
+
if wm
|
311
|
+
if wm[:command] == 'banner'
|
312
|
+
convert.rotate '-90'
|
231
313
|
convert << 'mpr:watermark'
|
314
|
+
convert.rotate '180'
|
315
|
+
convert.append
|
316
|
+
convert.rotate '-90'
|
232
317
|
else
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
stack
|
237
|
-
|
318
|
+
if (0..1).include? wm[:tiles]
|
319
|
+
convert << 'mpr:watermark'
|
320
|
+
else
|
321
|
+
convert.stack do |stack|
|
322
|
+
stack.size("#{image_info['width']}x#{image_info['height']}")
|
323
|
+
stack << 'xc:transparent'
|
324
|
+
stack.tile('mpr:watermark')
|
325
|
+
stack.draw "rectangle 0,0,#{image_info['width']},#{image_info['height']}"
|
326
|
+
end
|
327
|
+
convert.compose(wm[:composition])
|
328
|
+
convert.gravity(wm[:gravity])
|
329
|
+
convert.define("compose:args=#{wm[:opacity]}%")
|
330
|
+
convert.composite
|
238
331
|
end
|
239
332
|
end
|
240
|
-
convert.compose(@wm_composition).gravity(@wm_gravity).define("compose:args=#{@wm_opacity}%").composite
|
241
333
|
end
|
242
334
|
|
243
335
|
@flags.each { |f, v| v.is_a?(TrueClass) ? convert.send(f).+ : convert.send(f) }
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'os'
|
4
|
+
|
5
|
+
require 'libis/tools/extend/string'
|
6
|
+
require 'libis/tools/logger'
|
7
|
+
require 'libis/tools/command'
|
8
|
+
|
9
|
+
require 'libis/format/config'
|
10
|
+
|
11
|
+
module Libis
|
12
|
+
module Format
|
13
|
+
module Tool
|
14
|
+
class PdfMerge
|
15
|
+
include ::Libis::Tools::Logger
|
16
|
+
|
17
|
+
def self.installed?
|
18
|
+
result = Libis::Tools::Command.run(Libis::Format::Config[:java_cmd], '-version')
|
19
|
+
return false unless (result[:status]).zero?
|
20
|
+
|
21
|
+
File.exist?(Libis::Format::Config[:pdf_tool])
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.run(source, target, *options)
|
25
|
+
new.run source, target, options
|
26
|
+
end
|
27
|
+
|
28
|
+
def run(source, target, *options)
|
29
|
+
source = [source] unless source.is_a?(Array)
|
30
|
+
|
31
|
+
if OS.java?
|
32
|
+
# TODO: import library and execute in current VM. For now do exactly as in MRI.
|
33
|
+
end
|
34
|
+
|
35
|
+
timeout = Libis::Format::Config[:timeouts][:pdf_tool]
|
36
|
+
args = [
|
37
|
+
Libis::Format::Config[:java_cmd],
|
38
|
+
'-jar', Libis::Format::Config[:pdf_tool],
|
39
|
+
'merge',
|
40
|
+
'-o', target,
|
41
|
+
options,
|
42
|
+
source
|
43
|
+
].flatten
|
44
|
+
|
45
|
+
result = Libis::Tools::Command.run(*args, timeout: , kill_after: timeout * 2)
|
46
|
+
|
47
|
+
result[:err] << "#{self.class} took too long (> #{timeout} seconds) to complete" if result[:timeout]
|
48
|
+
|
49
|
+
result
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'libis/format/tool/pdf_tool'
|
4
|
+
|
5
|
+
module Libis
|
6
|
+
module Format
|
7
|
+
module Tool
|
8
|
+
class PdfSplit
|
9
|
+
|
10
|
+
def self.run(source, target, *options)
|
11
|
+
PdfTool.run('split', source, target, *options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def run(source, target, *options)
|
15
|
+
PdfTool.run('split', source, target, *options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/libis/format/version.rb
CHANGED
data/libis-format.gemspec
CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_runtime_dependency 'deep_dive', '~> 0.3'
|
30
30
|
spec.add_runtime_dependency 'libis-mapi', '~> 0.3'
|
31
31
|
spec.add_runtime_dependency 'libis-tools', '~> 1.1'
|
32
|
-
spec.add_runtime_dependency 'mini_magick', '~>
|
32
|
+
spec.add_runtime_dependency 'mini_magick', '~> 5.0.1'
|
33
33
|
spec.add_runtime_dependency 'naturally', '~> 2.2'
|
34
34
|
spec.add_runtime_dependency 'new_rfc_2047', '~> 1.0'
|
35
35
|
spec.add_runtime_dependency 'os', '~> 1.1'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: libis-format
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kris Dekeyser
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chromaprint
|
@@ -72,14 +72,14 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 5.0.1
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 5.0.1
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: naturally
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -281,7 +281,9 @@ files:
|
|
281
281
|
- lib/libis/format/tool/identification_tool.rb
|
282
282
|
- lib/libis/format/tool/msg_to_pdf.rb
|
283
283
|
- lib/libis/format/tool/office_to_pdf.rb
|
284
|
+
- lib/libis/format/tool/pdf_merge.rb
|
284
285
|
- lib/libis/format/tool/pdf_optimizer.rb
|
286
|
+
- lib/libis/format/tool/pdf_split.rb
|
285
287
|
- lib/libis/format/tool/pdf_to_pdfa.rb
|
286
288
|
- lib/libis/format/tool/pdf_tool.rb
|
287
289
|
- lib/libis/format/tool/pdfa_validator.rb
|
@@ -350,7 +352,7 @@ homepage: ''
|
|
350
352
|
licenses:
|
351
353
|
- MIT
|
352
354
|
metadata: {}
|
353
|
-
post_install_message:
|
355
|
+
post_install_message:
|
354
356
|
rdoc_options: []
|
355
357
|
require_paths:
|
356
358
|
- lib
|
@@ -366,7 +368,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
366
368
|
version: '0'
|
367
369
|
requirements: []
|
368
370
|
rubygems_version: 3.5.18
|
369
|
-
signing_key:
|
371
|
+
signing_key:
|
370
372
|
specification_version: 4
|
371
373
|
summary: LIBIS File format format services.
|
372
374
|
test_files: []
|