libis-format 1.0.2 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
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