image_paradise 0.1.12

Sign up to get free protection for your applications and to get access to all the features.

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