libis-format 1.0.2 → 2.0.1

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.
Files changed (236) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +5 -1
  3. data/.travis.yml +43 -25
  4. data/README.md +2 -2
  5. data/base/Dockerfile +35 -0
  6. data/base/Dockerfile.alpine +20 -0
  7. data/base/Dockerfile.rvm +56 -0
  8. data/base/rework_path +20 -0
  9. data/bin/libis_format +8 -0
  10. data/docker_cfg.yml +1 -0
  11. data/lib/libis/format.rb +12 -2
  12. data/lib/libis/format/cli/convert.rb +310 -0
  13. data/lib/libis/format/cli/format.rb +77 -0
  14. data/lib/libis/format/cli/prompt_helper.rb +87 -0
  15. data/lib/libis/format/cli/sub_command.rb +22 -0
  16. data/lib/libis/format/command_line.rb +25 -0
  17. data/lib/libis/format/config.rb +15 -10
  18. data/lib/libis/format/converter/audio_converter.rb +3 -37
  19. data/lib/libis/format/converter/base.rb +22 -8
  20. data/lib/libis/format/converter/chain.rb +3 -3
  21. data/lib/libis/format/converter/image_assembler.rb +82 -0
  22. data/lib/libis/format/converter/image_converter.rb +32 -127
  23. data/lib/libis/format/converter/image_splitter.rb +84 -0
  24. data/lib/libis/format/converter/image_watermarker.rb +261 -0
  25. data/lib/libis/format/converter/jp2_converter.rb +2 -2
  26. data/lib/libis/format/converter/office_converter.rb +2 -2
  27. data/lib/libis/format/converter/pdf_assembler.rb +66 -0
  28. data/lib/libis/format/converter/pdf_converter.rb +10 -134
  29. data/lib/libis/format/converter/pdf_metadata.rb +82 -0
  30. data/lib/libis/format/converter/pdf_optimizer.rb +67 -0
  31. data/lib/libis/format/converter/pdf_protecter.rb +147 -0
  32. data/lib/libis/format/converter/pdf_selecter.rb +77 -0
  33. data/lib/libis/format/converter/pdf_splitter.rb +70 -0
  34. data/lib/libis/format/converter/pdf_watermarker_header.rb +71 -0
  35. data/lib/libis/format/converter/pdf_watermarker_image.rb +76 -0
  36. data/lib/libis/format/converter/pdf_watermarker_text.rb +93 -0
  37. data/lib/libis/format/converter/spreadsheet_converter.rb +2 -2
  38. data/lib/libis/format/converter/video_converter.rb +1 -1
  39. data/lib/libis/format/identifier.rb +7 -7
  40. data/lib/libis/format/info.rb +27 -0
  41. data/lib/libis/format/library.rb +147 -0
  42. data/lib/libis/format/tool.rb +4 -1
  43. data/lib/libis/format/tool/droid.rb +2 -2
  44. data/lib/libis/format/tool/extension_identification.rb +4 -4
  45. data/lib/libis/format/tool/ffmpeg.rb +1 -1
  46. data/lib/libis/format/tool/fido.rb +1 -1
  47. data/lib/libis/format/tool/fop_pdf.rb +1 -1
  48. data/lib/libis/format/tool/identification_tool.rb +6 -6
  49. data/lib/libis/format/tool/office_to_pdf.rb +1 -1
  50. data/lib/libis/format/tool/pdf_merge.rb +4 -4
  51. data/lib/libis/format/tool/{pdf_copy.rb → pdf_metadata.rb} +6 -6
  52. data/lib/libis/format/tool/pdf_protect.rb +47 -0
  53. data/lib/libis/format/tool/pdf_select.rb +47 -0
  54. data/lib/libis/format/tool/pdf_split.rb +5 -5
  55. data/lib/libis/format/tool/pdf_to_pdfa.rb +1 -2
  56. data/lib/libis/format/tool/pdf_watermark.rb +47 -0
  57. data/lib/libis/format/tool/pdfa_validator.rb +3 -4
  58. data/lib/libis/format/tool/spreadsheet_to_ods.rb +2 -1
  59. data/lib/libis/format/version.rb +1 -1
  60. data/lib/libis/format/yaml_loader.rb +71 -0
  61. data/libis-format.gemspec +5 -5
  62. data/tools/PdfTool.jar +0 -0
  63. data/tools/bcpkix-jdk15on-167.jar +0 -0
  64. data/tools/bcprov-jdk15on-167.jar +0 -0
  65. data/tools/fop/build/fop.jar +0 -0
  66. data/tools/fop/conf/fop.xconf +466 -0
  67. data/tools/fop/fop +258 -0
  68. data/tools/fop/fop.bat +75 -0
  69. data/tools/fop/fop.cmd +31 -0
  70. data/tools/fop/fop.js +341 -0
  71. data/tools/fop/lib/README.txt +243 -0
  72. data/tools/fop/lib/avalon-framework-api-4.3.1.jar +0 -0
  73. data/tools/fop/lib/avalon-framework-impl-4.3.1.jar +0 -0
  74. data/tools/fop/lib/avalon-framework.LICENSE.txt +175 -0
  75. data/tools/fop/lib/avalon-framework.NOTICE.TXT +11 -0
  76. data/tools/fop/lib/batik-all-1.10.jar +0 -0
  77. data/tools/fop/lib/batik.LICENSE.txt +201 -0
  78. data/tools/fop/lib/batik.NOTICE.txt +18 -0
  79. data/tools/fop/lib/commons-io-1.3.1.jar +0 -0
  80. data/tools/fop/lib/commons-io.LICENSE.txt +203 -0
  81. data/tools/fop/lib/commons-io.NOTICE.txt +6 -0
  82. data/tools/fop/lib/commons-logging-1.0.4.jar +0 -0
  83. data/tools/fop/lib/commons-logging.LICENSE.txt +202 -0
  84. data/tools/fop/lib/commons-logging.NOTICE.txt +3 -0
  85. data/tools/fop/lib/fontbox-2.0.7.jar +0 -0
  86. data/tools/fop/lib/serializer-2.7.2.jar +0 -0
  87. data/tools/fop/lib/serializer.LICENSE.txt +201 -0
  88. data/tools/fop/lib/serializer.NOTICE.txt +15 -0
  89. data/tools/fop/lib/xalan-2.7.2.jar +0 -0
  90. data/tools/fop/lib/xalan.BCEL.LICENSE.txt +52 -0
  91. data/tools/fop/lib/xalan.LICENSE.txt +202 -0
  92. data/tools/fop/lib/xalan.NOTICE.txt +44 -0
  93. data/tools/fop/lib/xalan.regexp.LICENSE.txt +52 -0
  94. data/tools/fop/lib/xalan.runtime.LICENSE.txt +20 -0
  95. data/tools/fop/lib/xerces.LICENSE.txt +56 -0
  96. data/tools/fop/lib/xercesImpl-2.9.1.jar +0 -0
  97. data/tools/fop/lib/xercesImpl.LICENSE.txt +201 -0
  98. data/tools/fop/lib/xercesImpl.NOTICE.txt +14 -0
  99. data/tools/fop/lib/xml-apis-1.3.04.jar +0 -0
  100. data/tools/fop/lib/xml-apis-ext-1.3.04.jar +0 -0
  101. data/tools/fop/lib/xml-apis-ext.LICENSE.dom-documentation.txt +73 -0
  102. data/tools/fop/lib/xml-apis-ext.LICENSE.dom-software.txt +61 -0
  103. data/tools/fop/lib/xml-apis-ext.LICENSE.sac.html +75 -0
  104. data/tools/fop/lib/xml-apis-ext.LICENSE.txt +202 -0
  105. data/tools/fop/lib/xml-apis-ext.NOTICE.txt +16 -0
  106. data/tools/fop/lib/xml-apis-ext.README.dom.txt +56 -0
  107. data/tools/fop/lib/xml-apis.LICENSE-SAX.html +17 -0
  108. data/tools/fop/lib/xml-apis.LICENSE.DOM-documentation.html +74 -0
  109. data/tools/fop/lib/xml-apis.LICENSE.DOM-software.html +66 -0
  110. data/tools/fop/lib/xml-apis.LICENSE.txt +201 -0
  111. data/tools/fop/lib/xml-apis.NOTICE.txt +13 -0
  112. data/tools/fop/lib/xmlgraphics-commons-2.3.jar +0 -0
  113. data/tools/fop/lib/xmlgraphics-commons.LICENSE.txt +202 -0
  114. data/tools/fop/lib/xmlgraphics-commons.NOTICE.txt +5 -0
  115. data/tools/pdfbox/pdfbox-app-2.0.13.jar +0 -0
  116. data/tools/pdfbox/{pdfbox-app-1.8.10.jar → preflight-app-2.0.13.jar} +0 -0
  117. metadata +93 -259
  118. data/lib/libis/format/type_database.rb +0 -201
  119. data/spec/converter_audio_spec.rb +0 -66
  120. data/spec/converter_fop_spec.rb +0 -37
  121. data/spec/converter_image_spec.rb +0 -166
  122. data/spec/converter_office_spec.rb +0 -84
  123. data/spec/converter_pdf_spec.rb +0 -30
  124. data/spec/converter_repository_spec.rb +0 -97
  125. data/spec/converter_spreadsheet_spec.rb +0 -39
  126. data/spec/converter_video_spec.rb +0 -97
  127. data/spec/converter_xsl_spec.rb +0 -56
  128. data/spec/data/Cevennes2.bmp +0 -0
  129. data/spec/data/Cevennes2.jp2 +0 -0
  130. data/spec/data/Cevennes2.ppm +0 -22492
  131. data/spec/data/NikonRaw-CameraRaw.TIF +0 -0
  132. data/spec/data/NikonRaw-CaptureOne.tif +0 -0
  133. data/spec/data/audio/carlin_disappointed.aac +0 -0
  134. data/spec/data/audio/carlin_disappointed.ac3 +0 -0
  135. data/spec/data/audio/carlin_disappointed.aiff +0 -0
  136. data/spec/data/audio/carlin_disappointed.au +0 -0
  137. data/spec/data/audio/carlin_disappointed.flac +0 -0
  138. data/spec/data/audio/carlin_disappointed.m4a +0 -0
  139. data/spec/data/audio/carlin_disappointed.mka +0 -0
  140. data/spec/data/audio/carlin_disappointed.mp3 +0 -0
  141. data/spec/data/audio/carlin_disappointed.ogg +0 -0
  142. data/spec/data/audio/carlin_disappointed.ra +0 -0
  143. data/spec/data/audio/carlin_disappointed.voc +0 -0
  144. data/spec/data/audio/carlin_disappointed.wav +0 -0
  145. data/spec/data/audio/carlin_disappointed.wma +0 -0
  146. data/spec/data/audio/greensleeves.aac +0 -0
  147. data/spec/data/audio/greensleeves.ac3 +0 -0
  148. data/spec/data/audio/greensleeves.aiff +0 -0
  149. data/spec/data/audio/greensleeves.au +0 -0
  150. data/spec/data/audio/greensleeves.flac +0 -0
  151. data/spec/data/audio/greensleeves.m4a +0 -0
  152. data/spec/data/audio/greensleeves.mka +0 -0
  153. data/spec/data/audio/greensleeves.mp3 +0 -0
  154. data/spec/data/audio/greensleeves.ogg +0 -0
  155. data/spec/data/audio/greensleeves.ra +0 -0
  156. data/spec/data/audio/greensleeves.voc +0 -0
  157. data/spec/data/audio/greensleeves.wav +0 -0
  158. data/spec/data/audio/greensleeves.wma +0 -0
  159. data/spec/data/audio/king_nonviolence.aac +0 -0
  160. data/spec/data/audio/king_nonviolence.ac3 +0 -0
  161. data/spec/data/audio/king_nonviolence.aiff +0 -0
  162. data/spec/data/audio/king_nonviolence.au +0 -0
  163. data/spec/data/audio/king_nonviolence.flac +0 -0
  164. data/spec/data/audio/king_nonviolence.m4a +0 -0
  165. data/spec/data/audio/king_nonviolence.mka +0 -0
  166. data/spec/data/audio/king_nonviolence.mp3 +0 -0
  167. data/spec/data/audio/king_nonviolence.ogg +0 -0
  168. data/spec/data/audio/king_nonviolence.ra +0 -0
  169. data/spec/data/audio/king_nonviolence.voc +0 -0
  170. data/spec/data/audio/king_nonviolence.wav +0 -0
  171. data/spec/data/audio/king_nonviolence.wma +0 -0
  172. data/spec/data/audio/top_gun_secret.aac +0 -0
  173. data/spec/data/audio/top_gun_secret.ac3 +0 -0
  174. data/spec/data/audio/top_gun_secret.aiff +0 -0
  175. data/spec/data/audio/top_gun_secret.au +0 -0
  176. data/spec/data/audio/top_gun_secret.flac +0 -0
  177. data/spec/data/audio/top_gun_secret.m4a +0 -0
  178. data/spec/data/audio/top_gun_secret.mka +0 -0
  179. data/spec/data/audio/top_gun_secret.mp3 +0 -0
  180. data/spec/data/audio/top_gun_secret.ogg +0 -0
  181. data/spec/data/audio/top_gun_secret.ra +0 -0
  182. data/spec/data/audio/top_gun_secret.voc +0 -0
  183. data/spec/data/audio/top_gun_secret.wav +0 -0
  184. data/spec/data/audio/top_gun_secret.wma +0 -0
  185. data/spec/data/multipage.tif +0 -0
  186. data/spec/data/multipage.tif.jp2 +0 -0
  187. data/spec/data/test-ead.xml +0 -392
  188. data/spec/data/test-jpg.tif +0 -0
  189. data/spec/data/test-lzw.tif +0 -0
  190. data/spec/data/test-options.jpg +0 -0
  191. data/spec/data/test-options.png +0 -0
  192. data/spec/data/test.bmp +0 -0
  193. data/spec/data/test.doc +0 -0
  194. data/spec/data/test.docx +0 -0
  195. data/spec/data/test.gif +0 -0
  196. data/spec/data/test.jpg +0 -0
  197. data/spec/data/test.ods +0 -0
  198. data/spec/data/test.odt +0 -0
  199. data/spec/data/test.pdf +0 -0
  200. data/spec/data/test.pdf.tif +0 -0
  201. data/spec/data/test.png +0 -0
  202. data/spec/data/test.ps +0 -8631
  203. data/spec/data/test.psd +0 -0
  204. data/spec/data/test.rtf +0 -1455
  205. data/spec/data/test.tif +0 -0
  206. data/spec/data/test.txt +0 -12
  207. data/spec/data/test.xcf +0 -0
  208. data/spec/data/test.xls +0 -0
  209. data/spec/data/test.xlsx +0 -0
  210. data/spec/data/test.xml +0 -4
  211. data/spec/data/test_pdfa.pdf +0 -0
  212. data/spec/data/video/SampleVideo_1080x720_2mb.flv +0 -0
  213. data/spec/data/video/SampleVideo_1080x720_2mb.mkv +0 -0
  214. data/spec/data/video/SampleVideo_1080x720_2mb.mp4 +0 -0
  215. data/spec/data/video/SampleVideo_176x144_2mb.3gp +0 -0
  216. data/spec/data/video/SampleVideo_320x240_2mb.3gp +0 -0
  217. data/spec/data/video/SampleVideo_360x240_2mb.flv +0 -0
  218. data/spec/data/video/SampleVideo_360x240_2mb.mkv +0 -0
  219. data/spec/data/video/SampleVideo_360x240_2mb.mp4 +0 -0
  220. data/spec/data/video/copyright.png +0 -0
  221. data/spec/data/xml/134476_ead.XML +0 -1
  222. data/spec/data/xml/134476_ead.pdf +0 -0
  223. data/spec/data/xml/134476_fo.XML +0 -383
  224. data/spec/data/xml/134476_raw.XML +0 -141
  225. data/spec/data/xml/ead2fo_pdf.xsl +0 -1453
  226. data/spec/data/xml/header_nolink_pdf.xsl +0 -120
  227. data/spec/data/xml/lookupLists.xsl +0 -488
  228. data/spec/data/xml/scope_eadToHTML.xsl +0 -2376
  229. data/spec/data/xml/scope_xmlToEAD_dom.xsl +0 -952
  230. data/spec/identifier_spec.rb +0 -161
  231. data/spec/spec_helper.rb +0 -58
  232. data/spec/test_types.yml +0 -12
  233. data/spec/type_database_spec.rb +0 -140
  234. data/tools/bcpkix-jdk15on-1.49.jar +0 -0
  235. data/tools/bcprov-jdk15on-1.49.jar +0 -0
  236. data/tools/pdfbox/preflight-app-1.8.10.jar +0 -0
@@ -4,28 +4,29 @@ require_relative 'base'
4
4
  require 'libis/format/identifier'
5
5
 
6
6
  require 'mini_magick'
7
- require 'fileutils'
8
7
 
9
- MiniMagick.logger.level = ::Logger::ERROR
8
+ MiniMagick.logger.level = ::Logger::UNKNOWN
10
9
 
11
10
  MiniMagick.configure do |config|
12
11
  # config.cli = :graphicsmagick
13
12
  config.validate_on_create = false
14
13
  config.validate_on_write = false
14
+ config.whiny = false
15
15
  end
16
16
 
17
17
  module Libis
18
18
  module Format
19
19
  module Converter
20
20
 
21
+ # noinspection RubyTooManyInstanceVariablesInspection
21
22
  class ImageConverter < Libis::Format::Converter::Base
22
23
 
23
24
  def self.input_types
24
- [:TIFF, :JPG, :PNG, :BMP, :GIF, :PDF, :JP2]
25
+ [:TIFF, :JPG, :PNG, :BMP, :GIF, :PDF, :JP2, :PBM, :PGM, :PPM]
25
26
  end
26
27
 
27
28
  def self.output_types(format = nil)
28
- return [] unless input_types.include?(format)
29
+ return [] unless input_types.include?(format) if format
29
30
  [:TIFF, :JPG, :PNG, :BMP, :GIF, :PDF, :JP2]
30
31
  end
31
32
 
@@ -43,101 +44,58 @@ module Libis
43
44
  end
44
45
 
45
46
  def quiet(v)
46
- @flags[:quiet] = !!v
47
+ @quiet = !!v
48
+ self
47
49
  end
48
50
 
49
51
  def page(nr)
50
52
  @page = nr
53
+ self
51
54
  end
52
55
 
53
56
  def scale(percent)
54
57
  @options[:scale] = percent
58
+ self
55
59
  end
56
60
 
57
61
  def resize(geometry)
58
62
  @options[:resize] = geometry
63
+ self
59
64
  end
60
65
 
61
66
  def quality(value)
62
67
  @options[:quality] = value
68
+ self
63
69
  end
64
70
 
65
71
  def dpi(value)
66
72
  @options[:density] = value
73
+ self
67
74
  end
68
75
 
69
76
  def resample(value)
70
77
  @options[:resample] = value
78
+ self
71
79
  end
72
80
 
73
- def flatten
74
- @flags[:flatten] = true
81
+ def flatten(value = true)
82
+ @options[:flatten] = value
83
+ self
75
84
  end
76
85
 
77
86
  def colorspace(value)
78
87
  @options[:colorspace] = value
88
+ self
79
89
  end
80
90
 
81
- def delete_date
82
- @delete_date = true
91
+ def delete_date(value = true)
92
+ @delete_date = value
93
+ self
83
94
  end
84
95
 
85
96
  def profile(icc)
86
97
  @profile = icc
87
- end
88
-
89
- # Create or use a watermark image.
90
- #
91
- # The watermark options are:
92
- # - file: watermark image to use
93
- # - text: text to create a watermark from
94
- # - rotation: rotation of the watermark text (counter clockwise in degrees; integer number) - default 30
95
- # - size: size of the watermark (integer > 0, 1/n of image size) - default 4
96
- # - opacity: opacity of the watermark (fraction 0.0 - 1.0) - default 0.3
97
- # - gap: size of the gap between watermark instances. Fractions as percentage of widht/height. - default 0.2
98
- # If both options are given, the file will be used as-is if it exists and is a valid image file. Otherwise the
99
- # file will be created or overwritten with a newly created watermark image.
100
- #
101
- # The created watermark file will be a PNG image with transparent background containing the supplied text
102
- # slanted by 30 degrees counter-clockwise.
103
- #
104
- # @param [Hash] options Hash of options for watermark creation.
105
- def watermark(options = {})
106
- text = options[:text] || '© LIBIS'
107
- @wm_size = (options[:size] || '4').to_i
108
- @wm_opacity = ((options[:opacity] || 0.1).to_f * 100).to_i
109
- @wm_composition = options[:composition] || 'modulate'
110
- gap = ((options[:gap] || 0.2).to_f * 100).to_i
111
- rotation = 360 - (options[:rotation] || 30).to_i
112
- @wm_image = MiniMagick::Image.new(options[:file]) if options[:file]
113
- unless @wm_image && @wm_image.valid?
114
- image = options[:file] || (Dir::Tmpname.create(%w(wm_image .png)) { |_|})
115
- # noinspection RubyResolve
116
- MiniMagick::Tool::Convert.new do |convert|
117
- # noinspection RubyLiteralArrayInspection
118
- convert.quiet
119
- convert.background 'transparent'
120
- convert.size('2000x2000')
121
- convert.gravity 'Center'
122
- convert.font('Helvetica').fill('black').pointsize(72) #.stroke('black').strokewidth(1)
123
- convert << "label:#{text}"
124
- convert.rotate rotation
125
- convert.trim.repage.+
126
- convert.bordercolor('transparent').border("#{gap}%")
127
- convert << image
128
- end
129
- if options[:file]
130
- @wm_image = MiniMagick::Image.new(image)
131
- else
132
- @wm_image = MiniMagick::Image.open(image)
133
- File.delete(image)
134
- end
135
- # noinspection RubyResolve
136
- unless @wm_image.valid?
137
- error "Problem creating watermark image '#{image}'."
138
- @wm_image = nil
139
- end
140
- end
98
+ self
141
99
  end
142
100
 
143
101
  def convert(source, target, format, opts = {})
@@ -145,81 +103,26 @@ module Libis
145
103
 
146
104
  FileUtils.mkpath(File.dirname(target))
147
105
 
148
- if source.is_a? Array
149
-
150
- assemble_and_convert(source, target, format)
151
-
152
- elsif File.directory?(source)
153
- source_list = Dir[File.join(source, '**', '*')].reject { |p| File.directory? p }
154
-
155
- assemble_and_convert(source_list, target, format)
156
-
157
- else
158
-
159
- image = MiniMagick::Image.new(source)
160
-
161
- if image.pages.size > 1
162
- if @page
163
- convert_image(image.pages[@page].path, target, format)
164
- else
165
- assemble_and_convert(image.pages.map { |page| page.path }, target, format)
166
- end
167
- else
168
- convert_image(source, target, format)
169
- end
170
- end
106
+ convert_image(source, target, format)
171
107
 
172
108
  target
173
109
 
174
110
  end
175
111
 
176
- def assemble_and_convert(sources, target, format)
177
-
178
- warn 'Received multiple images as input and single page format as target.' unless self.class.multipage?(format)
179
- converted_pages = sources.inject([]) do |list, path|
180
- converted = Tempfile.new(['page-', ".#{Libis::Format::TypeDatabase.type_extentions(format).first}"])
181
- convert_image(path, converted.path, format)
182
- list << converted
183
- end
184
- MiniMagick::Tool::Convert.new do |b|
185
- b.append unless self.class.multipage?(format)
186
- converted_pages.each { |page| b << page.path }
187
- b << target
188
- end
189
- converted_pages.each do |temp_file|
190
- temp_file.close
191
- temp_file.unlink
192
- end
193
- end
194
-
195
112
  protected
196
113
 
197
114
  def convert_image(source, target, format)
198
115
 
199
- image_info = nil
200
- image_info = MiniMagick::Image::Info.new(source) if @wm_image
116
+ if @page
117
+ image = MiniMagick::Image.open(source) { |b| b.quiet }
118
+ source = image.pages[@page].path if image.pages.size > 1
119
+ end
201
120
 
202
121
  MiniMagick::Tool::Convert.new do |convert|
203
- if @wm_image
204
- convert << @wm_image.path
205
- convert.filter('Lagrange')
206
- convert.resize("#{image_info['width'] / @wm_size}x#{image_info['height'] / @wm_size}").write('mpr:watermark').delete.+
207
- end
208
-
122
+ convert.quiet if @quiet
209
123
  convert << source
210
- convert.flatten if format == :JPG
211
- if @wm_image
212
- # noinspection RubyResolve
213
- convert.stack do |stack|
214
- stack.size("#{image_info['width']}x#{image_info['height']}")
215
- stack << 'xc:transparent'
216
- stack.tile('mpr:watermark')
217
- stack.draw "rectangle 0,0,#{image_info['width']},#{image_info['height']}"
218
- end
219
- convert.compose(@wm_composition).define("compose:args=#{@wm_opacity}").composite
220
- end
221
-
222
- @flags.each { |f, v| v.is_a?(FalseClass) ? convert.send(f).+ : convert.send(f) }
124
+ convert.flatten if @options[:flatten].nil? && format == :JPG
125
+ @flags.each {|f, v| v.is_a?(TrueClass) ? convert.send(f).+ : convert.send(f)}
223
126
  if @delete_date
224
127
  convert << '+set' << 'modify-date' << '+set' << 'create-date'
225
128
  end
@@ -227,13 +130,15 @@ module Libis
227
130
  colorspace = @options.delete(:colorspace) || 'sRGB'
228
131
  unless @options.empty?
229
132
  convert.colorspace('RGB')
230
- @options.each { |o, v| convert.send(o, v) }
133
+ @options.each {|o, v| convert.send(o, v)}
231
134
  end
232
135
  convert.colorspace(colorspace)
233
136
  convert.profile @profile if @profile
234
137
 
235
138
  convert.format(format)
236
139
  convert << target
140
+
141
+ debug "ImageMagick command: '#{convert.command.join(' ')}'"
237
142
  end
238
143
 
239
144
  target
@@ -0,0 +1,84 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative 'base'
4
+ require 'libis/format/identifier'
5
+
6
+ require 'mini_magick'
7
+
8
+ MiniMagick.logger.level = ::Logger::UNKNOWN
9
+
10
+ MiniMagick.configure do |config|
11
+ # config.cli = :graphicsmagick
12
+ config.validate_on_create = false
13
+ config.validate_on_write = false
14
+ config.whiny = false
15
+ end
16
+
17
+ module Libis
18
+ module Format
19
+ module Converter
20
+
21
+ class ImageSplitter < Libis::Format::Converter::Base
22
+
23
+ def self.input_types
24
+ [:PDF, :TIFF, :GIF, :PBM, :PGM, :PPM]
25
+ end
26
+
27
+ def self.output_types(format = nil)
28
+ return [] unless input_types.include?(format) if format
29
+ [:TIFF, :JPG, :PNG, :BMP, :GIF, :PDF, :JP2]
30
+ end
31
+
32
+ def self.multipage?(format)
33
+ [:PDF, :TIFF, :GIF, :PBM, :PGM, :PPM].include?(format)
34
+ end
35
+
36
+ def self.category
37
+ :splitter
38
+ end
39
+
40
+ def image_split(_)
41
+ #force usage of this converter
42
+ end
43
+
44
+ def quiet(v)
45
+ @quiet = !!v
46
+ end
47
+
48
+ def convert(source, target, format, opts = {})
49
+ super
50
+
51
+ FileUtils.mkpath(File.dirname(target))
52
+
53
+ if self.class.multipage?(format)
54
+ target = File.join(File.dirname(target), "#{File.basename(target, '.*')}-%d#{File.extname(target)}")
55
+ end
56
+
57
+ result = split_image(source, target, format)
58
+ return nil unless result
59
+ target
60
+
61
+ end
62
+
63
+ private
64
+
65
+ def split_image(source, target, format)
66
+
67
+ MiniMagick::Tool::Convert.new do |convert|
68
+ convert.quiet if @quiet
69
+ convert << source
70
+ convert.format(format)
71
+ convert << target
72
+
73
+ debug "ImageMagick command: '#{convert.command.join(' ')}'"
74
+ end
75
+
76
+ target
77
+
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,261 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative 'base'
4
+ require 'libis/format/identifier'
5
+
6
+ require 'mini_magick'
7
+ # noinspection RubyResolve
8
+ require 'fileutils'
9
+
10
+ MiniMagick.logger.level = ::Logger::UNKNOWN
11
+
12
+ MiniMagick.configure do |config|
13
+ # config.cli = :graphicsmagick
14
+ config.validate_on_create = false
15
+ config.validate_on_write = false
16
+ config.whiny = false
17
+ end
18
+
19
+ module Libis
20
+ module Format
21
+ module Converter
22
+
23
+ # noinspection RubyTooManyInstanceVariablesInspection
24
+ class ImageWatermarker < Libis::Format::Converter::Base
25
+
26
+ def self.input_types
27
+ [:TIFF, :JPG, :PNG, :BMP, :GIF, :PDF, :JP2]
28
+ end
29
+
30
+ def self.output_types(format = nil)
31
+ return [] unless input_types.include?(format) if format
32
+ [format]
33
+ end
34
+
35
+ def self.multipage?(format)
36
+ [:PDF, :TIFF, :GIF, :PBM, :PGM, :PPM].include?(format)
37
+ end
38
+
39
+ def initialize
40
+ super
41
+ @quiet = true
42
+ @wm_image = nil
43
+ @wm_file = nil
44
+ @wm_text = '© LIBIS'
45
+ @wm_tiles = 4
46
+ @wm_resize = nil
47
+ @wm_gap = 20
48
+ @wm_gravity = 'Center'
49
+ @wm_rotation = 30
50
+ @wm_composition ='modulate'
51
+ @wm_composition_args = '10'
52
+ end
53
+
54
+ def image_watermark(_)
55
+ #force usage of this converter
56
+ self
57
+ end
58
+
59
+ def quiet(v)
60
+ @quiet = !!v
61
+ self
62
+ end
63
+
64
+ def page(v)
65
+ @page = v.to_i
66
+ self
67
+ end
68
+
69
+ # watermark image to use
70
+ def file(v)
71
+ @wm_file = v.blank? ? nil : v
72
+ self
73
+ end
74
+
75
+ # text to create a watermark from
76
+ def text(v)
77
+ @wm_text = v.blank? ? nil : v
78
+ self
79
+ end
80
+
81
+ # rotation of the watermark text (counter clockwise in degrees; integer number)
82
+ # default 30
83
+ def rotation(v)
84
+ @wm_rotation = v.to_i
85
+ self
86
+ end
87
+
88
+ # number of tiles of the watermark
89
+ # default 4
90
+ # 0: no tiling, so only 1 watermark will be placed with the original size
91
+ # 1: 1 tile, so the watermark will be scaled up to fill the image
92
+ # n > 1: minimum n tiles in both directions
93
+ # n < 0: tile without scaling the watermark
94
+ def tiles(v)
95
+ @wm_tiles = v.to_i
96
+ self
97
+ end
98
+
99
+ # fraction 0.0 - 1.0
100
+ def resize(v)
101
+ @wm_resize = (v.to_f * 100).to_i
102
+ self
103
+ end
104
+
105
+ # size of the gap between watermark instances. Fractions as percentage of widht/height
106
+ # default 0.2
107
+ def gap(v)
108
+ @wm_gap = (v.to_f * 100).to_i
109
+ self
110
+ end
111
+
112
+ # center point for the watermark overlay
113
+ # default 'center'
114
+ def gravity(v)
115
+ @wm_gravity = v.blank? ? nil : v
116
+ self
117
+ end
118
+
119
+ # the image composition method for merging the watermark image
120
+ # default 'modulate'
121
+ # See https://imagemagick.org/script/compose.php for more information
122
+ def composition(v)
123
+ @wm_composition = v.blank? ? nil : v
124
+ self
125
+ end
126
+
127
+ # arguments for the composition method
128
+ # default '10'
129
+ # See https://imagemagick.org/script/compose.php for more information
130
+ def composition_args(v)
131
+ @wm_composition_args = v.blank? ? nil : v
132
+ self
133
+ end
134
+
135
+
136
+ def convert(source, target, format, opts = {})
137
+ super
138
+
139
+ FileUtils.mkpath(File.dirname(target))
140
+
141
+ if source.is_a?(Array) || File.directory?(source)
142
+ error 'Only a single image file is allowed for input'
143
+ else
144
+ image = MiniMagick::Image.open(source) { |b| b.quiet }
145
+
146
+ if image.pages.size > 1
147
+ if @page
148
+ convert_image(image.pages[@page].path, target, format)
149
+ else
150
+ error 'multipage input file detecte; you need to supply a page number'
151
+ end
152
+ else
153
+ convert_image(source, target, format)
154
+ end
155
+ end
156
+
157
+ target
158
+
159
+ end
160
+
161
+ protected
162
+
163
+ # noinspection DuplicatedCode
164
+ def convert_image(source, target, format)
165
+
166
+ wm_image = watermark_image
167
+ return nil unless wm_image
168
+ image_info = MiniMagick::Image::Info.new(source) {|b| b.quiet}
169
+
170
+ MiniMagick::Tool::Convert.new do |convert|
171
+ convert.quiet if @quiet
172
+
173
+ # adapt watermark image to tile size and apply gap and resize if necessary
174
+ convert << @wm_image.path
175
+ # noinspection RubyResolve
176
+ convert.bordercolor('transparent').border("#{@wm_gap}%") if @wm_gap > 0
177
+ convert.filter('Lagrange')
178
+ convert.resize("#{image_info['width'] / @wm_tiles}x#{image_info['height'] / @wm_tiles}") if @wm_tiles > 0
179
+ convert.resize("#{@wm_resize}%") if @wm_resize
180
+ convert.write('mpr:watermark').delete.+
181
+
182
+ # convert the source image
183
+ convert << source
184
+ if @wm_tiles >= 0 and @wm_tiles <= 1
185
+ # only 1 watermark required (tiles = 0/1 => scaled no/yes)
186
+ convert << 'mpr:watermark'
187
+ else
188
+ # fill the image size with a pattern of the watermark image
189
+ convert.stack do |stack|
190
+ stack.size("#{image_info['width']}x#{image_info['height']}")
191
+ stack << 'xc:transparent'
192
+ # noinspection RubyResolve
193
+ stack.tile('mpr:watermark')
194
+ # noinspection RubyResolve
195
+ stack.draw "rectangle 0,0,#{image_info['width']},#{image_info['height']}"
196
+ end
197
+ end
198
+ # perform the blending operation
199
+ convert.compose(@wm_composition).gravity(@wm_gravity).define("compose:args=#{@wm_composition_args}").composite
200
+
201
+ convert.format(format)
202
+ convert << target
203
+
204
+ debug "ImageMagick command: '#{convert.command.join(' ')}'"
205
+ end
206
+
207
+ target
208
+
209
+ end
210
+
211
+ private
212
+
213
+ # Create or use a watermark image.
214
+ #
215
+ # If both text and image are set, the file will be used as-is if it exists and is a valid image file. Otherwise the
216
+ # file will be created or overwritten with a newly created watermark image.
217
+ #
218
+ # The created watermark file will be a 2000x2000 pixels PNG image with transparent background
219
+ #
220
+ # The text will be slanted by given rotation degrees counter-clockwise
221
+ def watermark_image
222
+ rotation = 360 - @wm_rotation
223
+ @wm_image = MiniMagick::Image.new(@wm_file) if @wm_file
224
+ # only create image if file is not an image
225
+ unless @wm_image&.valid?
226
+ # noinspection RubyResolve
227
+ # Create image file (as given or temp file)
228
+ image = @wm_file || (Dir::Tmpname.create(%w(wm_image .png)) {|_|})
229
+ # noinspection RubyResolve
230
+ MiniMagick::Tool::Convert.new do |convert|
231
+ convert.quiet # allways quiet
232
+ convert.background 'transparent'
233
+ convert.size('2000x2000')
234
+ convert.gravity 'Center'
235
+ convert.font('Helvetica').fill('black').pointsize(72) #.stroke('black').strokewidth(1)
236
+ convert << "label:#{@wm_text}"
237
+ convert.rotate rotation
238
+ convert.trim.repage.+
239
+ convert << image
240
+ end
241
+ if @wm_file
242
+ @wm_image = MiniMagick::Image.new(image)
243
+ else # delete temp file
244
+ @wm_image = MiniMagick::Image.open(image)
245
+ File.delete(image)
246
+ end
247
+ # noinspection RubyResolve
248
+ unless @wm_image.valid?
249
+ error "Problem creating watermark image '#{image}'."
250
+ @wm_image = nil
251
+ end
252
+ @wm_image
253
+ end
254
+ end
255
+
256
+
257
+ end
258
+
259
+ end
260
+ end
261
+ end