image_paradise 0.1.12

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.

Potentially problematic release.


This version of image_paradise might be problematic. Click here for more details.

Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +38 -0
  3. data/README.md +179 -0
  4. data/USAGE.md +10 -0
  5. data/bin/black_white +10 -0
  6. data/bin/display_text_from_this_image +7 -0
  7. data/bin/image_paradise +7 -0
  8. data/bin/image_paradise_shell +7 -0
  9. data/bin/image_to_ascii +54 -0
  10. data/bin/image_to_pdf +7 -0
  11. data/bin/make_this_image_transparent +7 -0
  12. data/bin/rotate_left +7 -0
  13. data/bin/rotate_right +7 -0
  14. data/doc/README.gen +162 -0
  15. data/doc/TODO_FOR_THE_GTK_GUI.md +1 -0
  16. data/image_paradise.gemspec +50 -0
  17. data/lib/image_paradise.rb +5 -0
  18. data/lib/image_paradise/base/base.rb +91 -0
  19. data/lib/image_paradise/black_white.rb +89 -0
  20. data/lib/image_paradise/confree_generator/class.rb +614 -0
  21. data/lib/image_paradise/confree_generator/constants.rb +61 -0
  22. data/lib/image_paradise/confree_generator/gui/gtk_confree_generator.rb +752 -0
  23. data/lib/image_paradise/confree_generator/gui/insert_button.rb +78 -0
  24. data/lib/image_paradise/confree_generator/reset.rb +61 -0
  25. data/lib/image_paradise/confree_generator/shared/shared.rb +100 -0
  26. data/lib/image_paradise/constants.rb +43 -0
  27. data/lib/image_paradise/constants/image_file_types.rb +21 -0
  28. data/lib/image_paradise/create_animated_gif.rb +47 -0
  29. data/lib/image_paradise/crop/crop.rb +302 -0
  30. data/lib/image_paradise/gm_support.rb +34 -0
  31. data/lib/image_paradise/graphs.rb +36 -0
  32. data/lib/image_paradise/graphs/accumulator_bar.rb +29 -0
  33. data/lib/image_paradise/graphs/area.rb +64 -0
  34. data/lib/image_paradise/graphs/bar.rb +117 -0
  35. data/lib/image_paradise/graphs/bar_conversion.rb +53 -0
  36. data/lib/image_paradise/graphs/base.rb +1392 -0
  37. data/lib/image_paradise/graphs/bezier.rb +45 -0
  38. data/lib/image_paradise/graphs/bullet.rb +115 -0
  39. data/lib/image_paradise/graphs/deprecated.rb +42 -0
  40. data/lib/image_paradise/graphs/dot.rb +129 -0
  41. data/lib/image_paradise/graphs/line.rb +328 -0
  42. data/lib/image_paradise/graphs/mini/bar.rb +42 -0
  43. data/lib/image_paradise/graphs/mini/legend.rb +109 -0
  44. data/lib/image_paradise/graphs/mini/pie.rb +42 -0
  45. data/lib/image_paradise/graphs/mini/side_bar.rb +41 -0
  46. data/lib/image_paradise/graphs/net.rb +133 -0
  47. data/lib/image_paradise/graphs/photo_bar.rb +106 -0
  48. data/lib/image_paradise/graphs/pie.rb +139 -0
  49. data/lib/image_paradise/graphs/scatter.rb +264 -0
  50. data/lib/image_paradise/graphs/scene.rb +216 -0
  51. data/lib/image_paradise/graphs/side_bar.rb +144 -0
  52. data/lib/image_paradise/graphs/side_stacked_bar.rb +116 -0
  53. data/lib/image_paradise/graphs/spider.rb +163 -0
  54. data/lib/image_paradise/graphs/stacked_area.rb +73 -0
  55. data/lib/image_paradise/graphs/stacked_bar.rb +68 -0
  56. data/lib/image_paradise/graphs/stacked_mixin.rb +30 -0
  57. data/lib/image_paradise/graphs/themes.rb +117 -0
  58. data/lib/image_paradise/graphviz/README.md +2 -0
  59. data/lib/image_paradise/graphviz/generate_graphviz_image.rb +274 -0
  60. data/lib/image_paradise/gui/gtk/control_panel.rb +126 -0
  61. data/lib/image_paradise/identify.rb +145 -0
  62. data/lib/image_paradise/image_border.rb +231 -0
  63. data/lib/image_paradise/image_manipulations.rb +320 -0
  64. data/lib/image_paradise/image_paradise.rb +150 -0
  65. data/lib/image_paradise/image_to_ascii/image_to_ascii.rb +187 -0
  66. data/lib/image_paradise/image_to_pdf/image_to_pdf.rb +99 -0
  67. data/lib/image_paradise/label/README.md +2 -0
  68. data/lib/image_paradise/label/simple_label.rb +206 -0
  69. data/lib/image_paradise/optimizer.rb +483 -0
  70. data/lib/image_paradise/project/project.rb +29 -0
  71. data/lib/image_paradise/random_text_to_image.rb +363 -0
  72. data/lib/image_paradise/requires/common_base_requires.rb +17 -0
  73. data/lib/image_paradise/requires/require_colours.rb +9 -0
  74. data/lib/image_paradise/requires/require_gtk_components.rb +8 -0
  75. data/lib/image_paradise/requires/require_image_to_ascii.rb +7 -0
  76. data/lib/image_paradise/requires/require_the_image_paradise_project.rb +24 -0
  77. data/lib/image_paradise/requires/require_toplevel_methods.rb +21 -0
  78. data/lib/image_paradise/rotate/README.md +2 -0
  79. data/lib/image_paradise/rotate/rotate.rb +98 -0
  80. data/lib/image_paradise/shell/interactive.rb +156 -0
  81. data/lib/image_paradise/svg/README.md +5 -0
  82. data/lib/image_paradise/svg/circle.rb +106 -0
  83. data/lib/image_paradise/svg/feature.rb +48 -0
  84. data/lib/image_paradise/svg/rectangle.rb +154 -0
  85. data/lib/image_paradise/svg/svg.rb +102 -0
  86. data/lib/image_paradise/to_gif.rb +91 -0
  87. data/lib/image_paradise/to_jpg.rb +90 -0
  88. data/lib/image_paradise/toplevel_methods/add_black_border_to_this_image.rb +56 -0
  89. data/lib/image_paradise/toplevel_methods/crop.rb +28 -0
  90. data/lib/image_paradise/toplevel_methods/e.rb +16 -0
  91. data/lib/image_paradise/toplevel_methods/esystem.rb +19 -0
  92. data/lib/image_paradise/toplevel_methods/extract_text_from_this_image.rb +56 -0
  93. data/lib/image_paradise/toplevel_methods/file_related_code.rb +25 -0
  94. data/lib/image_paradise/toplevel_methods/flip_image_left_right.rb +32 -0
  95. data/lib/image_paradise/toplevel_methods/greyscale_this_image.rb +59 -0
  96. data/lib/image_paradise/toplevel_methods/help.rb +30 -0
  97. data/lib/image_paradise/toplevel_methods/make_this_image_transparent.rb +30 -0
  98. data/lib/image_paradise/toplevel_methods/menu.rb +92 -0
  99. data/lib/image_paradise/toplevel_methods/merge_these_images.rb +49 -0
  100. data/lib/image_paradise/toplevel_methods/mirror_image.rb +28 -0
  101. data/lib/image_paradise/toplevel_methods/misc.rb +31 -0
  102. data/lib/image_paradise/toplevel_methods/png_to_svg.rb +34 -0
  103. data/lib/image_paradise/toplevel_methods/roebe.rb +17 -0
  104. data/lib/image_paradise/toplevel_methods/to_png.rb +105 -0
  105. data/lib/image_paradise/toplevel_methods/wallpaper.rb +37 -0
  106. data/lib/image_paradise/toplevel_methods/write_this_text.rb +76 -0
  107. data/lib/image_paradise/version/version.rb +19 -0
  108. data/test/16x16_red_square_image_for_testing.png +0 -0
  109. data/test/testing_confree_generator.rb +8 -0
  110. data/test/testing_crop.rb +19 -0
  111. data/test/testing_image_magick_commands.rb +39 -0
  112. data/test/testing_image_paradise.rb +49 -0
  113. data/test/testing_the_svg_component.html +261 -0
  114. data/test/testing_the_svg_component.rb +106 -0
  115. metadata +217 -0
@@ -0,0 +1,483 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ # === ImageParadise::Optimizer
6
+ #
7
+ # This class will delegate towards optimizing e. g. image files.
8
+ #
9
+ # Usage example:
10
+ #
11
+ # ImageParadise::Optimizer.new 'foo.png'
12
+ # ImageParadise::Optimizer.new 'foo.jpg'
13
+ #
14
+ # =========================================================================== #
15
+ # require 'image_paradise/optimizer.rb'
16
+ # =========================================================================== #
17
+ require 'image_paradise/base/base.rb'
18
+
19
+ module ImageParadise
20
+
21
+ class Optimizer < Base # === ImageParadise::Optimizer
22
+
23
+ # ========================================================================= #
24
+ # === NAMESPACE
25
+ # ========================================================================= #
26
+ NAMESPACE = inspect
27
+
28
+ # ========================================================================= #
29
+ # === CMD_TO_RUN
30
+ # ========================================================================= #
31
+ CMD_TO_RUN = 'pngquant' # This is either pngquant or jpegoptim for now.
32
+
33
+ # ========================================================================= #
34
+ # === FILE
35
+ # ========================================================================= #
36
+ FILE = __FILE__
37
+
38
+ # ========================================================================= #
39
+ # === initialize
40
+ # ========================================================================= #
41
+ def initialize(
42
+ i = ARGV,
43
+ run_already = true
44
+ )
45
+ reset
46
+ # ======================================================================= #
47
+ # Handle Hash as input next. These is currently only used to disable
48
+ # colours.
49
+ # ======================================================================= #
50
+ if block_given?
51
+ yielded = yield
52
+ if yielded.is_a? Hash
53
+ # =================================================================== #
54
+ # === :use_colours
55
+ # =================================================================== #
56
+ if yielded.has_key? :use_colours
57
+ @use_colours = yielded.delete(:use_colours)
58
+ end
59
+ # =================================================================== #
60
+ # === :may_we_exit
61
+ # =================================================================== #
62
+ if yielded.has_key? :may_we_exit
63
+ set_may_we_exit(yielded.delete(:may_we_exit))
64
+ end
65
+ else
66
+ case yielded
67
+ when :do_not_exit
68
+ @may_we_exit = false
69
+ end
70
+ end
71
+ end
72
+ set_these_files(i)
73
+ run if run_already
74
+ end
75
+
76
+ # ========================================================================= #
77
+ # === reset (reset tag)
78
+ # ========================================================================= #
79
+ def reset
80
+ super()
81
+ # ======================================================================= #
82
+ # === @may_we_exit
83
+ # ======================================================================= #
84
+ @may_we_exit = true
85
+ # ======================================================================= #
86
+ # === @output_file
87
+ # ======================================================================= #
88
+ @output_file = nil
89
+ # ======================================================================= #
90
+ # === @processed_n_files
91
+ #
92
+ # Keep track of how many image-files we already processed.
93
+ # ======================================================================= #
94
+ @processed_n_files = 0
95
+ # ======================================================================= #
96
+ # === @cmd_to_run
97
+ # ======================================================================= #
98
+ @cmd_to_run = CMD_TO_RUN
99
+ # ======================================================================= #
100
+ # === @use_colours
101
+ # ======================================================================= #
102
+ @use_colours = true
103
+ # ======================================================================= #
104
+ # === @obtain_this_image_format
105
+ #
106
+ # We can work either on .png files or on .jpg files.
107
+ #
108
+ # The following ivar will keep track of that.
109
+ # ======================================================================= #
110
+ @obtain_this_image_format = '.png'
111
+ end
112
+
113
+ # ========================================================================= #
114
+ # === set_may_we_exit
115
+ # ========================================================================= #
116
+ def set_may_we_exit(i)
117
+ case i
118
+ when :do_not_exit
119
+ i = false
120
+ end
121
+ @may_we_exit = i
122
+ end
123
+
124
+ # ========================================================================= #
125
+ # === rds
126
+ # ========================================================================= #
127
+ def rds(i)
128
+ i.squeeze('/')
129
+ end
130
+
131
+ # ========================================================================= #
132
+ # === cmd_to_run?
133
+ # ========================================================================= #
134
+ def cmd_to_run?
135
+ @cmd_to_run
136
+ end; alias cmd? cmd_to_run? # === cmd
137
+
138
+ # ========================================================================= #
139
+ # === set_these_files
140
+ #
141
+ # We always have to work on an Array.
142
+ # ========================================================================= #
143
+ def set_these_files(i = 'ALL_PNG_IMAGES')
144
+ if i.is_a? String
145
+ i = i.to_s.dup
146
+ i.strip!
147
+ # ===================================================================== #
148
+ # Assume that the user did input a String with internal ' '.
149
+ # This means that we will split up this String and assume
150
+ # that the entries will be valid files.
151
+ # ===================================================================== #
152
+ i = i.split(' ') if i.include? ' '
153
+ end
154
+ i = [i] unless i.is_a? Array # After this point, we have an array.
155
+ menu(i)
156
+ if i.any? {|_| _.include? 'localhost' }
157
+ i.map! {|entry|
158
+ _ = ENV['MY_DATA']+'/'
159
+ entry = entry.gsub(/localhost/, _).
160
+ gsub(/^http:\/\//,'')
161
+ }
162
+ end
163
+ @these_files = i
164
+ sanitize_these_files # Always optimize it after the assignment.
165
+ end
166
+
167
+ # ========================================================================= #
168
+ # === sanitize_these_files
169
+ # ========================================================================= #
170
+ def sanitize_these_files
171
+ @these_files.map! {|entry|
172
+ entry = entry.to_s.dup
173
+ entry.strip!
174
+ case entry # Next, act on a few special instructions. (case tag)
175
+ # ===================================================================== #
176
+ # === ALL_IMAGES
177
+ # ===================================================================== #
178
+ when 'ALL_IMAGES','ALL_PNG','ALLPNG','ALL_PNG_IMAGES','ALL',nil
179
+ entry = Dir['*'+image_format?]
180
+ # ===================================================================== #
181
+ # === DEEP
182
+ # ===================================================================== #
183
+ when 'DEEP','ALL_SUBDIRS' # As above but includes all subdirectories.
184
+ entry = Dir['**/*'+image_format?]
185
+ end
186
+ entry
187
+ }
188
+ @these_files.flatten!
189
+ end
190
+
191
+ # ========================================================================= #
192
+ # === show_help_then_exit (help tag)
193
+ # ========================================================================= #
194
+ def show_help_then_exit
195
+ e
196
+ Colours.ecomment ' ALL_IMAGES # Work on all images but only in the current directory.'
197
+ Colours.ecomment ' DEEP # Work on all images, including subdirectories.'
198
+ Colours.ecomment ' OPEN # Open this file here.'
199
+ e
200
+ exit
201
+ end
202
+
203
+ # ========================================================================= #
204
+ # === open_this_file_here_then_exit
205
+ # ========================================================================= #
206
+ def open_this_file_here_then_exit
207
+ _ = 'bluefish '+FILE
208
+ opnn; e _; system _
209
+ exit
210
+ end
211
+
212
+ # ========================================================================= #
213
+ # === menu
214
+ # ========================================================================= #
215
+ def menu(i)
216
+ if i.is_a? Array
217
+ i.each {|entry| menu(entry) }
218
+ else
219
+ case i # These case-entries here are commandline-options, hence why we exit.
220
+ # ===================================================================== #
221
+ # === optimizer --open
222
+ # ===================================================================== #
223
+ when /-?-?open/,'OPEN'
224
+ open_this_file_here_then_exit
225
+ # ===================================================================== #
226
+ # === optimizer --help
227
+ # ===================================================================== #
228
+ when /-?-?help/,'HELP','HELP?'
229
+ show_help_then_exit
230
+ end
231
+ end
232
+ end
233
+
234
+ # ========================================================================= #
235
+ # === these_files?
236
+ # ========================================================================= #
237
+ def these_files?
238
+ @these_files
239
+ end; alias files? these_files? # === files?
240
+ alias input? these_files? # === input?
241
+
242
+ # ========================================================================= #
243
+ # === rev
244
+ # ========================================================================= #
245
+ def rev
246
+ Colours.rev
247
+ end
248
+
249
+ # ========================================================================= #
250
+ # === sfancy
251
+ # ========================================================================= #
252
+ def sfancy(i = '')
253
+ return Colours.sfancy(i) if use_colours?
254
+ return i
255
+ end
256
+
257
+ # ========================================================================= #
258
+ # === sfile
259
+ # ========================================================================= #
260
+ def sfile(i = '')
261
+ return Colours.sfile(i)if use_colours?
262
+ return i
263
+ end
264
+
265
+ # ========================================================================= #
266
+ # === report_stats
267
+ # ========================================================================= #
268
+ def report_stats(i = file?)
269
+ opnn
270
+ e 'The old filesize of `'+sfile(i)+'` was: '+
271
+ sfancy('%6s' % @old_filesize.to_s)
272
+ opnn
273
+ e 'The new filesize of `'+sfile(i)+'` is: '+
274
+ sfancy('%6s' % @new_filesize.to_s)
275
+ end
276
+
277
+ # ========================================================================= #
278
+ # === use_colours?
279
+ # ========================================================================= #
280
+ def use_colours?
281
+ @use_colours
282
+ end
283
+
284
+ # ========================================================================= #
285
+ # === obtain_this_image_format?
286
+ # ========================================================================= #
287
+ def obtain_this_image_format?
288
+ @obtain_this_image_format
289
+ end; alias image_format? obtain_this_image_format? # === image_format?
290
+
291
+ # ========================================================================= #
292
+ # === is_png_file?
293
+ # ========================================================================= #
294
+ def is_png_file?(i) # check whether this file is a .png file or not.
295
+ return true if File.extname(i) == image_format?
296
+ false
297
+ end; alias is_jpeg_file? is_png_file? # === is_jpeg_file?
298
+
299
+ # ========================================================================= #
300
+ # === set_old_filesize
301
+ # ========================================================================= #
302
+ def set_old_filesize(i = file?)
303
+ if File.exist? i
304
+ @old_filesize = File.size(i)
305
+ determine_output_file(i)
306
+ end
307
+ end
308
+
309
+ # ========================================================================= #
310
+ # === rename_new_file_to_old_file
311
+ # ========================================================================= #
312
+ def rename_new_file_to_old_file(i = file?)
313
+ FileUtils.mv(output?, i)
314
+ end
315
+
316
+ # ========================================================================= #
317
+ # === determine_output_file
318
+ #
319
+ # This will determine the instance variable @output_file.
320
+ # ========================================================================= #
321
+ def determine_output_file(i)
322
+ @output_file = i.dup # Will store here.
323
+ @output_file[@output_file.index('.'),0] = '-fs8' # Append "-fs8".
324
+ end
325
+
326
+ # ========================================================================= #
327
+ # === work_on_the_images
328
+ # ========================================================================= #
329
+ def work_on_the_images
330
+ files?.each {|the_file|
331
+ the_file = rds(the_file)
332
+ extname = File.extname(the_file).delete('.')
333
+ case extname
334
+ # ===================================================================== #
335
+ # === Handle .jpg or .jpeg files here
336
+ # ===================================================================== #
337
+ when 'jpg','jpeg'
338
+ @processed_n_files += 1 # Increment the counter very early on.
339
+ @cmd_to_run = 'jpegoptim'
340
+ esystem @cmd_to_run+' '+the_file
341
+ # ===================================================================== #
342
+ # === Handle .png files here
343
+ # ===================================================================== #
344
+ when 'png'
345
+ if File.exist? the_file
346
+ @processed_n_files += 1 # Increment the counter very early on.
347
+ if is_png_file?(the_file) # main tag
348
+ set_old_filesize(the_file)
349
+ run_sys_command(the_file)
350
+ rename_new_file_to_old_file(the_file) # <-- Important for cleanup.
351
+ report_stats(the_file)
352
+ else
353
+ opnn
354
+ e 'The file '+sfile(the_file)+' is '+RED+'not'+rev+
355
+ ' a '+image_format?+' file. We can not optimize it.'
356
+ end
357
+ else
358
+ opnn
359
+ e 'No file could be found at `'+sfile(the_file)+'`.'
360
+ end
361
+ else
362
+ e 'Unsure what to do with `'+sfile(the_file)+'`.'
363
+ end
364
+ }
365
+ consider_reporting_how_many_image_files_we_did_process
366
+ end
367
+
368
+ # ========================================================================= #
369
+ # === output?
370
+ # ========================================================================= #
371
+ def output?
372
+ @output_file
373
+ end
374
+
375
+ # ========================================================================= #
376
+ # === red?
377
+ # ========================================================================= #
378
+ def red?
379
+ Colours::RED
380
+ end
381
+
382
+ # ========================================================================= #
383
+ # === consider_reporting_how_many_image_files_we_did_process
384
+ # ========================================================================= #
385
+ def consider_reporting_how_many_image_files_we_did_process
386
+ if @processed_n_files > 1 # Only if we have at least processed 2 images.
387
+ opnn
388
+ e 'Finished! We processed '+sfancy(@processed_n_files.to_s)+' '+
389
+ @obtain_this_image_format+' files.'
390
+ end
391
+ end
392
+
393
+ # ========================================================================= #
394
+ # === opnn
395
+ # ========================================================================= #
396
+ def opnn
397
+ Opn.opn(
398
+ namespace: NAMESPACE, use_colours: @use_colours
399
+ )
400
+ end
401
+
402
+ # ========================================================================= #
403
+ # === run_sys_command
404
+ #
405
+ # The first argument should be an existing, local file such as
406
+ # "foobar.jpg", without the quotes.
407
+ # ========================================================================= #
408
+ def run_sys_command(i)
409
+ if i.include? "'"
410
+ i = '"'+i+'"'
411
+ end
412
+ _ = cmd?.to_s.dup
413
+ _ << ' --force' if i.include? 'png'
414
+ _ << ' '+i # This is the filename here.
415
+ opnn
416
+ esystem(_)
417
+ if File.exist? output? # Check whether the output file exists.
418
+ @new_filesize = File.size(output?)
419
+ else
420
+ opnn; e "The file `#{sfile(output?)}` does not exist."
421
+ if @may_we_exit
422
+ opnn; e 'Thus exiting now.'
423
+ exit
424
+ end
425
+ end
426
+ end
427
+
428
+ # ========================================================================= #
429
+ # === check_whether_the_command_is_available_or_not
430
+ #
431
+ # We check whether the commands are available or not.
432
+ # ========================================================================= #
433
+ def check_whether_the_command_is_available_or_not
434
+ result = `#{cmd?} 2>&1`
435
+ is_available = true
436
+ is_available = false if result.include? cmd?+': not found'
437
+ if is_available == false
438
+ opnn
439
+ e 'The program `'+sfancy(cmd?)+'` is '+red?+'not'+rev+
440
+ ' available. Please install it first.'
441
+ if is_on_roebe?
442
+ e 'As this is a roebe-system, we will try to make use of'
443
+ e 'the RBT project in order to compile this program next.'
444
+ try_to_compile_this_program(cmd?)
445
+ end
446
+ exit
447
+ end
448
+ end
449
+
450
+ # ========================================================================= #
451
+ # === try_to_compile_this_program
452
+ #
453
+ # This method will tab into the RBT project and compile the
454
+ # given input at hand - which is typically "pngquant".
455
+ #
456
+ # The method was added mostly as a convenience-method, to
457
+ # quickly install pngquant.
458
+ # ========================================================================= #
459
+ def try_to_compile_this_program(i = cmd?)
460
+ require 'rbt'
461
+ RBT::Compile.new(i)
462
+ end
463
+
464
+ # ========================================================================= #
465
+ # === run
466
+ # ========================================================================= #
467
+ def run
468
+ check_whether_the_command_is_available_or_not
469
+ work_on_the_images
470
+ end
471
+
472
+ # ========================================================================= #
473
+ # === ImageParadise::Optimizer[]
474
+ # ========================================================================= #
475
+ def self.[](i)
476
+ new(i)
477
+ end
478
+
479
+ end; end
480
+
481
+ if __FILE__ == $PROGRAM_NAME
482
+ ImageParadise::Optimizer.new(ARGV)
483
+ end # optimizer