image_paradise 0.4.8

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 (649) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +38 -0
  3. data/README.md +928 -0
  4. data/USAGE.md +10 -0
  5. data/bin/black_white +10 -0
  6. data/bin/confree_generator +7 -0
  7. data/bin/create_new_image +7 -0
  8. data/bin/display_text_from_this_image +7 -0
  9. data/bin/draw_as_specified_from_the_yaml_file +7 -0
  10. data/bin/embed_the_filename_into_this_image +7 -0
  11. data/bin/image_paradise +7 -0
  12. data/bin/image_paradise_shell +7 -0
  13. data/bin/image_to_ascii +54 -0
  14. data/bin/image_to_pdf +7 -0
  15. data/bin/imageparadise_img2pdf +12 -0
  16. data/bin/img_text +14 -0
  17. data/bin/interlace +7 -0
  18. data/bin/jpg_to_pdf +12 -0
  19. data/bin/magic_card_border +8 -0
  20. data/bin/make_this_image_transparent +7 -0
  21. data/bin/morph_these_images +7 -0
  22. data/bin/optimize_this_image +7 -0
  23. data/bin/quality +7 -0
  24. data/bin/resize_by_percent +10 -0
  25. data/bin/rotate_left +7 -0
  26. data/bin/rotate_right +7 -0
  27. data/bin/round_the_corner +7 -0
  28. data/bin/ruby_montage +7 -0
  29. data/bin/transparent +15 -0
  30. data/doc/README.gen +871 -0
  31. data/doc/todo/TODO_FOR_THE_GTK_GUI.md +9 -0
  32. data/doc/todo/TODO_FOR_THE_IMAGE_PARADISE_PROJECT.md +22 -0
  33. data/doc/todo/TODO_WORK_THROUGH_THESE_LINKS.md +3 -0
  34. data/doc/todo/todo_for_the_libui_gui.md +4 -0
  35. data/image_paradise.gemspec +46 -0
  36. data/images/IMAGE_PARADISE_LOGO.png +0 -0
  37. data/lib/image_paradise/base/base.rb +293 -0
  38. data/lib/image_paradise/cfdg/1dca_pattern.cfdg +48 -0
  39. data/lib/image_paradise/cfdg/3d_coloured_cube.cfdg +95 -0
  40. data/lib/image_paradise/cfdg/a_3D_spiral.cfdg +40 -0
  41. data/lib/image_paradise/cfdg/a_chaotic_city.cfdg +156 -0
  42. data/lib/image_paradise/cfdg/a_coloured_red.cfdg +21 -0
  43. data/lib/image_paradise/cfdg/a_daisy_flower.cfdg +66 -0
  44. data/lib/image_paradise/cfdg/a_decorated_window.cfdg +74 -0
  45. data/lib/image_paradise/cfdg/a_human_profile.cfdg +303 -0
  46. data/lib/image_paradise/cfdg/a_lost_heart.cfdg +28 -0
  47. data/lib/image_paradise/cfdg/a_plant_root.cfdg +26 -0
  48. data/lib/image_paradise/cfdg/a_rather_realistic_forest.cfdg +29 -0
  49. data/lib/image_paradise/cfdg/a_shoreline_next_to_a_forest.cfdg +127 -0
  50. data/lib/image_paradise/cfdg/a_simple_mini_brain.cfdg +17 -0
  51. data/lib/image_paradise/cfdg/a_simple_star.cfdg +22 -0
  52. data/lib/image_paradise/cfdg/adorned_tree.cfdg +58 -0
  53. data/lib/image_paradise/cfdg/adsorption.cfdg +19 -0
  54. data/lib/image_paradise/cfdg/alfabet_free.cfdg +346 -0
  55. data/lib/image_paradise/cfdg/alfreebet.cfdg +229 -0
  56. data/lib/image_paradise/cfdg/algal_flora.cfdg +25 -0
  57. data/lib/image_paradise/cfdg/alien_eyeball.cfdg +15 -0
  58. data/lib/image_paradise/cfdg/alien_flower.cfdg +35 -0
  59. data/lib/image_paradise/cfdg/alphabet_circles.cfdg +38 -0
  60. data/lib/image_paradise/cfdg/alveolo.cfdg +38 -0
  61. data/lib/image_paradise/cfdg/an_icosahedron.cfdg +134 -0
  62. data/lib/image_paradise/cfdg/an_oils_surface.cfdg +48 -0
  63. data/lib/image_paradise/cfdg/ancient_map.cfdg +30 -0
  64. data/lib/image_paradise/cfdg/ancient_scripts_tile.cfdg +96 -0
  65. data/lib/image_paradise/cfdg/angelfish.cfdg +58 -0
  66. data/lib/image_paradise/cfdg/angry_yarn.cfdg +82 -0
  67. data/lib/image_paradise/cfdg/apple_tree_small.cfdg +46 -0
  68. data/lib/image_paradise/cfdg/aqua_star.cfdg +27 -0
  69. data/lib/image_paradise/cfdg/army_explosion.cfdg +25 -0
  70. data/lib/image_paradise/cfdg/arrows_in_quadcity.cfdg +143 -0
  71. data/lib/image_paradise/cfdg/artificial_intelligence.cfdg +41 -0
  72. data/lib/image_paradise/cfdg/askew.cfdg +27 -0
  73. data/lib/image_paradise/cfdg/audio_diagram_waves.cfdg +54 -0
  74. data/lib/image_paradise/cfdg/autumn_fractal.cfdg +39 -0
  75. data/lib/image_paradise/cfdg/baignoire.cfdg +33 -0
  76. data/lib/image_paradise/cfdg/barcode.cfdg +781 -0
  77. data/lib/image_paradise/cfdg/basic_polygon_shapes.cfdg +311 -0
  78. data/lib/image_paradise/cfdg/basic_spreaders.cfdg +52 -0
  79. data/lib/image_paradise/cfdg/basic_square.cfdg +8 -0
  80. data/lib/image_paradise/cfdg/bats_hiding_in_foliage.cfdg +19 -0
  81. data/lib/image_paradise/cfdg/bees.cfdg +61 -0
  82. data/lib/image_paradise/cfdg/bent_squares.cfdg +46 -0
  83. data/lib/image_paradise/cfdg/benzo_dreaming.cfdg +54 -0
  84. data/lib/image_paradise/cfdg/beta_bet.cfdg +645 -0
  85. data/lib/image_paradise/cfdg/big_bang_theory.cfdg +31 -0
  86. data/lib/image_paradise/cfdg/big_pacman.cfdg +70 -0
  87. data/lib/image_paradise/cfdg/bigger_tree.cfdg +64 -0
  88. data/lib/image_paradise/cfdg/binary_connection.cfdg +34 -0
  89. data/lib/image_paradise/cfdg/birch_line.cfdg +57 -0
  90. data/lib/image_paradise/cfdg/blacksmith_masterpiece.cfdg +3 -0
  91. data/lib/image_paradise/cfdg/blocked_rectangles.cfdg +23 -0
  92. data/lib/image_paradise/cfdg/blood_tubes.cfdg +45 -0
  93. data/lib/image_paradise/cfdg/bloom.cfdg +23 -0
  94. data/lib/image_paradise/cfdg/blown_glass_spheres.cfdg +30 -0
  95. data/lib/image_paradise/cfdg/blue_daisies_in_detail.cfdg +101 -0
  96. data/lib/image_paradise/cfdg/blue_galaxy.cfdg +20 -0
  97. data/lib/image_paradise/cfdg/blue_moon.cfdg +36 -0
  98. data/lib/image_paradise/cfdg/boa_feathers.cfdg +53 -0
  99. data/lib/image_paradise/cfdg/bomb.cfdg +75 -0
  100. data/lib/image_paradise/cfdg/boxy_continent.cfdg +111 -0
  101. data/lib/image_paradise/cfdg/bright_coloured_neurons.cfdg +53 -0
  102. data/lib/image_paradise/cfdg/brightness_flower.cfdg +31 -0
  103. data/lib/image_paradise/cfdg/btp_71_beautiful_coloured_lines.cfdg +85 -0
  104. data/lib/image_paradise/cfdg/btp_73.cfdg +76 -0
  105. data/lib/image_paradise/cfdg/bubblesun.cfdg +46 -0
  106. data/lib/image_paradise/cfdg/burning_bush.cfdg +31 -0
  107. data/lib/image_paradise/cfdg/butterflies_in_the_moonlight.cfdg +55 -0
  108. data/lib/image_paradise/cfdg/cardiod_arc.cfdg +44 -0
  109. data/lib/image_paradise/cfdg/cardioid.cfdg +41 -0
  110. data/lib/image_paradise/cfdg/caros_wallpaper.cfdg +46 -0
  111. data/lib/image_paradise/cfdg/cartoony_face_arrays.cfdg +137 -0
  112. data/lib/image_paradise/cfdg/centerfold.cfdg +12 -0
  113. data/lib/image_paradise/cfdg/chain_link_fence.cfdg +31 -0
  114. data/lib/image_paradise/cfdg/chanukah.cfdg +109 -0
  115. data/lib/image_paradise/cfdg/chaos_red_sun.cfdg +42 -0
  116. data/lib/image_paradise/cfdg/chaotic_farn.cfdg +76 -0
  117. data/lib/image_paradise/cfdg/chaotic_fractal_shell.cfdg +41 -0
  118. data/lib/image_paradise/cfdg/charleston.cfdg +182 -0
  119. data/lib/image_paradise/cfdg/ciliasun.cfdg +109 -0
  120. data/lib/image_paradise/cfdg/cipal.cfdg +65 -0
  121. data/lib/image_paradise/cfdg/circuits.cfdg +176 -0
  122. data/lib/image_paradise/cfdg/city_map.cfdg +66 -0
  123. data/lib/image_paradise/cfdg/clifford_torus.cfdg +135 -0
  124. data/lib/image_paradise/cfdg/colonize_flat_colour_pattern.cfdg +14 -0
  125. data/lib/image_paradise/cfdg/colour_blind_squid.cfdg +30 -0
  126. data/lib/image_paradise/cfdg/colour_hole.cfdg +56 -0
  127. data/lib/image_paradise/cfdg/colour_wheel.cfdg +40 -0
  128. data/lib/image_paradise/cfdg/coloured_eyes.cfdg +40 -0
  129. data/lib/image_paradise/cfdg/coloured_forest.cfdg +133 -0
  130. data/lib/image_paradise/cfdg/coloured_tree.cfdg +50 -0
  131. data/lib/image_paradise/cfdg/colourful_lives.cfdg +123 -0
  132. data/lib/image_paradise/cfdg/colourful_neuronal_network.cfdg +32 -0
  133. data/lib/image_paradise/cfdg/complex_city_plans.cfdg +75 -0
  134. data/lib/image_paradise/cfdg/complex_kritworks.cfdg +75 -0
  135. data/lib/image_paradise/cfdg/complex_snowflake.cfdg +61 -0
  136. data/lib/image_paradise/cfdg/conspiracy_theory.cfdg +104 -0
  137. data/lib/image_paradise/cfdg/constellation_grid.cfdg +29 -0
  138. data/lib/image_paradise/cfdg/cool_caterpillar.cfdg +44 -0
  139. data/lib/image_paradise/cfdg/coolcubes.cfdg +70 -0
  140. data/lib/image_paradise/cfdg/crawler_battle.cfdg +93 -0
  141. data/lib/image_paradise/cfdg/crazy_octo.cfdg +48 -0
  142. data/lib/image_paradise/cfdg/cthulhu.cfdg +166 -0
  143. data/lib/image_paradise/cfdg/cubies.cfdg +43 -0
  144. data/lib/image_paradise/cfdg/cubist_sunset.cfdg +55 -0
  145. data/lib/image_paradise/cfdg/curled_tree.cfdg +37 -0
  146. data/lib/image_paradise/cfdg/curls.cfdg +45 -0
  147. data/lib/image_paradise/cfdg/curve_stiched.cfdg +59 -0
  148. data/lib/image_paradise/cfdg/curved_tubes.cfdg +20 -0
  149. data/lib/image_paradise/cfdg/cylinder_city.cfdg +27 -0
  150. data/lib/image_paradise/cfdg/cymbal.cfdg +38 -0
  151. data/lib/image_paradise/cfdg/d_mustard.cfdg +52 -0
  152. data/lib/image_paradise/cfdg/dance_party.cfdg +81 -0
  153. data/lib/image_paradise/cfdg/dance_party_and_background.cfdg +86 -0
  154. data/lib/image_paradise/cfdg/decreasing_aperture.cfdg +16 -0
  155. data/lib/image_paradise/cfdg/delicat_twist.cfdg +13 -0
  156. data/lib/image_paradise/cfdg/demo_text.cfdg +22 -0
  157. data/lib/image_paradise/cfdg/dennis_ritchie.cfdg +294 -0
  158. data/lib/image_paradise/cfdg/diablo.cfdg +47 -0
  159. data/lib/image_paradise/cfdg/different_flowers.cfdg +60 -0
  160. data/lib/image_paradise/cfdg/different_snowflakes_shapes.cfdg +149 -0
  161. data/lib/image_paradise/cfdg/dimensions.cfdg +33 -0
  162. data/lib/image_paradise/cfdg/domino_pieces.cfdg +166 -0
  163. data/lib/image_paradise/cfdg/dong.cfdg +41 -0
  164. data/lib/image_paradise/cfdg/drip_shape.cfdg +24 -0
  165. data/lib/image_paradise/cfdg/earthday2007b.cfdg +49 -0
  166. data/lib/image_paradise/cfdg/edera_circles.cfdg +55 -0
  167. data/lib/image_paradise/cfdg/eight_queens_problem.cfdg +85 -0
  168. data/lib/image_paradise/cfdg/electro_shock.cfdg +88 -0
  169. data/lib/image_paradise/cfdg/enter_the_force_field.cfdg +56 -0
  170. data/lib/image_paradise/cfdg/escargot_fleur.cfdg +98 -0
  171. data/lib/image_paradise/cfdg/european_city.cfdg +63 -0
  172. data/lib/image_paradise/cfdg/evil_eye.cfdg +74 -0
  173. data/lib/image_paradise/cfdg/evolving_coloured_spots.cfdg +47 -0
  174. data/lib/image_paradise/cfdg/excellines_nr2.cfdg +171 -0
  175. data/lib/image_paradise/cfdg/exoplanet_settlement.cfdg +117 -0
  176. data/lib/image_paradise/cfdg/explosion.cfdg +45 -0
  177. data/lib/image_paradise/cfdg/explosion_of_a_megabyte.cfdg +73 -0
  178. data/lib/image_paradise/cfdg/eye_of_katora.cfdg +20 -0
  179. data/lib/image_paradise/cfdg/family_tree.cfdg +169 -0
  180. data/lib/image_paradise/cfdg/feathers.cfdg +17 -0
  181. data/lib/image_paradise/cfdg/ferma_drawings.cfdg +23 -0
  182. data/lib/image_paradise/cfdg/fevrier.cfdg +66 -0
  183. data/lib/image_paradise/cfdg/fibmod.cfdg +25 -0
  184. data/lib/image_paradise/cfdg/field_of_boxes.cfdg +21 -0
  185. data/lib/image_paradise/cfdg/finetre.cfdg +34 -0
  186. data/lib/image_paradise/cfdg/fireblorks.cfdg +37 -0
  187. data/lib/image_paradise/cfdg/first_branch.cfdg +18 -0
  188. data/lib/image_paradise/cfdg/fish_with_coloured_bubbles.cfdg +77 -0
  189. data/lib/image_paradise/cfdg/fishing_lure.cfdg +30 -0
  190. data/lib/image_paradise/cfdg/flake.cfdg +20 -0
  191. data/lib/image_paradise/cfdg/flaming_spiro.cfdg +10 -0
  192. data/lib/image_paradise/cfdg/fleshflower.cfdg +25 -0
  193. data/lib/image_paradise/cfdg/flourescent_fish_btp.cfdg +48 -0
  194. data/lib/image_paradise/cfdg/flow_control_shape.cfdg +45 -0
  195. data/lib/image_paradise/cfdg/flower_galaxy.cfdg +57 -0
  196. data/lib/image_paradise/cfdg/flower_house.cfdg +115 -0
  197. data/lib/image_paradise/cfdg/flower_stories.cfdg +136 -0
  198. data/lib/image_paradise/cfdg/fluctuating_heart.cfdg +87 -0
  199. data/lib/image_paradise/cfdg/fly_agaric.cfdg +22 -0
  200. data/lib/image_paradise/cfdg/forest_and_ocean.cfdg +65 -0
  201. data/lib/image_paradise/cfdg/fractal_fern.cfdg +15 -0
  202. data/lib/image_paradise/cfdg/fractal_shell.cfdg +36 -0
  203. data/lib/image_paradise/cfdg/frost_bite.cfdg +23 -0
  204. data/lib/image_paradise/cfdg/fun_with_paper.cfdg +17 -0
  205. data/lib/image_paradise/cfdg/func_plot.cfdg +59 -0
  206. data/lib/image_paradise/cfdg/funky_squiggle.cfdg +40 -0
  207. data/lib/image_paradise/cfdg/fuzzy_sun.cfdg +47 -0
  208. data/lib/image_paradise/cfdg/galaxy.cfdg +59 -0
  209. data/lib/image_paradise/cfdg/gallery.cfdg +28 -0
  210. data/lib/image_paradise/cfdg/game1_turn6.cfdg +35 -0
  211. data/lib/image_paradise/cfdg/garland.cfdg +42 -0
  212. data/lib/image_paradise/cfdg/general_polygons.cfdg +20 -0
  213. data/lib/image_paradise/cfdg/generational_birds.cfdg +118 -0
  214. data/lib/image_paradise/cfdg/ghostly_spine.cfdg +24 -0
  215. data/lib/image_paradise/cfdg/gift_wrapping.cfdg +46 -0
  216. data/lib/image_paradise/cfdg/glass_cubes.cfdg +33 -0
  217. data/lib/image_paradise/cfdg/gleaming_bush.cfdg +33 -0
  218. data/lib/image_paradise/cfdg/glowing_bush.cfdg +33 -0
  219. data/lib/image_paradise/cfdg/go_grid.cfdg +32 -0
  220. data/lib/image_paradise/cfdg/gold_tiles.cfdg +21 -0
  221. data/lib/image_paradise/cfdg/golden_rectangle.cfdg +19 -0
  222. data/lib/image_paradise/cfdg/golden_sierpinski.cfdg +49 -0
  223. data/lib/image_paradise/cfdg/golgi_stain.cfdg +74 -0
  224. data/lib/image_paradise/cfdg/gothic_bath_tiles.cfdg +14 -0
  225. data/lib/image_paradise/cfdg/grass_land.cfdg +112 -0
  226. data/lib/image_paradise/cfdg/gray_matter.cfdg +110 -0
  227. data/lib/image_paradise/cfdg/great_forest.cfdg +91 -0
  228. data/lib/image_paradise/cfdg/growth.cfdg +46 -0
  229. data/lib/image_paradise/cfdg/gumtree.cfdg +28 -0
  230. data/lib/image_paradise/cfdg/haggards_bull.cfdg +92 -0
  231. data/lib/image_paradise/cfdg/haight_ashbury.cfdg +882 -0
  232. data/lib/image_paradise/cfdg/hair_pattern.cfdg +59 -0
  233. data/lib/image_paradise/cfdg/hairy.cfdg +43 -0
  234. data/lib/image_paradise/cfdg/hairy_branch.cfdg +48 -0
  235. data/lib/image_paradise/cfdg/hands_and_feet.cfdg +49 -0
  236. data/lib/image_paradise/cfdg/happy_new_year.cfdg +3435 -0
  237. data/lib/image_paradise/cfdg/hatagu_lila_spiral.cfdg +27 -0
  238. data/lib/image_paradise/cfdg/hexaeder_triangle.cfdg +43 -0
  239. data/lib/image_paradise/cfdg/hexclouds_textures.cfdg +75 -0
  240. data/lib/image_paradise/cfdg/hextiles.cfdg +73 -0
  241. data/lib/image_paradise/cfdg/hexy_continent.cfdg +83 -0
  242. data/lib/image_paradise/cfdg/human_ballet.cfdg +215 -0
  243. data/lib/image_paradise/cfdg/human_eyes.cfdg +102 -0
  244. data/lib/image_paradise/cfdg/hydra_tail.cfdg +57 -0
  245. data/lib/image_paradise/cfdg/i_like_it_dirty.cfdg +88 -0
  246. data/lib/image_paradise/cfdg/i_pix.cfdg +679 -0
  247. data/lib/image_paradise/cfdg/imaginary_star.cfdg +55 -0
  248. data/lib/image_paradise/cfdg/imaginery_forest.cfdg +61 -0
  249. data/lib/image_paradise/cfdg/impossible_stairs.cfdg +211 -0
  250. data/lib/image_paradise/cfdg/in_the_morning.cfdg +83 -0
  251. data/lib/image_paradise/cfdg/inertial_confinement.cfdg +150 -0
  252. data/lib/image_paradise/cfdg/infected_shell.cfdg +56 -0
  253. data/lib/image_paradise/cfdg/insect_fight.cfdg +316 -0
  254. data/lib/image_paradise/cfdg/insectivore.cfdg +80 -0
  255. data/lib/image_paradise/cfdg/interference.cfdg +43 -0
  256. data/lib/image_paradise/cfdg/interference_fields.cfdg +25 -0
  257. data/lib/image_paradise/cfdg/into_the_deep.cfdg +96 -0
  258. data/lib/image_paradise/cfdg/inverted_decorations.cfdg +85 -0
  259. data/lib/image_paradise/cfdg/irregular_galaxies.cfdg +29 -0
  260. data/lib/image_paradise/cfdg/iso_blocks.cfdg +35 -0
  261. data/lib/image_paradise/cfdg/jewelry_old_style.cfdg +31 -0
  262. data/lib/image_paradise/cfdg/just_some_flowers.cfdg +127 -0
  263. data/lib/image_paradise/cfdg/kaboom.cfdg +40 -0
  264. data/lib/image_paradise/cfdg/kaleidoskop.cfdg +27 -0
  265. data/lib/image_paradise/cfdg/kama_sutra.cfdg +182 -0
  266. data/lib/image_paradise/cfdg/kitakoa_akiyoshi_illusions_roller.cfdg +40 -0
  267. data/lib/image_paradise/cfdg/koch_snowflake.cfdg +11 -0
  268. data/lib/image_paradise/cfdg/kochlea.cfdg +43 -0
  269. data/lib/image_paradise/cfdg/kreepykrawler.cfdg +48 -0
  270. data/lib/image_paradise/cfdg/kw_expanded_explosion.cfdg +46 -0
  271. data/lib/image_paradise/cfdg/lapsang_abstrait.cfdg +51 -0
  272. data/lib/image_paradise/cfdg/laser.cfdg +51 -0
  273. data/lib/image_paradise/cfdg/last_pluto_dream.cfdg +95 -0
  274. data/lib/image_paradise/cfdg/lazy_dust.cfdg +42 -0
  275. data/lib/image_paradise/cfdg/lesson_one_two_three_four.cfdg +217 -0
  276. data/lib/image_paradise/cfdg/lila_lili.cfdg +60 -0
  277. data/lib/image_paradise/cfdg/lindenmayergrassef2_pretty_flowers.cfdg +94 -0
  278. data/lib/image_paradise/cfdg/lines_from_excel.cfdg +136 -0
  279. data/lib/image_paradise/cfdg/looking_out.cfdg +51 -0
  280. data/lib/image_paradise/cfdg/looking_up_in_the_sky.cfdg +43 -0
  281. data/lib/image_paradise/cfdg/lotus_logo.cfdg +49 -0
  282. data/lib/image_paradise/cfdg/lowercased_alphabet.cfdg +565 -0
  283. data/lib/image_paradise/cfdg/luma_smiley.cfdg +563 -0
  284. data/lib/image_paradise/cfdg/maggi_stars.cfdg +11 -0
  285. data/lib/image_paradise/cfdg/mandelbrot_3.cfdg +111 -0
  286. data/lib/image_paradise/cfdg/martini.cfdg +147 -0
  287. data/lib/image_paradise/cfdg/material_studies.cfdg +172 -0
  288. data/lib/image_paradise/cfdg/math_eye.cfdg +30 -0
  289. data/lib/image_paradise/cfdg/matrix_freestyle.cfdg +127 -0
  290. data/lib/image_paradise/cfdg/maze.cfdg +211 -0
  291. data/lib/image_paradise/cfdg/meaculpo.cfdg +46 -0
  292. data/lib/image_paradise/cfdg/medieval_madness.cfdg +140 -0
  293. data/lib/image_paradise/cfdg/menage_a_trois.cfdg +77 -0
  294. data/lib/image_paradise/cfdg/micky_mouse.cfdg +75 -0
  295. data/lib/image_paradise/cfdg/mistletoe_forest.cfdg +62 -0
  296. data/lib/image_paradise/cfdg/mixed_simple_bubbles.cfdg +20 -0
  297. data/lib/image_paradise/cfdg/mod4g_starhole.cfdg +27 -0
  298. data/lib/image_paradise/cfdg/moebius.cfdg +57 -0
  299. data/lib/image_paradise/cfdg/molecules.cfdg +30 -0
  300. data/lib/image_paradise/cfdg/momos_blossom.cfdg +70 -0
  301. data/lib/image_paradise/cfdg/mona_lisa.cfdg +7937 -0
  302. data/lib/image_paradise/cfdg/more_arrows_in_quadcity.cfdg +49 -0
  303. data/lib/image_paradise/cfdg/more_cats.cfdg +1002 -0
  304. data/lib/image_paradise/cfdg/mosaic_for_2D_games.cfdg +69 -0
  305. data/lib/image_paradise/cfdg/mr_bezier.cfdg +195 -0
  306. data/lib/image_paradise/cfdg/mtree.cfdg +33 -0
  307. data/lib/image_paradise/cfdg/multiple_triangles.cfdg +13 -0
  308. data/lib/image_paradise/cfdg/mycel.cfdg +88 -0
  309. data/lib/image_paradise/cfdg/mytohexagone.cfdg +56 -0
  310. data/lib/image_paradise/cfdg/nature_is_not_like_that.cfdg +48 -0
  311. data/lib/image_paradise/cfdg/negative_flowers.cfdg +85 -0
  312. data/lib/image_paradise/cfdg/neo_town.cfdg +41 -0
  313. data/lib/image_paradise/cfdg/nesting_pattern.cfdg +34 -0
  314. data/lib/image_paradise/cfdg/neuronal_network.cfdg +94 -0
  315. data/lib/image_paradise/cfdg/neuronal_root.cfdg +46 -0
  316. data/lib/image_paradise/cfdg/night.cfdg +82 -0
  317. data/lib/image_paradise/cfdg/nightwalker.cfdg +23 -0
  318. data/lib/image_paradise/cfdg/no_xcape.cfdg +41 -0
  319. data/lib/image_paradise/cfdg/noise.cfdg +12 -0
  320. data/lib/image_paradise/cfdg/octopodi.cfdg +51 -0
  321. data/lib/image_paradise/cfdg/octopussy.cfdg +49 -0
  322. data/lib/image_paradise/cfdg/oldschool_cartoon_figure.cfdg +181 -0
  323. data/lib/image_paradise/cfdg/open_shapes.cfdg +240 -0
  324. data/lib/image_paradise/cfdg/orange_blossom.cfdg +57 -0
  325. data/lib/image_paradise/cfdg/orange_guts.cfdg +43 -0
  326. data/lib/image_paradise/cfdg/orange_monster.cfdg +42 -0
  327. data/lib/image_paradise/cfdg/organic.cfdg +30 -0
  328. data/lib/image_paradise/cfdg/ouo_happy_smiley.cfdg +45 -0
  329. data/lib/image_paradise/cfdg/output.png +0 -0
  330. data/lib/image_paradise/cfdg/pacman.cfdg +18 -0
  331. data/lib/image_paradise/cfdg/palmen.cfdg +162 -0
  332. data/lib/image_paradise/cfdg/pandoras_box.cfdg +53 -0
  333. data/lib/image_paradise/cfdg/papillon_butterfly.cfdg +28 -0
  334. data/lib/image_paradise/cfdg/patchwork.cfdg +32 -0
  335. data/lib/image_paradise/cfdg/pattern_grass.cfdg +110 -0
  336. data/lib/image_paradise/cfdg/peau_de_grenouille.cfdg +16 -0
  337. data/lib/image_paradise/cfdg/penrose_tiling.cfdg +102 -0
  338. data/lib/image_paradise/cfdg/pentagon.cfdg +68 -0
  339. data/lib/image_paradise/cfdg/pentagons.cfdg +25 -0
  340. data/lib/image_paradise/cfdg/perspective_tsunami.cfdg +20 -0
  341. data/lib/image_paradise/cfdg/phi_cloud.cfdg +23 -0
  342. data/lib/image_paradise/cfdg/picnic_birds_eye_view.cfdg +132 -0
  343. data/lib/image_paradise/cfdg/ping_pong.cfdg +29 -0
  344. data/lib/image_paradise/cfdg/pink_blossom.cfdg +58 -0
  345. data/lib/image_paradise/cfdg/piupole.cfdg +77 -0
  346. data/lib/image_paradise/cfdg/plotting.cfdg +61 -0
  347. data/lib/image_paradise/cfdg/point_onto_root.cfdg +64 -0
  348. data/lib/image_paradise/cfdg/primitive_reptile_pattern.cfdg +96 -0
  349. data/lib/image_paradise/cfdg/psycho_knot.cfdg +20 -0
  350. data/lib/image_paradise/cfdg/pyramide.cfdg +67 -0
  351. data/lib/image_paradise/cfdg/pythagoras_puzzle.cfdg +17 -0
  352. data/lib/image_paradise/cfdg/pythagorean_tree.cfdg +70 -0
  353. data/lib/image_paradise/cfdg/qimica.cfdg +64 -0
  354. data/lib/image_paradise/cfdg/quad_green_satellite.cfdg +53 -0
  355. data/lib/image_paradise/cfdg/quadcity.cfdg +24 -0
  356. data/lib/image_paradise/cfdg/quiet_wood_town.cfdg +195 -0
  357. data/lib/image_paradise/cfdg/r180.cfdg +26 -0
  358. data/lib/image_paradise/cfdg/r45.cfdg +26 -0
  359. data/lib/image_paradise/cfdg/r_square.cfdg +36 -0
  360. data/lib/image_paradise/cfdg/rads.cfdg +33 -0
  361. data/lib/image_paradise/cfdg/rainbow_black_hole.cfdg +9 -0
  362. data/lib/image_paradise/cfdg/rainbow_sun.cfdg +9 -0
  363. data/lib/image_paradise/cfdg/random_handwriting.cfdg +50 -0
  364. data/lib/image_paradise/cfdg/random_tile_shapes_jens_revisited.cfdg +146 -0
  365. data/lib/image_paradise/cfdg/rays_attack.cfdg +29 -0
  366. data/lib/image_paradise/cfdg/razpad.cfdg +20 -0
  367. data/lib/image_paradise/cfdg/rectangular_distortion.cfdg +169 -0
  368. data/lib/image_paradise/cfdg/recurse_path.cfdg +38 -0
  369. data/lib/image_paradise/cfdg/red_flurry.cfdg +64 -0
  370. data/lib/image_paradise/cfdg/red_horse_tail.cfdg +36 -0
  371. data/lib/image_paradise/cfdg/red_yellow_mosaic.cfdg +26 -0
  372. data/lib/image_paradise/cfdg/rendering_tests.cfdg +183 -0
  373. data/lib/image_paradise/cfdg/repeat_floor_tile_pattern.cfdg +153 -0
  374. data/lib/image_paradise/cfdg/repeat_tile.cfdg +160 -0
  375. data/lib/image_paradise/cfdg/retro_disc.cfdg +736 -0
  376. data/lib/image_paradise/cfdg/ring_growth_variation.cfdg +41 -0
  377. data/lib/image_paradise/cfdg/robot_nightlife.cfdg +25 -0
  378. data/lib/image_paradise/cfdg/rolled_firespiral.cfdg +34 -0
  379. data/lib/image_paradise/cfdg/rose.cfdg +44 -0
  380. data/lib/image_paradise/cfdg/round_tree.cfdg +121 -0
  381. data/lib/image_paradise/cfdg/rubiks_cube.cfdg +120 -0
  382. data/lib/image_paradise/cfdg/ruins.cfdg +19 -0
  383. data/lib/image_paradise/cfdg/sails_and_the_sea.cfdg +27 -0
  384. data/lib/image_paradise/cfdg/salt_crystals.cfdg +26 -0
  385. data/lib/image_paradise/cfdg/saturn.cfdg +105 -0
  386. data/lib/image_paradise/cfdg/scary_pot.cfdg +49 -0
  387. data/lib/image_paradise/cfdg/schematic_worm.cfdg +35 -0
  388. data/lib/image_paradise/cfdg/school_script.cfdg +359 -0
  389. data/lib/image_paradise/cfdg/seahorse.cfdg +78 -0
  390. data/lib/image_paradise/cfdg/seasons.cfdg +115 -0
  391. data/lib/image_paradise/cfdg/segmental_veins.cfdg +66 -0
  392. data/lib/image_paradise/cfdg/select_mayhem.cfdg +28 -0
  393. data/lib/image_paradise/cfdg/seven_folded_symmetry.cfdg +7 -0
  394. data/lib/image_paradise/cfdg/several_cats.cfdg +996 -0
  395. data/lib/image_paradise/cfdg/shadow_box.cfdg +49 -0
  396. data/lib/image_paradise/cfdg/shadowrun_google_maps.cfdg +66 -0
  397. data/lib/image_paradise/cfdg/shadowrun_nightline.cfdg +18 -0
  398. data/lib/image_paradise/cfdg/shards.cfdg +70 -0
  399. data/lib/image_paradise/cfdg/sheet_music.cfdg +213 -0
  400. data/lib/image_paradise/cfdg/shy_guy.cfdg +886 -0
  401. data/lib/image_paradise/cfdg/sierpinski1.cfdg +41 -0
  402. data/lib/image_paradise/cfdg/sierpinski2.cfdg +34 -0
  403. data/lib/image_paradise/cfdg/sierpinski_like_red_swirl.cfdg +46 -0
  404. data/lib/image_paradise/cfdg/sierpinsktri.cfdg +9 -0
  405. data/lib/image_paradise/cfdg/silk_flowers.cfdg +68 -0
  406. data/lib/image_paradise/cfdg/silk_scarf.cfdg +18 -0
  407. data/lib/image_paradise/cfdg/simple_cilia.cfdg +88 -0
  408. data/lib/image_paradise/cfdg/simple_circle_and_square.cfdg +7 -0
  409. data/lib/image_paradise/cfdg/simple_coloured_square.cfdg +38 -0
  410. data/lib/image_paradise/cfdg/simple_ferns.cfdg +40 -0
  411. data/lib/image_paradise/cfdg/simple_fish.cfdg +77 -0
  412. data/lib/image_paradise/cfdg/simple_orchid.cfdg +23 -0
  413. data/lib/image_paradise/cfdg/simple_rounded_colour_wheel.cfdg +10 -0
  414. data/lib/image_paradise/cfdg/simple_sheet_music.cfdg +27 -0
  415. data/lib/image_paradise/cfdg/sincos_pattern_2.cfdg +42 -0
  416. data/lib/image_paradise/cfdg/singing_birdy.cfdg +112 -0
  417. data/lib/image_paradise/cfdg/skyscraper.cfdg +85 -0
  418. data/lib/image_paradise/cfdg/small_golden_rectangle.cfdg +12 -0
  419. data/lib/image_paradise/cfdg/smells_like_layered.cfdg +43 -0
  420. data/lib/image_paradise/cfdg/snowflake.cfdg +26 -0
  421. data/lib/image_paradise/cfdg/snowstorm.cfdg +26 -0
  422. data/lib/image_paradise/cfdg/soar_on_wings.cfdg +8 -0
  423. data/lib/image_paradise/cfdg/soft_core.cfdg +26 -0
  424. data/lib/image_paradise/cfdg/soft_touch.cfdg +20 -0
  425. data/lib/image_paradise/cfdg/some_sort_of_tree.cfdg +57 -0
  426. data/lib/image_paradise/cfdg/spade_ball.cfdg +39 -0
  427. data/lib/image_paradise/cfdg/sparks.cfdg +39 -0
  428. data/lib/image_paradise/cfdg/sperm.cfdg +63 -0
  429. data/lib/image_paradise/cfdg/sphinx.cfdg +17 -0
  430. data/lib/image_paradise/cfdg/spiral_clusters.cfdg +29 -0
  431. data/lib/image_paradise/cfdg/spiral_cross.cfdg +27 -0
  432. data/lib/image_paradise/cfdg/spiral_star.cfdg +19 -0
  433. data/lib/image_paradise/cfdg/spiral_sun.cfdg +39 -0
  434. data/lib/image_paradise/cfdg/spirit.cfdg +47 -0
  435. data/lib/image_paradise/cfdg/splatter_tree.cfdg +61 -0
  436. data/lib/image_paradise/cfdg/spliced.cfdg +27 -0
  437. data/lib/image_paradise/cfdg/spring_parade.cfdg +105 -0
  438. data/lib/image_paradise/cfdg/sprinkle_explosion.cfdg +23 -0
  439. data/lib/image_paradise/cfdg/square_limit_one.cfdg +15 -0
  440. data/lib/image_paradise/cfdg/square_rose.cfdg +75 -0
  441. data/lib/image_paradise/cfdg/square_spiral4.cfdg +41 -0
  442. data/lib/image_paradise/cfdg/square_star.cfdg +39 -0
  443. data/lib/image_paradise/cfdg/squiggle.cfdg +54 -0
  444. data/lib/image_paradise/cfdg/stacked_blob.cfdg +27 -0
  445. data/lib/image_paradise/cfdg/star_explosion.cfdg +38 -0
  446. data/lib/image_paradise/cfdg/star_flower.cfdg +72 -0
  447. data/lib/image_paradise/cfdg/star_mosaic_2007.cfdg +51 -0
  448. data/lib/image_paradise/cfdg/starry_pines.cfdg +79 -0
  449. data/lib/image_paradise/cfdg/stars_tentacles.cfdg +28 -0
  450. data/lib/image_paradise/cfdg/starshape.cfdg +57 -0
  451. data/lib/image_paradise/cfdg/strange_antlers.cfdg +49 -0
  452. data/lib/image_paradise/cfdg/strange_carpet.cfdg +13 -0
  453. data/lib/image_paradise/cfdg/sunset_city.cfdg +112 -0
  454. data/lib/image_paradise/cfdg/sweep.cfdg +946 -0
  455. data/lib/image_paradise/cfdg/swimmers_sperms.cfdg +54 -0
  456. data/lib/image_paradise/cfdg/sword.cfdg +24 -0
  457. data/lib/image_paradise/cfdg/tangle.cfdg +25 -0
  458. data/lib/image_paradise/cfdg/tapestry.cfdg +40 -0
  459. data/lib/image_paradise/cfdg/tasty_loops.cfdg +97 -0
  460. data/lib/image_paradise/cfdg/tendril.cfdg +6 -0
  461. data/lib/image_paradise/cfdg/tentacle_tree.cfdg +57 -0
  462. data/lib/image_paradise/cfdg/terraforming.cfdg +87 -0
  463. data/lib/image_paradise/cfdg/test.cfdg +7 -0
  464. data/lib/image_paradise/cfdg/tetris.cfdg +123 -0
  465. data/lib/image_paradise/cfdg/textured_giraffes.cfdg +122 -0
  466. data/lib/image_paradise/cfdg/the_eye.cfdg +16 -0
  467. data/lib/image_paradise/cfdg/the_go_game.cfdg +81 -0
  468. data/lib/image_paradise/cfdg/the_secret.cfdg +52 -0
  469. data/lib/image_paradise/cfdg/the_third_eye.cfdg +42 -0
  470. data/lib/image_paradise/cfdg/thingy.cfdg +13 -0
  471. data/lib/image_paradise/cfdg/thorns.cfdg +26 -0
  472. data/lib/image_paradise/cfdg/too_many_notes.cfdg +155 -0
  473. data/lib/image_paradise/cfdg/top_down_plant_root.cfdg +43 -0
  474. data/lib/image_paradise/cfdg/top_view_tree.cfdg +79 -0
  475. data/lib/image_paradise/cfdg/transparent_heart.cfdg +31 -0
  476. data/lib/image_paradise/cfdg/tree.cfdg +68 -0
  477. data/lib/image_paradise/cfdg/tree_number_5.cfdg +28 -0
  478. data/lib/image_paradise/cfdg/tree_retro.cfdg +46 -0
  479. data/lib/image_paradise/cfdg/tree_spiral.cfdg +52 -0
  480. data/lib/image_paradise/cfdg/treematic.cfdg +42 -0
  481. data/lib/image_paradise/cfdg/tri_arc.cfdg +16 -0
  482. data/lib/image_paradise/cfdg/tri_squares.cfdg +7 -0
  483. data/lib/image_paradise/cfdg/tube_map.cfdg +112 -0
  484. data/lib/image_paradise/cfdg/turing_morphogenesis.cfdg +788 -0
  485. data/lib/image_paradise/cfdg/twisted_hex_grid.cfdg +26 -0
  486. data/lib/image_paradise/cfdg/twisty_triangel.cfdg +79 -0
  487. data/lib/image_paradise/cfdg/twizeeded.cfdg +19 -0
  488. data/lib/image_paradise/cfdg/uncontrolled_fungus.cfdg +36 -0
  489. data/lib/image_paradise/cfdg/underground.cfdg +72 -0
  490. data/lib/image_paradise/cfdg/underwater.cfdg +75 -0
  491. data/lib/image_paradise/cfdg/unicorn_boi.cfdg +20 -0
  492. data/lib/image_paradise/cfdg/unification_sign.cfdg +52 -0
  493. data/lib/image_paradise/cfdg/urban_connections.cfdg +44 -0
  494. data/lib/image_paradise/cfdg/us_flag.cfdg +109 -0
  495. data/lib/image_paradise/cfdg/v_null.cfdg +89 -0
  496. data/lib/image_paradise/cfdg/very_simple_flower.cfdg +45 -0
  497. data/lib/image_paradise/cfdg/very_simple_hexagon.cfdg +16 -0
  498. data/lib/image_paradise/cfdg/very_simple_octagon.cfg +13 -0
  499. data/lib/image_paradise/cfdg/vigorous_vine.cfdg +45 -0
  500. data/lib/image_paradise/cfdg/ville_topview.cfdg +70 -0
  501. data/lib/image_paradise/cfdg/vine.cfdg +176 -0
  502. data/lib/image_paradise/cfdg/vinyl.cfdg +12 -0
  503. data/lib/image_paradise/cfdg/violet_ribbons.cfdg +45 -0
  504. data/lib/image_paradise/cfdg/voronoi_2.cfdg +61 -0
  505. data/lib/image_paradise/cfdg/wald.cfdg +46 -0
  506. data/lib/image_paradise/cfdg/water_ink.cfdg +71 -0
  507. data/lib/image_paradise/cfdg/water_monster.cfdg +33 -0
  508. data/lib/image_paradise/cfdg/web.cfdg +53 -0
  509. data/lib/image_paradise/cfdg/weighting_demo.cfdg +16 -0
  510. data/lib/image_paradise/cfdg/weird_spots.cfdg +15 -0
  511. data/lib/image_paradise/cfdg/welcome.cfdg +109 -0
  512. data/lib/image_paradise/cfdg/where_do_you_want_to_go_today.cfdg +632 -0
  513. data/lib/image_paradise/cfdg/where_is_the_head.cfdg +28 -0
  514. data/lib/image_paradise/cfdg/where_to_go.cfdg +62 -0
  515. data/lib/image_paradise/cfdg/willow.cfdg +39 -0
  516. data/lib/image_paradise/cfdg/witch_poison.cfdg +58 -0
  517. data/lib/image_paradise/cfdg/wooden_floor.cfdg +95 -0
  518. data/lib/image_paradise/cfdg/writhing.cfdg +15 -0
  519. data/lib/image_paradise/cfdg/wrooom_cars.cfdg +124 -0
  520. data/lib/image_paradise/cfdg/xmas_code.cfdg +101 -0
  521. data/lib/image_paradise/cfdg/xmas_tree.cfdg +70 -0
  522. data/lib/image_paradise/cfdg/yellow_cactus.cfdg +52 -0
  523. data/lib/image_paradise/cfdg/yet_another_explosion.cfdg +46 -0
  524. data/lib/image_paradise/cfdg/yin_yang_taijitu_pattern.cfdg +44 -0
  525. data/lib/image_paradise/cfdg/yog.cfdg +27 -0
  526. data/lib/image_paradise/cfdg/yurbanis_m.cfdg +27 -0
  527. data/lib/image_paradise/cfdg/zen_tree.cfdg +79 -0
  528. data/lib/image_paradise/cfdg/ziggy_flowers.cfdg +44 -0
  529. data/lib/image_paradise/cfdg/zodiac.cfdg +43 -0
  530. data/lib/image_paradise/chunky_png/chunky_png.rb +54 -0
  531. data/lib/image_paradise/colours/colours.rb +46 -0
  532. data/lib/image_paradise/confree_generator/confree_generator.rb +791 -0
  533. data/lib/image_paradise/confree_generator/constants.rb +93 -0
  534. data/lib/image_paradise/constants/constants.rb +50 -0
  535. data/lib/image_paradise/constants/image_file_types.rb +26 -0
  536. data/lib/image_paradise/crop/crop.rb +429 -0
  537. data/lib/image_paradise/gm_support.rb +34 -0
  538. data/lib/image_paradise/graphs/accumulator_bar.rb +29 -0
  539. data/lib/image_paradise/graphs/area.rb +64 -0
  540. data/lib/image_paradise/graphs/bar.rb +117 -0
  541. data/lib/image_paradise/graphs/bar_conversion.rb +53 -0
  542. data/lib/image_paradise/graphs/base.rb +1392 -0
  543. data/lib/image_paradise/graphs/bezier.rb +45 -0
  544. data/lib/image_paradise/graphs/bullet.rb +115 -0
  545. data/lib/image_paradise/graphs/deprecated.rb +42 -0
  546. data/lib/image_paradise/graphs/dot.rb +129 -0
  547. data/lib/image_paradise/graphs/line.rb +328 -0
  548. data/lib/image_paradise/graphs/mini/bar.rb +42 -0
  549. data/lib/image_paradise/graphs/mini/legend.rb +109 -0
  550. data/lib/image_paradise/graphs/mini/pie.rb +42 -0
  551. data/lib/image_paradise/graphs/mini/side_bar.rb +41 -0
  552. data/lib/image_paradise/graphs/net.rb +133 -0
  553. data/lib/image_paradise/graphs/photo_bar.rb +106 -0
  554. data/lib/image_paradise/graphs/pie.rb +139 -0
  555. data/lib/image_paradise/graphs/scatter.rb +264 -0
  556. data/lib/image_paradise/graphs/scene.rb +216 -0
  557. data/lib/image_paradise/graphs/side_bar.rb +144 -0
  558. data/lib/image_paradise/graphs/side_stacked_bar.rb +116 -0
  559. data/lib/image_paradise/graphs/spider.rb +163 -0
  560. data/lib/image_paradise/graphs/stacked_area.rb +73 -0
  561. data/lib/image_paradise/graphs/stacked_bar.rb +68 -0
  562. data/lib/image_paradise/graphs/stacked_mixin.rb +30 -0
  563. data/lib/image_paradise/graphs/themes.rb +117 -0
  564. data/lib/image_paradise/graphs.rb +36 -0
  565. data/lib/image_paradise/graphviz/README.md +2 -0
  566. data/lib/image_paradise/graphviz/generate_graphviz_image.rb +276 -0
  567. data/lib/image_paradise/gui/gtk3/cfdg_widget/cfdg_widget.rb +1452 -0
  568. data/lib/image_paradise/gui/gtk3/cfdg_widget/connect_skeleton.rb +46 -0
  569. data/lib/image_paradise/gui/gtk3/image_editor/connect_skeleton.rb +126 -0
  570. data/lib/image_paradise/gui/gtk3/image_editor/image_editor.rb +2003 -0
  571. data/lib/image_paradise/identify.rb +184 -0
  572. data/lib/image_paradise/image_paradise.rb +153 -0
  573. data/lib/image_paradise/image_to_ascii/image_to_ascii.rb +187 -0
  574. data/lib/image_paradise/image_to_pdf/image_to_pdf.rb +99 -0
  575. data/lib/image_paradise/label/README.md +2 -0
  576. data/lib/image_paradise/label/simple_label.rb +206 -0
  577. data/lib/image_paradise/logo/IMGUR_LOGO.png +0 -0
  578. data/lib/image_paradise/project/project.rb +30 -0
  579. data/lib/image_paradise/requires/common_base_requires.rb +17 -0
  580. data/lib/image_paradise/requires/require_colours.rb +9 -0
  581. data/lib/image_paradise/requires/require_gtk_components.rb +8 -0
  582. data/lib/image_paradise/requires/require_image_to_ascii.rb +7 -0
  583. data/lib/image_paradise/requires/require_the_image_paradise_project.rb +42 -0
  584. data/lib/image_paradise/requires/require_toplevel_methods.rb +21 -0
  585. data/lib/image_paradise/rotate/README.md +2 -0
  586. data/lib/image_paradise/rotate/rotate.rb +124 -0
  587. data/lib/image_paradise/shell/interactive.rb +156 -0
  588. data/lib/image_paradise/svg/README.md +5 -0
  589. data/lib/image_paradise/svg/circle.rb +106 -0
  590. data/lib/image_paradise/svg/feature.rb +48 -0
  591. data/lib/image_paradise/svg/rectangle.rb +154 -0
  592. data/lib/image_paradise/svg/svg.rb +102 -0
  593. data/lib/image_paradise/toplevel_methods/add_black_border_to_this_image.rb +94 -0
  594. data/lib/image_paradise/toplevel_methods/create_animated_gif.rb +49 -0
  595. data/lib/image_paradise/toplevel_methods/crop.rb +29 -0
  596. data/lib/image_paradise/toplevel_methods/e.rb +16 -0
  597. data/lib/image_paradise/toplevel_methods/esystem.rb +19 -0
  598. data/lib/image_paradise/toplevel_methods/extract_text_from_this_image.rb +56 -0
  599. data/lib/image_paradise/toplevel_methods/file_related_code.rb +48 -0
  600. data/lib/image_paradise/toplevel_methods/flip_image_left_right.rb +59 -0
  601. data/lib/image_paradise/toplevel_methods/font_related_methods.rb +62 -0
  602. data/lib/image_paradise/toplevel_methods/greyscale_this_image.rb +76 -0
  603. data/lib/image_paradise/toplevel_methods/gui.rb +19 -0
  604. data/lib/image_paradise/toplevel_methods/help.rb +30 -0
  605. data/lib/image_paradise/toplevel_methods/interlace.rb +33 -0
  606. data/lib/image_paradise/toplevel_methods/is_an_image_file.rb +18 -0
  607. data/lib/image_paradise/toplevel_methods/make_this_image_transparent.rb +40 -0
  608. data/lib/image_paradise/toplevel_methods/menu.rb +110 -0
  609. data/lib/image_paradise/toplevel_methods/merge_these_images.rb +49 -0
  610. data/lib/image_paradise/toplevel_methods/mirror_image.rb +28 -0
  611. data/lib/image_paradise/toplevel_methods/misc.rb +1407 -0
  612. data/lib/image_paradise/toplevel_methods/negate.rb +36 -0
  613. data/lib/image_paradise/toplevel_methods/png_to_svg.rb +38 -0
  614. data/lib/image_paradise/toplevel_methods/quality.rb +34 -0
  615. data/lib/image_paradise/toplevel_methods/resized.rb +43 -0
  616. data/lib/image_paradise/toplevel_methods/roebe.rb +323 -0
  617. data/lib/image_paradise/toplevel_methods/thumbnail.rb +54 -0
  618. data/lib/image_paradise/toplevel_methods/to_png.rb +106 -0
  619. data/lib/image_paradise/toplevel_methods/wallpaper.rb +51 -0
  620. data/lib/image_paradise/toplevel_methods/write_this_text.rb +89 -0
  621. data/lib/image_paradise/utility_scripts/black_white.rb +92 -0
  622. data/lib/image_paradise/utility_scripts/create_new_image.rb +110 -0
  623. data/lib/image_paradise/utility_scripts/image_border.rb +226 -0
  624. data/lib/image_paradise/utility_scripts/image_gallery/image_gallery.rb +283 -0
  625. data/lib/image_paradise/utility_scripts/image_manipulations.rb +316 -0
  626. data/lib/image_paradise/utility_scripts/magic_card_border.rb +215 -0
  627. data/lib/image_paradise/utility_scripts/optimizer.rb +452 -0
  628. data/lib/image_paradise/utility_scripts/random_text_to_image.rb +364 -0
  629. data/lib/image_paradise/utility_scripts/text_on_image.rb +311 -0
  630. data/lib/image_paradise/utility_scripts/to_gif.rb +93 -0
  631. data/lib/image_paradise/utility_scripts/to_jpg.rb +82 -0
  632. data/lib/image_paradise/version/version.rb +19 -0
  633. data/lib/image_paradise/www/cfdg.cgi +25 -0
  634. data/lib/image_paradise/www/imagemagick/imagemagick.cgi +266 -0
  635. data/lib/image_paradise/yaml/README.md +2 -0
  636. data/lib/image_paradise/yaml/arc.yml +0 -0
  637. data/lib/image_paradise/yaml/circle.yml +6 -0
  638. data/lib/image_paradise/yaml/rectangle.yml +6 -0
  639. data/lib/image_paradise.rb +5 -0
  640. data/test/16x16_red_square_image_for_testing.png +0 -0
  641. data/test/misc/README.md +3 -0
  642. data/test/misc/testing_filling_up_with_circles.rb +65 -0
  643. data/test/testing_confree_generator.rb +8 -0
  644. data/test/testing_crop.rb +19 -0
  645. data/test/testing_image_magick_commands.rb +39 -0
  646. data/test/testing_image_paradise.rb +49 -0
  647. data/test/testing_the_svg_component.html +261 -0
  648. data/test/testing_the_svg_component.rb +106 -0
  649. metadata +760 -0
@@ -0,0 +1,2003 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ # === ImageParadise::GUI::Gtk::ImageEditor
6
+ # =========================================================================== #
7
+ # require 'image_paradise/gui/gtk3/image_editor/image_editor.rb'
8
+ # ImageParadise::GUI::Gtk::ImageEditor.run
9
+ # =========================================================================== #
10
+ require 'gtk_paradise/require_gtk3'
11
+
12
+ module ImageParadise
13
+
14
+ module GUI
15
+
16
+ module Gtk
17
+
18
+ class ImageEditor < ::Gtk::Box # === ImageParadise::GUI::Gtk::ImageEditor
19
+
20
+ require 'fileutils'
21
+
22
+ require 'gtk_paradise/requires/require_the_base_module.rb'
23
+ include ::Gtk::BaseModule
24
+
25
+ require 'image_paradise/gui/gtk3/image_editor/connect_skeleton.rb'
26
+ require 'image_paradise/toplevel_methods/add_black_border_to_this_image.rb'
27
+ require 'image_paradise/toplevel_methods/flip_image_left_right.rb'
28
+ require 'image_paradise/toplevel_methods/greyscale_this_image.rb'
29
+ require 'image_paradise/toplevel_methods/make_this_image_transparent.rb'
30
+ require 'image_paradise/toplevel_methods/misc.rb'
31
+ require 'image_paradise/toplevel_methods/negate.rb'
32
+ require 'image_paradise/toplevel_methods/resized.rb'
33
+ require 'image_paradise/toplevel_methods/thumbnail.rb'
34
+ require 'image_paradise/rotate/rotate.rb'
35
+ require 'image_paradise/image_to_ascii/image_to_ascii.rb'
36
+
37
+ # ========================================================================= #
38
+ # === NAMESPACE
39
+ # ========================================================================= #
40
+ NAMESPACE = inspect
41
+
42
+ # ========================================================================= #
43
+ # === TITLE
44
+ # ========================================================================= #
45
+ TITLE = 'Image-related manipulations'
46
+
47
+ # ========================================================================= #
48
+ # === WIDTH
49
+ # ========================================================================= #
50
+ WIDTH = '100% or minimum 800px'
51
+
52
+ # ========================================================================= #
53
+ # === HEIGHT
54
+ # ========================================================================= #
55
+ HEIGHT = '88% or minimum 620px'
56
+
57
+ # ========================================================================= #
58
+ # === USE_THIS_FONT
59
+ # ========================================================================= #
60
+ USE_THIS_FONT = :dejavu_condensed_18
61
+
62
+ # ========================================================================= #
63
+ # === SMALLER_FONT
64
+ # ========================================================================= #
65
+ SMALLER_FONT = :dejavu_condensed_16
66
+
67
+ # ========================================================================= #
68
+ # === HINT_MAGIC_CARD_CORNER
69
+ # ========================================================================= #
70
+ HINT_MAGIC_CARD_CORNER = 'Create a magic rounded border effect.'
71
+
72
+ # ========================================================================= #
73
+ # === HINT_MESSAGE_FOR_ROTATING_THE_IMAGE
74
+ # ========================================================================= #
75
+ HINT_MESSAGE_FOR_ROTATING_THE_IMAGE =
76
+ 'Click on this button in order to <b>rotate</b> the '\
77
+ 'image by the specified rotation-value. A leading - means '\
78
+ 'that the rotation will occur counter-clockwise.'
79
+
80
+ # ========================================================================= #
81
+ # === CLOCKWISE_ROTATION_SYMBOL
82
+ # ========================================================================= #
83
+ CLOCKWISE_ROTATION_SYMBOL = '↻'
84
+
85
+ # ========================================================================= #
86
+ # === HINT_FOR_BUTTON_OPEN_THE_IMAGE_IN_THE_BROWSER
87
+ # ========================================================================= #
88
+ HINT_FOR_BUTTON_OPEN_THE_IMAGE_IN_THE_BROWSER = 'Click on '\
89
+ 'this icon to open the image in the browser.'
90
+
91
+ # ========================================================================= #
92
+ # === HINT_FOR_BUTTON_UNDO
93
+ # ========================================================================= #
94
+ HINT_FOR_BUTTON_UNDO = 'Click on this button '\
95
+ 'in order to select the prior image in the '\
96
+ 'image-chain.'
97
+
98
+ # ========================================================================= #
99
+ # === initialize
100
+ # ========================================================================= #
101
+ def initialize(
102
+ commandline_arguments = ARGV,
103
+ run_already = true
104
+ )
105
+ super(:vertical)
106
+ reset
107
+ set_commandline_arguments(
108
+ commandline_arguments
109
+ )
110
+ run if run_already
111
+ end
112
+
113
+ # ========================================================================= #
114
+ # === reset (reset tag)
115
+ # ========================================================================= #
116
+ def reset
117
+ reset_the_internal_variables
118
+ # ======================================================================= #
119
+ # === @configuration
120
+ # ======================================================================= #
121
+ @configuration = [true, __dir__, NAMESPACE]
122
+ # ======================================================================= #
123
+ # === Set the title, width, height and the font in use.
124
+ # ======================================================================= #
125
+ title_width_height_font(TITLE, WIDTH, HEIGHT, USE_THIS_FONT)
126
+ use_gtk_paradise_project_css_file
127
+ infer_the_size_automatically
128
+ # ======================================================================= #
129
+ # === @path_to_the_image
130
+ # ======================================================================= #
131
+ @path_to_the_image = '/Depot/j/Unknown1.jpg'
132
+ # ======================================================================= #
133
+ # === @array_images
134
+ #
135
+ # This array will store the images the user has been working on.
136
+ # ======================================================================= #
137
+ @array_images = []
138
+ button_hover_colour '#cef0ea; /* This is a very light blue. */'
139
+ end
140
+
141
+ # ========================================================================= #
142
+ # === padding?
143
+ # ========================================================================= #
144
+ def padding?
145
+ 2
146
+ end
147
+
148
+ # ========================================================================= #
149
+ # === border_size?
150
+ # ========================================================================= #
151
+ def border_size?
152
+ 0
153
+ end
154
+
155
+ # ========================================================================= #
156
+ # === work_on_this_image?
157
+ # ========================================================================= #
158
+ def work_on_this_image?
159
+ @work_on_this_image
160
+ end
161
+
162
+ # ========================================================================= #
163
+ # === do_convert_the_image_to_an_ASCII_representation
164
+ # ========================================================================= #
165
+ def do_convert_the_image_to_an_ASCII_representation(
166
+ i = @entry_work_on_the_following_image.text?
167
+ )
168
+ a = ::ImageParadise::ImageToAscii.new(i)
169
+ puts a.to_ascii(color: true)
170
+ end
171
+
172
+ # ========================================================================= #
173
+ # === current_file_extension?
174
+ # ========================================================================= #
175
+ def current_file_extension?
176
+ File.extname(
177
+ @entry_work_on_the_following_image.text?
178
+ )
179
+ end
180
+
181
+ # ========================================================================= #
182
+ # === make_a_screenshot
183
+ # ========================================================================= #
184
+ def make_a_screenshot
185
+ esystem 'import -window root screenshot.png'
186
+ this_file_is_the_new_image_file('screenshot.png')
187
+ end; alias do_make_a_screenshot make_a_screenshot # === do_make_a_screenshot
188
+
189
+ # ========================================================================= #
190
+ # === path_to_the_image?
191
+ # ========================================================================= #
192
+ def path_to_the_image?
193
+ @path_to_the_image
194
+ end; alias main_image? path_to_the_image? # === main_image?
195
+ alias main_file? path_to_the_image? # === main_file?
196
+ alias work_on_which_image? path_to_the_image? # === work_on_which_image?
197
+ alias path_to_the_main_image? path_to_the_image? # === path_to_the_main_image?
198
+
199
+ # ========================================================================= #
200
+ # === width_of_the_main_image?
201
+ #
202
+ # This method depends on ImageMagick "convert" binary. It will return
203
+ # the width of the main image, as Integer.
204
+ # ========================================================================= #
205
+ def width_of_the_main_image?(
206
+ main_image = main_image?
207
+ )
208
+ `convert #{main_image} -print "%w" /dev/nul`.strip.dup.to_i
209
+ end
210
+
211
+ # ========================================================================= #
212
+ # === handle_mouse_click_event_for_the_main_image
213
+ # ========================================================================= #
214
+ def handle_mouse_click_event_for_the_main_image(widget, event)
215
+ x = event.x_coordinate?.round(0)
216
+ y = event.y_coordinate?.round(0)
217
+ # This does not work correctly yet; we need to find out how to
218
+ # get the x and y position from a sub-widget.
219
+ # y = (width_of_the_main_image? - y)
220
+ # ======================================================================= #
221
+ # Next sync it onto the correct entry.
222
+ # ======================================================================= #
223
+ @entry_crop3.set_text(x.to_s)
224
+ @entry_crop4.set_text(y.to_s)
225
+ end
226
+
227
+ # ========================================================================= #
228
+ # === menu
229
+ # ========================================================================= #
230
+ def menu(
231
+ i = @commandline_arguments
232
+ )
233
+ if i.is_a? Array
234
+ i.each {|entry| menu(entry) }
235
+ else
236
+ case i
237
+ when /help/
238
+ e 'No help option is documented so far.'
239
+ else
240
+ if i and i.start_with? 'file://'
241
+ i = i.to_s.dup
242
+ i.delete_prefix!('file://')
243
+ end
244
+ if i and File.exist?(i)
245
+ this_file_is_the_new_image_file(i)
246
+ end
247
+ end
248
+ end
249
+ end
250
+
251
+ # ========================================================================= #
252
+ # === do_greyscale_the_main_image
253
+ # ========================================================================= #
254
+ def do_greyscale_the_main_image(
255
+ i = @entry_work_on_the_following_image.text?
256
+ )
257
+ new_filename = increment_the_name_of_this_image(i)
258
+ # The old code in place was:
259
+ # 'greyscaled_image'+current_file_extension?
260
+ ::ImageParadise.grayscale_this_image(i, new_filename)
261
+ this_file_is_the_new_image_file(new_filename)
262
+ end
263
+
264
+ # ========================================================================= #
265
+ # === do_flip_the_main_image
266
+ #
267
+ # This will flip the image from left to right (or vice versa; is the
268
+ # same).
269
+ # ========================================================================= #
270
+ def do_flip_the_main_image
271
+ _ = main_image?
272
+ hash = {
273
+ use_this_as_the_filepath: increment_the_name_of_this_image(work_on_which_image?)
274
+ }
275
+ ImageParadise.flip_image_left_right(
276
+ _, hash
277
+ )
278
+ # ======================================================================= #
279
+ # Also designate it as the new main file in use.
280
+ # ======================================================================= #
281
+ if File.exist? hash[:use_this_as_the_filepath]
282
+ this_file_is_the_new_image_file(hash[:use_this_as_the_filepath])
283
+ end
284
+ end
285
+
286
+ # ========================================================================= #
287
+ # === do_resize_the_main_image
288
+ # ========================================================================= #
289
+ def do_resize_the_main_image(
290
+ i = @entry_work_on_the_following_image.text?,
291
+ by_n_percent = @entry_rotate_n_percent.text?
292
+ )
293
+ by_n_percent = by_n_percent.to_i
294
+ new_filename = ::ImageParadise.resized(
295
+ i, by_n_percent, increment_the_name_of_this_image(work_on_which_image?)
296
+ )
297
+ this_file_is_the_new_image_file(new_filename)
298
+ end
299
+
300
+ # ========================================================================= #
301
+ # === do_rotate_the_image
302
+ # ========================================================================= #
303
+ def do_rotate_the_image(
304
+ main_file = main_file?
305
+ )
306
+ _ = @entry_rotate_by_n_degrees.text?
307
+ new_filename = increment_the_name_of_this_image(main_file)
308
+ ::ImageParadise.rotate_this_image(
309
+ main_file,
310
+ _,
311
+ :default,
312
+ new_filename
313
+ )
314
+ if File.exist? new_filename
315
+ this_file_is_the_new_image_file(new_filename)
316
+ end
317
+ end
318
+
319
+ # ========================================================================= #
320
+ # === increment_the_name_of_this_image
321
+ #
322
+ # This method will change a name such as "foobar.png" to
323
+ # "foobar1.png", or "foobar1.png" to "foobar2.png" and so
324
+ # forth.
325
+ # ========================================================================= #
326
+ def increment_the_name_of_this_image(
327
+ i = 'foobar.png'
328
+ )
329
+ new_name = ''.dup
330
+ extname = File.extname(i) # e. g. => ".png"
331
+ basename = File.basename(i).delete_suffix(extname) # This is now e. g. 'foobar'
332
+ # ======================================================================= #
333
+ # In the past we just used the last character, but this will fail
334
+ # if we have something like "foobar_012.png". Thus, we must
335
+ # use a regex instead.
336
+ # ======================================================================= #
337
+ if basename =~ /\d+$/ # Ends with at the least one number. In this case, increment it by +1.
338
+ basename = ::ImageParadise.increment_this_number_by_one(basename)
339
+ new_name << basename
340
+ else # else append it
341
+ new_name << basename+'1'
342
+ end
343
+ # ======================================================================= #
344
+ # And append the extname again, e. g. ".png".
345
+ # ======================================================================= #
346
+ new_name << extname
347
+ return File.absolute_path(new_name)
348
+ end
349
+
350
+ # ========================================================================= #
351
+ # === return_widget_with_more_buttons_starting_with_the_sharpen_button
352
+ # ========================================================================= #
353
+ def return_widget_with_more_buttons_starting_with_the_sharpen_button
354
+ vbox = gtk_vbox
355
+ vbox.minimal(@button_sharpen_the_image, 1)
356
+ vbox.minimal(@button_solarize, 1)
357
+ vbox.minimal(@button_apply_the_wave_transformation, 1)
358
+ vbox.minimal(@button_change_the_constrast, 1)
359
+ vbox.minimal(@button_normalize_the_image, 1)
360
+ return vbox
361
+ end
362
+
363
+ # ========================================================================= #
364
+ # === return_vbox_containing_the_colour_filled_image_button_and_other_buttons
365
+ # ========================================================================= #
366
+ def return_vbox_containing_the_colour_filled_image_button_and_other_buttons
367
+ vbox = gtk_vbox
368
+ vbox.minimal(@button_colour_fill_this_image, 1)
369
+ vbox.minimal(@button_implode, 1)
370
+ vbox.minimal(@button_noise_up_the_image, 1)
371
+ vbox.minimal(@button_raise, 1)
372
+ vbox.minimal(@button_sepia_tone, 1)
373
+ return vbox
374
+ end
375
+
376
+ # ========================================================================= #
377
+ # === return_vbox_containing_the_round_the_corner_button_and_other_buttons
378
+ # ========================================================================= #
379
+ def return_vbox_containing_the_round_the_corner_button_and_other_buttons
380
+ vbox = gtk_vbox
381
+ vbox.minimal(@button_shear_effect, 1)
382
+ vbox.minimal(@button_create_a_thumbnail, 1)
383
+ vbox.minimal(@button_charcoal, 1)
384
+ vbox.minimal(@button_make_a_screenshot, 1)
385
+ return vbox
386
+ end
387
+
388
+ # ========================================================================= #
389
+ # === return_label_with_arrow_clock_wise_semi_circle
390
+ # ========================================================================= #
391
+ def return_label_with_arrow_clock_wise_semi_circle
392
+ _ = gtk_label(::Gtk::Emojis::ARROW_CLOCK_WISE_SEMI_CIRCLE)
393
+ _.width_height(40, 40)
394
+ return _
395
+ end
396
+
397
+ # ========================================================================= #
398
+ # === create_the_headerbar (top tag, menubar tag)
399
+ #
400
+ # This is the top-bar.
401
+ # ========================================================================= #
402
+ def create_the_headerbar
403
+ @header_bar = gtk_header_bar { :with_close_button }
404
+ @header_bar.spacing = 5
405
+ # @header_bar.title = 'Image-manipulation via ruby-gtk3 and ImageMagick'
406
+ button = gtk_button
407
+ button.on_clicked { do_open_a_local_image_file }
408
+ button.add(image_document_open)
409
+ button.hint = 'Open a local (image) file.'
410
+ @header_bar.add(button)
411
+
412
+ button = gtk_button
413
+ button.on_clicked { do_revert_the_last_action }
414
+ button.hint = HINT_FOR_BUTTON_UNDO
415
+ button.add(image_document_revert)
416
+ @header_bar.add(button)
417
+
418
+ label_with_arrow = return_label_with_arrow_clock_wise_semi_circle
419
+ event_box = gtk_event_box(label_with_arrow)
420
+ event_box.hint = HINT_FOR_BUTTON_OPEN_THE_IMAGE_IN_THE_BROWSER
421
+ event_box.on_clicked {
422
+ do_open_the_current_image_in_the_browser
423
+ }
424
+ @header_bar.add(event_box)
425
+
426
+ button = gtk_button
427
+ button.on_clicked { do_create_a_magic_card_corner_effect }
428
+ button.hint = HINT_MAGIC_CARD_CORNER
429
+ button.add(image_document_revert)
430
+ @header_bar.add(button)
431
+ end
432
+
433
+ # ========================================================================= #
434
+ # === create_the_spin_button
435
+ #
436
+ # The high number of 5000 is mostly because we may also want to create
437
+ # large, new images, so this would be width and height. The start
438
+ # values are lower - 3 and 1, respectively.
439
+ # ========================================================================= #
440
+ def create_the_spin_button
441
+ @spin_button_for_the_first_argument = gtk_spin_button(0, 5000, 1)
442
+ @spin_button_for_the_first_argument.center
443
+ @spin_button_for_the_first_argument.start_value = 3
444
+ @spin_button_for_the_first_argument.hint = "This is the value "\
445
+ "for any of the first arguments to a method. For example, "\
446
+ "if you need to specify a border size of 3, simply set this "\
447
+ "widget's value to 3."
448
+ @spin_button_for_the_second_argument = gtk_spin_button(0, 5000, 1)
449
+ @spin_button_for_the_second_argument.center
450
+ @spin_button_for_the_second_argument.start_value = 1
451
+ @spin_button_for_the_second_argument.hint = "This is the value "\
452
+ "for any of the first arguments to a method. For example, "\
453
+ "if you need to specify a border size of 3, simply set this "\
454
+ "widget's value to 3."
455
+ # @spin_button_for_the_first_argument.on_value_changed {|widget|
456
+ # }
457
+ end
458
+
459
+ # ========================================================================= #
460
+ # === create_the_scrolled_window_and_associated_event_box_for_the_box_for_the_main_image
461
+ #
462
+ # This method will create the central scrolled window containing our
463
+ # image as well.
464
+ # ========================================================================= #
465
+ def create_the_scrolled_window_and_associated_event_box_for_the_box_for_the_main_image
466
+ @event_box_for_the_main_image = gtk_event_box(
467
+ @box_for_the_main_image
468
+ )
469
+ @scrolled_window_for_the_box_for_the_main_image = gtk_scrolled_window(
470
+ @event_box_for_the_main_image
471
+ ) { :always }
472
+ @scrolled_window_for_the_box_for_the_main_image.set_size_request(
473
+ 680, 520
474
+ )
475
+ @event_box_for_the_main_image.signal_connect(:event) {|widget, event|
476
+ if is_mouse_button_event?(event)
477
+ case event.button
478
+ when 1,2,3 # These are all left-mouse-button events.
479
+ handle_mouse_click_event_for_the_main_image(widget, event)
480
+ end
481
+ end
482
+ }
483
+ end
484
+
485
+ # ========================================================================= #
486
+ # === return_draw_rectangle_widget
487
+ # ========================================================================= #
488
+ def return_draw_rectangle_widget
489
+ outer_hbox = gtk_hbox
490
+ inner_vbox = gtk_vbox
491
+ inner_vbox.minimal(@entry_rectangle_start_position1, 1)
492
+ inner_vbox.minimal(@entry_rectangle_start_position2, 1)
493
+ inner_vbox.minimal(@entry_rectangle_start_position3, 1)
494
+ inner_vbox.minimal(@entry_rectangle_start_position4, 1)
495
+ outer_hbox.minimal(@button_draw_a_rectangle, 1)
496
+ outer_hbox.minimal(inner_vbox, 1)
497
+ return outer_hbox
498
+ end
499
+
500
+ # ========================================================================= #
501
+ # === do_create_a_thumbnail_from_the_main_image
502
+ # ========================================================================= #
503
+ def do_create_a_thumbnail_from_the_main_image(
504
+ i = @entry_work_on_the_following_image.text?
505
+ )
506
+ new_filename = increment_the_name_of_this_image(i)
507
+ ::ImageParadise.thumbnail(
508
+ i, :default_width_and_size, new_filename
509
+ )
510
+ if File.exist? new_filename
511
+ this_file_is_the_new_image_file(new_filename)
512
+ end
513
+ end
514
+
515
+ # ========================================================================= #
516
+ # === do_make_the_main_image_transparent
517
+ # ========================================================================= #
518
+ def do_make_the_main_image_transparent(
519
+ i = path_to_the_main_image?
520
+ )
521
+ new_filename = increment_the_name_of_this_image(i)
522
+ result = ::ImageParadise.make_this_image_transparent(i, new_filename)
523
+ if result.is_a? Array
524
+ result = result.first
525
+ if File.exist? result
526
+ this_file_is_the_new_image_file(result)
527
+ end
528
+ end
529
+ end
530
+
531
+ require 'image_paradise/crop/crop.rb'
532
+ # ========================================================================= #
533
+ # === do_crop_the_image (crop tag)
534
+ #
535
+ # This method can be used to crop the main image.
536
+ # ========================================================================= #
537
+ def do_crop_the_image(
538
+ main_file = main_file?
539
+ )
540
+ string_to_use = @entry_crop1.text?+
541
+ 'x'+
542
+ @entry_crop2.text?+
543
+ '+'+
544
+ @entry_crop3.text?+
545
+ '+'+
546
+ @entry_crop4.text?
547
+ # ======================================================================= #
548
+ # We must query the data-set points to use. Thus we need four entries
549
+ # as shown above.
550
+ # ======================================================================= #
551
+ new_filename = increment_the_name_of_this_image(main_file)
552
+ ::ImageParadise.crop(
553
+ main_file,
554
+ string_to_use,
555
+ new_filename
556
+ )
557
+ if File.exist? new_filename
558
+ this_file_is_the_new_image_file(new_filename)
559
+ end
560
+ end
561
+
562
+ # ========================================================================= #
563
+ # === return_widget_containing_the_write_text_functionality
564
+ # ========================================================================= #
565
+ def return_widget_containing_the_write_text_functionality
566
+ vbox = gtk_vbox
567
+ @entry_write_this_text = gtk_entry
568
+ @entry_write_this_text.center
569
+ @entry_write_this_text.on_enter { do_write_text }
570
+ @entry_write_this_text.highlight_on_focus
571
+ @entry_x_coordinate = gtk_entry('10')
572
+ @entry_x_coordinate.hint = 'The <b>x coordinate</b>.'
573
+ @entry_x_coordinate.center
574
+ @entry_x_coordinate.on_enter { do_write_text }
575
+ @entry_y_coordinate = gtk_entry('10')
576
+ @entry_y_coordinate.hint = 'The <b>x coordinate</b>.'
577
+ @entry_y_coordinate.center
578
+ @entry_y_coordinate.on_enter { do_write_text }
579
+ another_small_vbox = gtk_vbox
580
+ another_small_vbox.minimal(text('Use this colour:'))
581
+ another_small_vbox.minimal(@entry_use_this_colour)
582
+ vbox.minimal(another_small_vbox, 1)
583
+ vbox.minimal(@button_shade, 1)
584
+ vbox.minimal(@button_write_text, 1)
585
+ vbox.minimal(@entry_write_this_text, 1)
586
+ hbox = gtk_hbox
587
+ hbox.maximal(@entry_x_coordinate, 1)
588
+ hbox.maximal(@entry_y_coordinate, 1)
589
+ vbox.minimal(
590
+ hbox, 1
591
+ )
592
+ return vbox
593
+ end
594
+
595
+ # ========================================================================= #
596
+ # === return_the_widget_containing_the_crop_button_and_the_associated_entries
597
+ # ========================================================================= #
598
+ def return_the_widget_containing_the_crop_button_and_the_associated_entries
599
+ vbox = gtk_vbox
600
+ vbox.minimal(@entry_crop1, 1)
601
+ vbox.minimal(@entry_crop2, 1)
602
+ vbox.minimal(@entry_crop3, 1)
603
+ vbox.minimal(@entry_crop4, 1)
604
+ vbox.minimal(@button_crop_the_image, 1)
605
+ return vbox
606
+ end
607
+
608
+ # ========================================================================= #
609
+ # === do_draw_a_line
610
+ # ========================================================================= #
611
+ def do_draw_a_line(
612
+ main_file = main_file?
613
+ )
614
+ output_file = increment_the_name_of_this_image(main_file)
615
+ _ = 'convert '+main_file.to_s+' '+
616
+ ::ImageParadise.return_draw_line(
617
+ [@entry_start_position1.text?, @entry_start_position2.text?],
618
+ [@entry_start_position3.text?, @entry_start_position4.text?],
619
+ return_colour_from_the_border_colour_entry,
620
+ strokewidth: @entry_strokewidth.text?
621
+ )+
622
+ ' '+
623
+ output_file
624
+ esystem _
625
+ if File.exist? output_file
626
+ this_file_is_the_new_image_file(output_file)
627
+ end
628
+ end
629
+
630
+ # ========================================================================= #
631
+ # === do_draw_a_rectangle
632
+ #
633
+ # This method will draw a rectangle onto the main image.
634
+ # ========================================================================= #
635
+ def do_draw_a_rectangle(
636
+ main_file = main_file?
637
+ )
638
+ output_file = increment_the_name_of_this_image(main_file)
639
+ _ = 'convert '+main_file.to_s+' '+
640
+ ::ImageParadise.return_draw_rectangle(
641
+ [@entry_rectangle_start_position1.text?, @entry_rectangle_start_position2.text?],
642
+ [@entry_rectangle_start_position3.text?, @entry_rectangle_start_position4.text?],
643
+ return_colour_from_the_border_colour_entry
644
+ )+
645
+ ' '+
646
+ output_file
647
+ esystem _
648
+ if File.exist? output_file
649
+ this_file_is_the_new_image_file(output_file)
650
+ end
651
+ end
652
+
653
+ # ========================================================================= #
654
+ # === return_the_widget_containing_the_draw_line_functionality
655
+ # ========================================================================= #
656
+ def return_the_widget_containing_the_draw_line_functionality
657
+ outer_hbox = gtk_hbox
658
+ inner_vbox = gtk_vbox
659
+ @entry_start_position1 = gtk_entry('10') { :do_center }
660
+ @entry_start_position2 = gtk_entry('10') { :do_center }
661
+ @entry_start_position3 = gtk_entry('70') { :do_center }
662
+ @entry_start_position4 = gtk_entry('90') { :do_center }
663
+ @entry_strokewidth = gtk_entry('1') { :do_center }
664
+ @entry_strokewidth.hint = 'This entry specifies the '\
665
+ '<b>stroke-width</b> of the line in use.'
666
+ spinner_button = gtk_spinner_button {{ start_point: 1 }}
667
+ spinner_button.connect_to(@entry_strokewidth) # Connect it to this widget.
668
+ hbox_containing_entry_strokewidth_and_spinner_button = gtk_hbox
669
+ hbox_containing_entry_strokewidth_and_spinner_button.minimal(@entry_strokewidth)
670
+ hbox_containing_entry_strokewidth_and_spinner_button.minimal(spinner_button)
671
+ inner_vbox.minimal(@entry_start_position1, 1)
672
+ inner_vbox.minimal(@entry_start_position2, 1)
673
+ inner_vbox.minimal(@entry_start_position3, 1)
674
+ inner_vbox.minimal(@entry_start_position4, 1)
675
+ inner_vbox.minimal(hbox_containing_entry_strokewidth_and_spinner_button, 1)
676
+ outer_hbox.minimal(@button_draw_a_line, 1)
677
+ outer_hbox.minimal(inner_vbox, 1)
678
+ return outer_hbox
679
+ end
680
+
681
+ # ========================================================================= #
682
+ # === update_the_info_box
683
+ #
684
+ # This method can be used to specifically update the widget showing
685
+ # information about the image - be it the width, the size, or any
686
+ # additional meta-data that may be stored in the image at hand.
687
+ # ========================================================================= #
688
+ def update_the_info_box(
689
+ main_image = main_image?
690
+ )
691
+ if File.exist? main_image
692
+ analysed_string = `convert #{main_image} -print "Resolution: <b>%wx%h px</b>" /dev/nul`.strip.dup
693
+ # Assume a String like: "Size: 819x453"
694
+ analysed_string << "\nFile size: "\
695
+ "<b>#{(File.size(main_image) / 1024.0).round(2)} kb</b>"
696
+ @label_resolution.set_text(analysed_string)
697
+ @label_resolution.do_markify
698
+ # ===================================================================== #
699
+ # Next, identify comments in the image at hand:
700
+ # ===================================================================== #
701
+ result = `identify -verbose #{main_image}`
702
+ if result.include?('Properties:') and result.include?(' comment: ')
703
+ scanned = result.scan(/ comment: (.+)$/).flatten
704
+ unless scanned.empty?
705
+ _ = scanned.first.to_s
706
+ if _.size > 15
707
+ _ = _[0 .. 15]+' [...]'
708
+ end
709
+ @label_comments_stored_in_the_image.set_text(
710
+ "Comment: \n<b>#{_}</b>"
711
+ )
712
+ @label_comments_stored_in_the_image.do_markify
713
+ end
714
+ end
715
+ end
716
+ end
717
+
718
+ # ========================================================================= #
719
+ # === do_negate_the_main_image
720
+ # ========================================================================= #
721
+ def do_negate_the_main_image(
722
+ i = @entry_work_on_the_following_image.text?
723
+ )
724
+ new_filename = increment_the_name_of_this_image(i)
725
+ ::ImageParadise.negate(i, new_filename)
726
+ this_file_is_the_new_image_file(new_filename)
727
+ end
728
+
729
+ # ========================================================================= #
730
+ # === do_write_text
731
+ #
732
+ # This method can be used to draw text onto the main image.
733
+ # ========================================================================= #
734
+ def do_write_text(
735
+ i = main_file?,
736
+ x_coordinate = @entry_x_coordinate.text?,
737
+ y_coordinate = @entry_y_coordinate.text?
738
+ )
739
+ output_file = increment_the_name_of_this_image(i)
740
+ _ = @entry_write_this_text.text?
741
+ if _.empty?
742
+ e 'No text has been assigned.'
743
+ return_popover(
744
+ 'Please assign some text.',
745
+ @entry_write_this_text,
746
+ 10
747
+ )
748
+ else
749
+ cmd = 'convert '+i+' -fill '+main_colour?+' -pointsize 30 -draw '\
750
+ '"text '+x_coordinate.to_s+','+y_coordinate.to_s+' \''+_+'\'" '.dup
751
+ cmd << '-font computerfont '
752
+ cmd << output_file
753
+ esystem cmd
754
+ if File.exist? output_file
755
+ this_is_the_new_image(output_file)
756
+ end
757
+ end
758
+ end
759
+
760
+ # ========================================================================= #
761
+ # === do_apply_a_circle_mask
762
+ # ========================================================================= #
763
+ def do_apply_a_circle_mask(
764
+ i = main_file?
765
+ )
766
+ output_file = increment_the_name_of_this_image(i)
767
+ ::ImageParadise.circle_masked(i, output_file)
768
+ if File.exist? output_file
769
+ this_is_the_new_image(File.absolute_path(output_file))
770
+ end
771
+ end
772
+
773
+ # ========================================================================= #
774
+ # === do_apply_a_torn_paper_effect
775
+ # ========================================================================= #
776
+ def do_apply_a_torn_paper_effect(
777
+ i = main_file?
778
+ )
779
+ output_file = increment_the_name_of_this_image(i)
780
+ ::ImageParadise.torn_paper(i, :default, output_file)
781
+ if File.exist? output_file
782
+ this_is_the_new_image(File.absolute_path(output_file))
783
+ end
784
+ end
785
+
786
+ # ========================================================================= #
787
+ # === do_apply_a_shadow_effect
788
+ # ========================================================================= #
789
+ def do_apply_a_shadow_effect(
790
+ i = main_file?,
791
+ colour_to_use = return_colour_from_the_border_colour_entry
792
+ )
793
+ output_file = increment_the_name_of_this_image(i)
794
+ ::ImageParadise.shadow(i, colour_to_use, output_file)
795
+ if File.exist? output_file
796
+ this_is_the_new_image(File.absolute_path(output_file))
797
+ end
798
+ end
799
+
800
+ # ========================================================================= #
801
+ # === do_chop_away_outer_pixels
802
+ # ========================================================================= #
803
+ def do_chop_away_outer_pixels(
804
+ i = main_file?
805
+ )
806
+ output_file = increment_the_name_of_this_image(i)
807
+ ::ImageParadise.chop_away_outer_pixels(
808
+ i,
809
+ @spin_button_for_the_first_argument.text?, # 5px
810
+ output_file
811
+ )
812
+ if File.exist? output_file
813
+ this_is_the_new_image(File.absolute_path(output_file))
814
+ end
815
+ end
816
+
817
+ # ========================================================================= #
818
+ # === do_charcoal_the_main_image
819
+ # ========================================================================= #
820
+ def do_charcoal_the_main_image(
821
+ i = main_file?,
822
+ radius_to_apply = @spin_button_for_the_first_argument.text?
823
+ )
824
+ output_file = increment_the_name_of_this_image(i)
825
+ ::ImageParadise.charcoal(
826
+ i,
827
+ radius_to_apply, # 5px
828
+ output_file
829
+ )
830
+ if File.exist? output_file
831
+ this_is_the_new_image(File.absolute_path(output_file))
832
+ end
833
+ end
834
+
835
+ # ========================================================================= #
836
+ # === do_colour_fill_the_image
837
+ # ========================================================================= #
838
+ def do_colour_fill_the_image(
839
+ i = main_file?,
840
+ percentage_to_apply = @spin_button_for_the_first_argument.text?
841
+ )
842
+ output_file = increment_the_name_of_this_image(i)
843
+ ::ImageParadise.colour_fill_this_image(
844
+ i,
845
+ main_colour?,
846
+ percentage_to_apply,
847
+ output_file
848
+ )
849
+ if File.exist? output_file
850
+ this_is_the_new_image(File.absolute_path(output_file))
851
+ end
852
+ end
853
+
854
+ # ========================================================================= #
855
+ # === return_colour_from_the_border_colour_entry
856
+ # ========================================================================= #
857
+ def return_colour_from_the_border_colour_entry
858
+ @entry_use_this_colour.text?
859
+ end; alias main_colour? return_colour_from_the_border_colour_entry # === main_colour?
860
+
861
+ # ========================================================================= #
862
+ # === do_implode_the_image
863
+ # ========================================================================= #
864
+ def do_implode_the_image(
865
+ i = main_file?,
866
+ percentage_to_apply = @spin_button_for_the_first_argument.text?
867
+ )
868
+ output_file = increment_the_name_of_this_image(i)
869
+ ::ImageParadise.implode(
870
+ i,
871
+ percentage_to_apply,
872
+ output_file
873
+ )
874
+ if File.exist? output_file
875
+ this_is_the_new_image(File.absolute_path(output_file))
876
+ end
877
+ end
878
+
879
+ # ========================================================================= #
880
+ # === do_noise_up_the_image
881
+ # ========================================================================= #
882
+ def do_noise_up_the_image(
883
+ i = main_file?,
884
+ noise_up_by_n = @spin_button_for_the_first_argument.text?
885
+ )
886
+ output_file = increment_the_name_of_this_image(i)
887
+ ::ImageParadise.noise(
888
+ i,
889
+ noise_up_by_n,
890
+ output_file
891
+ )
892
+ if File.exist? output_file
893
+ this_is_the_new_image(File.absolute_path(output_file))
894
+ end
895
+ end
896
+
897
+ # ========================================================================= #
898
+ # === do_raise_the_image
899
+ # ========================================================================= #
900
+ def do_raise_the_image(
901
+ i = main_file?,
902
+ noise_up_by_n = "#{@spin_button_for_the_first_argument.text?}x#{@spin_button_for_the_second_argument.text?}"
903
+ )
904
+ output_file = increment_the_name_of_this_image(i)
905
+ ::ImageParadise.raise(
906
+ i,
907
+ noise_up_by_n,
908
+ output_file
909
+ )
910
+ if File.exist? output_file
911
+ this_is_the_new_image(File.absolute_path(output_file))
912
+ end
913
+ end
914
+
915
+ # ========================================================================= #
916
+ # === do_apply_the_sepia_filter
917
+ # ========================================================================= #
918
+ def do_apply_the_sepia_filter(
919
+ i = main_file?,
920
+ up_by_n = "#{@spin_button_for_the_first_argument.text?}"
921
+ )
922
+ output_file = increment_the_name_of_this_image(i)
923
+ ::ImageParadise.sepia_filter(
924
+ i,
925
+ up_by_n,
926
+ output_file
927
+ )
928
+ if File.exist? output_file
929
+ this_is_the_new_image(File.absolute_path(output_file))
930
+ end
931
+ end
932
+
933
+ # ========================================================================= #
934
+ # === undo (undo tag)
935
+ #
936
+ # This is for the undo-operation.
937
+ # ========================================================================= #
938
+ def undo(
939
+ i = @array_images
940
+ )
941
+ if i.size > 0
942
+ i.pop
943
+ if i and i.last
944
+ this_is_the_new_image(i.last) if File.exist?(i.last)
945
+ end
946
+ else
947
+ e 'No image is stored in @array_images.'
948
+ end
949
+ end; alias do_revert_the_last_action undo # === do_revert_the_last_action
950
+
951
+ # ========================================================================= #
952
+ # === do_create_a_shade_effect
953
+ # ========================================================================= #
954
+ def do_create_a_shade_effect(
955
+ i = main_file?,
956
+ up_by_n = "#{@spin_button_for_the_first_argument.text?}x#{@spin_button_for_the_second_argument.text?}"
957
+ )
958
+ output_file = increment_the_name_of_this_image(i)
959
+ ::ImageParadise.shade_effect(
960
+ i,
961
+ up_by_n,
962
+ output_file
963
+ )
964
+ if File.exist? output_file
965
+ this_is_the_new_image(File.absolute_path(output_file))
966
+ end
967
+ end
968
+
969
+ # ========================================================================= #
970
+ # === do_sharpen_the_image_at_hand
971
+ # ========================================================================= #
972
+ def do_sharpen_the_image_at_hand(
973
+ i = main_file?,
974
+ up_by_n = "#{@spin_button_for_the_first_argument.text?}"
975
+ )
976
+ output_file = increment_the_name_of_this_image(i)
977
+ ::ImageParadise.sharpen(
978
+ i,
979
+ up_by_n,
980
+ output_file
981
+ )
982
+ if File.exist? output_file
983
+ this_is_the_new_image(File.absolute_path(output_file))
984
+ end
985
+ end
986
+
987
+ # ========================================================================= #
988
+ # === do_solarize_the_image
989
+ # ========================================================================= #
990
+ def do_solarize_the_image(
991
+ i = main_file?,
992
+ up_by_n = "#{@spin_button_for_the_first_argument.text?}"
993
+ )
994
+ output_file = increment_the_name_of_this_image(i)
995
+ ::ImageParadise.solarize(
996
+ i,
997
+ up_by_n,
998
+ output_file
999
+ )
1000
+ if File.exist? output_file
1001
+ this_is_the_new_image(File.absolute_path(output_file))
1002
+ end
1003
+ end
1004
+
1005
+ # ========================================================================= #
1006
+ # === do_apply_the_wave_transformation
1007
+ # ========================================================================= #
1008
+ def do_apply_the_wave_transformation(
1009
+ i = main_file?,
1010
+ noise_up_by_n = "#{@spin_button_for_the_first_argument.text?}x#{@spin_button_for_the_second_argument.text?}"
1011
+ )
1012
+ output_file = increment_the_name_of_this_image(i)
1013
+ ::ImageParadise.wave(
1014
+ i,
1015
+ noise_up_by_n,
1016
+ output_file
1017
+ )
1018
+ if File.exist? output_file
1019
+ this_is_the_new_image(File.absolute_path(output_file))
1020
+ end
1021
+ end
1022
+
1023
+ # ========================================================================= #
1024
+ # === do_change_the_contrast
1025
+ # ========================================================================= #
1026
+ def do_change_the_contrast(
1027
+ i = main_file?,
1028
+ noise_up_by_n = "#{@spin_button_for_the_first_argument.text?}"
1029
+ )
1030
+ output_file = increment_the_name_of_this_image(i)
1031
+ ::ImageParadise.contrast(
1032
+ i,
1033
+ noise_up_by_n,
1034
+ output_file
1035
+ )
1036
+ if File.exist? output_file
1037
+ this_is_the_new_image(File.absolute_path(output_file))
1038
+ end
1039
+ end
1040
+
1041
+ # ========================================================================= #
1042
+ # === do_normalize_the_image
1043
+ # ========================================================================= #
1044
+ def do_normalize_the_image(
1045
+ i = main_file?
1046
+ )
1047
+ output_file = increment_the_name_of_this_image(i)
1048
+ ::ImageParadise.normalize(
1049
+ i,
1050
+ output_file
1051
+ )
1052
+ if File.exist? output_file
1053
+ this_is_the_new_image(File.absolute_path(output_file))
1054
+ end
1055
+ end
1056
+
1057
+ # ========================================================================= #
1058
+ # === do_apply_a_shear_effect
1059
+ # ========================================================================= #
1060
+ def do_apply_a_shear_effect(
1061
+ i = path_to_the_main_image?,
1062
+ shear_factor = @spin_button_for_the_first_argument.value.to_s
1063
+ )
1064
+ new_filename = increment_the_name_of_this_image(i)
1065
+ new_filename = ::ImageParadise.shear(
1066
+ i, shear_factor.to_s+'x0', new_filename
1067
+ )
1068
+ if new_filename and File.exist? new_filename
1069
+ this_file_is_the_new_image_file(new_filename)
1070
+ end
1071
+ end
1072
+
1073
+ # ========================================================================= #
1074
+ # === do_create_a_new_image
1075
+ # ========================================================================= #
1076
+ def do_create_a_new_image(
1077
+ new_filename = 'foobar.png',
1078
+ width = first_value?,
1079
+ height = second_value?
1080
+ )
1081
+ esystem 'convert -size '+width.to_s+'x'+height.to_s+
1082
+ ' xc:'+@entry_background_colour_for_a_new_image.text?+
1083
+ ' '+new_filename
1084
+ if File.exist? new_filename
1085
+ this_file_is_the_new_image_file(new_filename)
1086
+ end
1087
+ end
1088
+
1089
+ # ========================================================================= #
1090
+ # === first_value?
1091
+ # ========================================================================= #
1092
+ def first_value?
1093
+ @spin_button_for_the_first_argument.text?.to_s
1094
+ end
1095
+
1096
+ # ========================================================================= #
1097
+ # === second_value?
1098
+ # ========================================================================= #
1099
+ def second_value?
1100
+ @spin_button_for_the_second_argument.text?.to_s
1101
+ end
1102
+
1103
+ # ========================================================================= #
1104
+ # === return_widget_containing_the_undo_button
1105
+ # ========================================================================= #
1106
+ def return_widget_containing_the_undo_button
1107
+ vbox = gtk_vbox
1108
+ hbox = gtk_hbox
1109
+ hbox.minimal(@button_open_file, 2)
1110
+ hbox.minimal(@button_create_a_new_image, 2)
1111
+ hbox.minimal(@button_convert_to_png_format, 2)
1112
+ vbox.minimal(hbox, 1)
1113
+ # ======================================================================= #
1114
+ # The undo-button will be in a hbox that is minimal, and centered.
1115
+ # ======================================================================= #
1116
+ hbox1 = gtk_hbox
1117
+ hbox1.minimal(@button_undo, 1)
1118
+ hbox1.centered_container
1119
+ vbox.minimal(hbox1, 2)
1120
+ _ = text("Background-colour \nfor a new image")
1121
+ _.use_this_font = :hack_16
1122
+ vbox.minimal(_, 1)
1123
+ vbox.minimal(@entry_background_colour_for_a_new_image, 1)
1124
+ return vbox
1125
+ end
1126
+
1127
+ # ========================================================================= #
1128
+ # === do_create_a_border_around_the_image
1129
+ #
1130
+ # The third argument defines which colour is to be used for the
1131
+ # border.
1132
+ # ========================================================================= #
1133
+ def do_create_a_border_around_the_image(
1134
+ i = path_to_the_main_image?,
1135
+ border_size = @spin_button_for_the_first_argument.value.to_s,
1136
+ use_this_colour = @entry_use_this_colour.text?
1137
+ )
1138
+ new_filename = increment_the_name_of_this_image(i)
1139
+ new_filename = ::ImageParadise.add_border_to_this_image(
1140
+ i, border_size, use_this_colour, new_filename
1141
+ )
1142
+ if new_filename and File.exist? new_filename
1143
+ this_file_is_the_new_image_file(new_filename)
1144
+ end
1145
+ end
1146
+
1147
+ # ========================================================================= #
1148
+ # === do_round_the_corner
1149
+ # ========================================================================= #
1150
+ def do_round_the_corner(
1151
+ i = main_file?
1152
+ )
1153
+ output_file = increment_the_name_of_this_image(i)
1154
+ ::ImageParadise.rounded_corner(i, output_file)
1155
+ if File.exist? output_file
1156
+ this_is_the_new_image(output_file)
1157
+ end
1158
+ end
1159
+
1160
+ # ========================================================================= #
1161
+ # === do_create_a_magic_card_corner_effect
1162
+ #
1163
+ # This combines two other effects.
1164
+ # ========================================================================= #
1165
+ def do_create_a_magic_card_corner_effect(
1166
+ i = main_file?
1167
+ )
1168
+ do_create_a_border_around_the_image(i, 10, :black)
1169
+ do_round_the_corner
1170
+ end
1171
+
1172
+ # ========================================================================= #
1173
+ # === do_randomly_change_the_colour_of_the_entry_keeping_track_of_the_colour
1174
+ # ========================================================================= #
1175
+ def do_randomly_change_the_colour_of_the_entry_keeping_track_of_the_colour(
1176
+ modify_this_entry = @entry_use_this_colour
1177
+ )
1178
+ modify_this_entry.set_text(
1179
+ random_html_colour.to_s
1180
+ )
1181
+ end
1182
+
1183
+ # ========================================================================= #
1184
+ # === do_create_a_drop_shadow_effect
1185
+ # ========================================================================= #
1186
+ def do_create_a_drop_shadow_effect(
1187
+ i = path_to_the_main_image?,
1188
+ use_this_colour = @entry_use_this_colour.text?
1189
+ )
1190
+ new_filename = increment_the_name_of_this_image(i)
1191
+ new_filename = ::ImageParadise.drop_shadow_effect(
1192
+ i, use_this_colour, new_filename
1193
+ )
1194
+ if new_filename and File.exist? new_filename
1195
+ this_file_is_the_new_image_file(new_filename)
1196
+ end
1197
+ end
1198
+
1199
+ # ========================================================================= #
1200
+ # === return_rotate_the_image_widget
1201
+ # ========================================================================= #
1202
+ def return_rotate_the_image_widget
1203
+ button_rotate_the_image_with_a_symbol = gtk_button(CLOCKWISE_ROTATION_SYMBOL)
1204
+ button_rotate_the_image_with_a_symbol.bblack1
1205
+ button_rotate_the_image_with_a_symbol.hint = HINT_MESSAGE_FOR_ROTATING_THE_IMAGE
1206
+ button_rotate_the_image_with_a_symbol.on_clicked {
1207
+ do_rotate_the_image
1208
+ }
1209
+ vbox = gtk_vbox
1210
+ vbox.minimal(@entry_rotate_by_n_degrees, 1)
1211
+ vbox.minimal(button_rotate_the_image_with_a_symbol, 1)
1212
+ vbox.maximal(@button_rotate_the_image, 1)
1213
+ return vbox
1214
+ end
1215
+
1216
+ # ========================================================================= #
1217
+ # === return_the_widget_containing_the_button_create_border
1218
+ # ========================================================================= #
1219
+ def return_the_widget_containing_the_button_create_border
1220
+ vbox = gtk_vbox
1221
+ vbox.maximal(@button_create_border, 1)
1222
+ vbox.maximal(@button_round_the_corner, 1)
1223
+ vbox.maximal(@button_create_magic_card_corner, 1)
1224
+ return vbox
1225
+ end
1226
+
1227
+ # ========================================================================= #
1228
+ # === create_the_main_image
1229
+ # ========================================================================= #
1230
+ def create_the_main_image
1231
+ # ======================================================================= #
1232
+ # Load up the image from a file. @work_on_this_image will be an
1233
+ # instance of Gtk::Image.
1234
+ # ======================================================================= #
1235
+ @work_on_this_image = image_from_file(@path_to_the_image)
1236
+ @work_on_this_image.bblack2
1237
+ @work_on_this_image.css_class('pad5px')
1238
+ this_file_is_the_new_image_file(@path_to_the_image)
1239
+ end
1240
+
1241
+ # ========================================================================= #
1242
+ # === create_the_button_boxes
1243
+ # ========================================================================= #
1244
+ def create_the_button_boxes
1245
+ @button_box1 = gtk_hbox
1246
+ @button_box2 = gtk_hbox
1247
+ end
1248
+
1249
+ # ========================================================================= #
1250
+ # === do_open_the_current_image_in_the_browser
1251
+ # ========================================================================= #
1252
+ def do_open_the_current_image_in_the_browser(
1253
+ i = @entry_work_on_the_following_image.text?
1254
+ )
1255
+ require 'open'
1256
+ Open.in_browser(i.to_s)
1257
+ end
1258
+
1259
+ # ========================================================================= #
1260
+ # === do_open_a_local_image_file (open tag)
1261
+ # ========================================================================= #
1262
+ def do_open_a_local_image_file
1263
+ create_a_new_file_chooser_dialog(self) {{
1264
+ start_dir: (Dir.pwd+'/').squeeze('/'),
1265
+ additional_directories: %w(
1266
+ /home/x/data/images/
1267
+ /home/x/data/images/NJOY/,
1268
+ /Depot/j/
1269
+ /Depot/jj/
1270
+ /Depot/jjj/
1271
+ )
1272
+ }}
1273
+ _ = ::Gtk.main_file?
1274
+ if _ and File.exist?(_)
1275
+ this_is_the_new_image(_)
1276
+ end
1277
+ end
1278
+
1279
+ # ========================================================================= #
1280
+ # === create_skeleton (create tag, skeleton tag)
1281
+ # ========================================================================= #
1282
+ def create_skeleton
1283
+ @box_for_the_main_image = gtk_hbox
1284
+ create_the_button_boxes
1285
+ create_the_buttons
1286
+ create_the_entries
1287
+ create_the_main_image
1288
+ create_the_headerbar
1289
+ end
1290
+
1291
+ # ========================================================================= #
1292
+ # === smaller_font?
1293
+ # ========================================================================= #
1294
+ def smaller_font?
1295
+ SMALLER_FONT
1296
+ end
1297
+
1298
+ # ========================================================================= #
1299
+ # === return_widget_containing_information_about_an_image
1300
+ #
1301
+ # This is the widget that contains information about the image at hand.
1302
+ # ========================================================================= #
1303
+ def return_widget_containing_information_about_an_image(
1304
+ main_image = main_image?
1305
+ )
1306
+ frame = gtk_frame
1307
+ frame.set_label('Information about the image: ')
1308
+ frame.set_border_width(8)
1309
+ frame.use_this_font = smaller_font?
1310
+ vbox = gtk_vbox
1311
+ @label_resolution = label('Resolution: ')
1312
+ @label_comments_stored_in_the_image = label
1313
+ vbox << @label_resolution
1314
+ vbox << @label_comments_stored_in_the_image
1315
+ vbox.use_this_font = smaller_font?
1316
+ frame << vbox
1317
+ return frame
1318
+ end
1319
+
1320
+ # ========================================================================= #
1321
+ # === create_the_entries (entries tag, entry tag)
1322
+ # ========================================================================= #
1323
+ def create_the_entries(
1324
+ length_of_the_selection = 300
1325
+ )
1326
+
1327
+ # ======================================================================= #
1328
+ # === @entry_work_on_the_following_image
1329
+ #
1330
+ # This entry contains the path to our current image.
1331
+ # ======================================================================= #
1332
+ @entry_work_on_the_following_image = gtk_entry
1333
+ @entry_work_on_the_following_image.set_max_length(150)
1334
+ @entry_work_on_the_following_image.center
1335
+ @entry_work_on_the_following_image.yellow_background
1336
+ @entry_work_on_the_following_image.read_only
1337
+ @entry_work_on_the_following_image.select_region(0, 1)
1338
+ @entry_work_on_the_following_image.css_class('border_steelblue_2px')
1339
+ @entry_work_on_the_following_image.on_enter_key {
1340
+ _ = @entry_work_on_the_following_image.text?
1341
+ if _ and File.exist?(_)
1342
+ this_file_is_the_new_image_file(_)
1343
+ end
1344
+ }
1345
+ @entry_work_on_the_following_image.make_scrollable
1346
+ @entry_work_on_the_following_image.on_scrolled {|widget, event|
1347
+ _ = widget.text?
1348
+ if scroll_up_event?(event) and !_.empty? and _.include?('.') and _.include?('/')
1349
+ # =================================================================== #
1350
+ # Scroll-up event:
1351
+ # =================================================================== #
1352
+ try_to_assign_a_new_random_image_from_the_base_directory_of_entry_work_on_the_following_image
1353
+ elsif scroll_down_event?(event) and !_.empty? and _.include?('.') and _.include?('/')
1354
+ # =================================================================== #
1355
+ # Scroll-down event:
1356
+ # =================================================================== #
1357
+ try_to_assign_a_new_random_image_from_the_base_directory_of_entry_work_on_the_following_image
1358
+ end
1359
+ }
1360
+ # ======================================================================= #
1361
+ # === @entry_rotate_by_n_degrees
1362
+ #
1363
+ # This is the entry associated with the rotate-image functionality.
1364
+ # ======================================================================= #
1365
+ @entry_rotate_by_n_degrees = gtk_entry('+90')
1366
+ @entry_rotate_by_n_degrees.on_enter {
1367
+ do_rotate_the_image
1368
+ }
1369
+ @entry_rotate_by_n_degrees.hint = 'Rotate by n degrees. You can use '\
1370
+ 'leading + or - to indicate forward-rotation or backwards '\
1371
+ 'rotation. Forward rotation means clock-wise rotation. Backwards '\
1372
+ 'rotation refers to counter-clock-wise rotation.'
1373
+ @entry_rotate_by_n_degrees.center
1374
+
1375
+ @entry_crop1 = gtk_entry(length_of_the_selection.to_s) {{ max_length: 8 }}
1376
+ @entry_crop1.center
1377
+ @entry_crop1.hint = 'Width of the new image'
1378
+
1379
+ @entry_crop2 = gtk_entry(length_of_the_selection.to_s) {{ max_length: 8 }}
1380
+ @entry_crop2.center
1381
+ @entry_crop2.hint = 'Height of the new image'
1382
+
1383
+ @entry_crop3 = gtk_entry('15') {{ max_length: 8 }}
1384
+ @entry_crop3.center
1385
+ @entry_crop3.hint = 'Left-start of the crop-rectangle'
1386
+
1387
+ @entry_crop4 = gtk_entry('15') {{ max_length: 8 }}
1388
+ @entry_crop4.center
1389
+ @entry_crop4.hint = 'Right-start of the crop-rectangle'
1390
+
1391
+ @entry_rectangle_start_position1 = gtk_entry('0')
1392
+ @entry_rectangle_start_position1.center
1393
+ @entry_rectangle_start_position1.hint =
1394
+ 'start-position of the x-axis'
1395
+ @entry_rectangle_start_position2 = gtk_entry('0')
1396
+ @entry_rectangle_start_position2.center
1397
+ @entry_rectangle_start_position2.hint =
1398
+ 'start-position of the y-axis'
1399
+ @entry_rectangle_start_position3 = gtk_entry('40')
1400
+ @entry_rectangle_start_position3.center
1401
+ @entry_rectangle_start_position3.hint =
1402
+ 'This designates the <b>width</b> of the rectangle.'
1403
+ @entry_rectangle_start_position4 = gtk_entry('140')
1404
+ @entry_rectangle_start_position4.center
1405
+ @entry_rectangle_start_position4.hint =
1406
+ 'This designates the <b>height</b> of the rectangle.'
1407
+
1408
+ @entry_background_colour_for_a_new_image = gtk_entry('white')
1409
+ @entry_background_colour_for_a_new_image.select_everything_on_click
1410
+ @entry_background_colour_for_a_new_image.center
1411
+ @entry_background_colour_for_a_new_image.hint =
1412
+ 'This entry designates the <b>background-color</b> '\
1413
+ 'for a new image.'
1414
+ @entry_background_colour_for_a_new_image.enable_scroll_events
1415
+ @entry_background_colour_for_a_new_image.on_scrolled {
1416
+ do_randomly_change_the_colour_of_the_entry_keeping_track_of_the_colour(
1417
+ @entry_background_colour_for_a_new_image
1418
+ )
1419
+ }
1420
+
1421
+ # ======================================================================= #
1422
+ # Next create the entry that contains which colour we should use, when
1423
+ # making a border.
1424
+ # ======================================================================= #
1425
+ @entry_use_this_colour = gtk_entry('black')
1426
+ @entry_use_this_colour.hint = 'This specifies the colour to use for '\
1427
+ 'any particular operation, if it makes sense in that context. The '\
1428
+ 'default will be black, so if you make a border, that border '\
1429
+ 'will be black. You can use the scrollwheel of the mouse '\
1430
+ 'to randomly pick another colour here.'
1431
+ @entry_use_this_colour.center
1432
+ @entry_use_this_colour.on_click_select_everything
1433
+ @entry_use_this_colour.enable_scroll_events
1434
+ @entry_use_this_colour.on_scrolled {
1435
+ do_randomly_change_the_colour_of_the_entry_keeping_track_of_the_colour
1436
+ }
1437
+ # @entry_use_this_colour.on_clicked {
1438
+ # do_create_a_border_around_the_image
1439
+ #}
1440
+ end
1441
+
1442
+ # ========================================================================= #
1443
+ # === cd_to_the_log_directory
1444
+ # ========================================================================= #
1445
+ def cd_to_the_log_directory(
1446
+ log_dir = ImageParadise.log_dir?
1447
+ )
1448
+ FileUtils.mkdir_p(log_dir) unless File.directory?(log_dir)
1449
+ cd log_dir
1450
+ end
1451
+
1452
+ # ========================================================================= #
1453
+ # === is_an_image_file?
1454
+ #
1455
+ # Note that this does not work on .gif files, as some of them may be
1456
+ # animated .gif files. One day this should be changed, if we can
1457
+ # find out which .gif file is animated - but for now this is not
1458
+ # the case.
1459
+ # ========================================================================= #
1460
+ def is_an_image_file?(i)
1461
+ %w( .png .jpg ).include?(File.extname(i))
1462
+ end
1463
+
1464
+ # ========================================================================= #
1465
+ # === try_to_assign_a_new_random_image_from_the_base_directory_of_entry_work_on_the_following_image
1466
+ # ========================================================================= #
1467
+ def try_to_assign_a_new_random_image_from_the_base_directory_of_entry_work_on_the_following_image
1468
+ _ = @entry_work_on_the_following_image.text?
1469
+ if _.include?('/')
1470
+ basedir = File.dirname(_)+'/'
1471
+ if File.directory? basedir
1472
+ random_file = Dir[basedir+'*'].select {|entry| is_an_image_file?(entry) }.sample
1473
+ if File.exist? random_file
1474
+ this_is_the_new_image(random_file) { :be_verbose }
1475
+ end
1476
+ end
1477
+ end
1478
+ end
1479
+
1480
+ # ========================================================================= #
1481
+ # === do_convert_to_png_format
1482
+ # ========================================================================= #
1483
+ def do_convert_to_png_format(
1484
+ i = main_file?
1485
+ )
1486
+ if i.end_with? '.png'
1487
+ e 'Can not convert as it is already a .png file.'
1488
+ else
1489
+ # ===================================================================== #
1490
+ # We prefer the absolute path, as it is easier to find out where
1491
+ # the new image file will reside at.
1492
+ # ===================================================================== #
1493
+ output_file = File.absolute_path(
1494
+ File.basename(i).delete_suffix(File.extname(i))+'.png'
1495
+ )
1496
+ esystem "convert #{i} #{output_file}"
1497
+ if output_file and File.exist?(output_file)
1498
+ this_is_the_new_image(File.absolute_path(output_file))
1499
+ end
1500
+ end
1501
+ end
1502
+
1503
+ # ========================================================================= #
1504
+ # === this_file_is_the_new_image_file
1505
+ #
1506
+ # This method is used to designate the current main image file in use.
1507
+ # ========================================================================= #
1508
+ def this_file_is_the_new_image_file(i, &block)
1509
+ i = i.to_s
1510
+ @path_to_the_image = File.absolute_path(i)
1511
+ if @path_to_the_image and File.exist?(@path_to_the_image)
1512
+ if block_given?
1513
+ yielded = yield
1514
+ case yielded
1515
+ # =================================================================== #
1516
+ # === :be_verbose
1517
+ # =================================================================== #
1518
+ when :be_verbose
1519
+ e "Assigning the image #{i} next."
1520
+ end
1521
+ end
1522
+ @work_on_this_image.set_file(
1523
+ @path_to_the_image
1524
+ )
1525
+ unless (@array_images.last == @path_to_the_image)
1526
+ @array_images << @path_to_the_image
1527
+ end
1528
+ @entry_work_on_the_following_image.set_text(@path_to_the_image)
1529
+ update_the_info_box(@path_to_the_image)
1530
+ end
1531
+ end; alias this_is_the_new_image this_file_is_the_new_image_file # === this_is_the_new_image
1532
+
1533
+ # ========================================================================= #
1534
+ # === create_the_buttons (buttons tag, button tag)
1535
+ #
1536
+ # All buttons will have bblack1, aka a black border.
1537
+ # ========================================================================= #
1538
+ def create_the_buttons
1539
+ create_the_spin_button
1540
+ @button_colour_button = gtk_colour_button
1541
+ @button_colour_button.bblack1
1542
+ @button_colour_button.pad2px
1543
+ @button_colour_button.signal_connect(:color_set) {
1544
+ # ===================================================================== #
1545
+ # When a colour is chosen by the user, we must sync it downwards.
1546
+ # ===================================================================== #
1547
+ @entry_use_this_colour.set_text(
1548
+ @button_colour_button.color.to_s
1549
+ )
1550
+ }
1551
+ @button_colour_button.color = '#616135358383' # Use a starting-colour.
1552
+ # ======================================================================= #
1553
+ # === Create the solarize button
1554
+ # ======================================================================= #
1555
+ @button_solarize = gtk_button('Solarize')
1556
+ @button_solarize.hint = 'This button will '\
1557
+ '"solarize", aka lighten-up, the given image at hand.'
1558
+ @button_solarize.on_clicked {
1559
+ do_solarize_the_image
1560
+ }
1561
+ # ======================================================================= #
1562
+ # === Create the to-png button
1563
+ # ======================================================================= #
1564
+ @button_convert_to_png_format = gtk_button('to_png')
1565
+ @button_convert_to_png_format.hint = 'This button will '\
1566
+ 'convert the file into a .png file (unless it already '\
1567
+ 'is a .png file).'
1568
+ @button_convert_to_png_format.on_clicked {
1569
+ do_convert_to_png_format
1570
+ }
1571
+ # ======================================================================= #
1572
+ # === Create the colour-fill button
1573
+ # ======================================================================= #
1574
+ @button_colour_fill_this_image = gtk_button('Colour fill the image')
1575
+ @button_colour_fill_this_image.hint = 'Click this button to '\
1576
+ 'fill the image with the designated colour.'
1577
+ @button_colour_fill_this_image.on_clicked {
1578
+ do_colour_fill_the_image
1579
+ }
1580
+ # ======================================================================= #
1581
+ # === Create the shade button
1582
+ # ======================================================================= #
1583
+ @button_shade = gtk_button('Create a shade-effect')
1584
+ @button_shade.hint = 'Click this button to '\
1585
+ 'create a shade effect onto the image at hand.'
1586
+ @button_shade.on_clicked {
1587
+ do_create_a_shade_effect
1588
+ }
1589
+ # ======================================================================= #
1590
+ # === Create the sharpen-image button
1591
+ # ======================================================================= #
1592
+ @button_sharpen_the_image = gtk_button('Sharpen the image')
1593
+ @button_sharpen_the_image.hint = 'Click this button to '\
1594
+ 'sharpen the image at hand.'
1595
+ @button_sharpen_the_image.on_clicked {
1596
+ do_sharpen_the_image_at_hand
1597
+ }
1598
+ # ======================================================================= #
1599
+ # === Create the implode button
1600
+ # ======================================================================= #
1601
+ @button_implode = gtk_button('Implode the image')
1602
+ @button_implode.hint = 'Click this button to '\
1603
+ 'implode onto the center of the image.'
1604
+ @button_implode.on_clicked {
1605
+ do_implode_the_image
1606
+ }
1607
+ # ======================================================================= #
1608
+ # === Create the change-contrast button
1609
+ # ======================================================================= #
1610
+ @button_change_the_constrast = gtk_button('Change the contrast')
1611
+ @button_change_the_constrast.hint = 'Click this button to '\
1612
+ 'change the contrast (increase or decrease) '\
1613
+ 'of the image.'
1614
+ @button_change_the_constrast.on_clicked {
1615
+ do_change_the_contrast
1616
+ }
1617
+ # ======================================================================= #
1618
+ # === Create the noise button
1619
+ # ======================================================================= #
1620
+ @button_noise_up_the_image = gtk_button('Noise-up the image')
1621
+ @button_noise_up_the_image.hint = 'Click this button to '\
1622
+ 'noise-up the image. This will either add or remove '\
1623
+ 'noise to an image. It can be used to smooth out an '\
1624
+ 'image, if these have slight imperfections - a bit '\
1625
+ 'like a blur-filter.'
1626
+ @button_noise_up_the_image.on_clicked {
1627
+ do_noise_up_the_image
1628
+ }
1629
+ # ======================================================================= #
1630
+ # === Create the round-the-corner button
1631
+ # ======================================================================= #
1632
+ @button_round_the_corner = gtk_button('Round the corner')
1633
+ @button_round_the_corner.hint = 'Click this to '\
1634
+ 'round the corner. This currently does not work for '\
1635
+ '<b>.jpg</b> files.'
1636
+ @button_round_the_corner.on_clicked {
1637
+ do_round_the_corner
1638
+ }
1639
+ # ======================================================================= #
1640
+ # === Create the write-text button
1641
+ # ======================================================================= #
1642
+ @button_write_text = gtk_button('Write text')
1643
+ @button_write_text.hint = 'This button commits the text stored below '\
1644
+ 'onto the main image.'
1645
+ @button_write_text.on_clicked {
1646
+ do_write_text
1647
+ }
1648
+ # ======================================================================= #
1649
+ # === Create the sepia-tone button
1650
+ # ======================================================================= #
1651
+ @button_sepia_tone = gtk_button('Sepia tone')
1652
+ @button_sepia_tone.hint = 'This button will sepia-change the image. '\
1653
+ 'This will look a bit like in old photographs.'
1654
+ @button_sepia_tone.on_clicked {
1655
+ do_apply_the_sepia_filter
1656
+ }
1657
+ # ======================================================================= #
1658
+ # === Create the open-file-button
1659
+ # ======================================================================= #
1660
+ @button_open_file = gtk_button('Open File')
1661
+ @button_open_file.hint = 'Click on this button '\
1662
+ 'in order to select a local .cfdg file to open.'
1663
+ @button_open_file.on_clicked {
1664
+ do_open_a_local_image_file
1665
+ }
1666
+ # ======================================================================= #
1667
+ # === Create the undo-button
1668
+ # ======================================================================= #
1669
+ @button_undo = gtk_bold_button('Undo')
1670
+ @button_undo.css_class 'clear_background'
1671
+ @button_undo.css_class('BG_lightsteelblue')
1672
+ @button_undo.hint = HINT_FOR_BUTTON_UNDO
1673
+ @button_undo.on_clicked {
1674
+ undo
1675
+ }
1676
+ # ======================================================================= #
1677
+ # === Button for the "draw-rectangle" functionality
1678
+ # ======================================================================= #
1679
+ @button_draw_a_rectangle = gtk_button("Draw a\nrectangle")
1680
+ @button_draw_a_rectangle.hint = 'Click on this button to draw '\
1681
+ 'a rectangle, specified via the start points to the right '\
1682
+ 'side.'
1683
+ @button_draw_a_rectangle.on_clicked {
1684
+ do_draw_a_rectangle
1685
+ }
1686
+ # ======================================================================= #
1687
+ # === Button for the "draw-line" functionality
1688
+ # ======================================================================= #
1689
+ @button_draw_a_line = gtk_button("Draw a\nline")
1690
+ @button_draw_a_line.hint = 'Click on this '\
1691
+ 'button to draw a line, specified via the '\
1692
+ 'start points to the right side.'
1693
+ @button_draw_a_line.on_clicked {
1694
+ do_draw_a_line
1695
+ }
1696
+ # ======================================================================= #
1697
+ # === Button for the "wave-transformation" functionality
1698
+ # ======================================================================= #
1699
+ @button_apply_the_wave_transformation = gtk_button('_Wave')
1700
+ @button_apply_the_wave_transformation.hint = 'Click on this '\
1701
+ 'button to apply a wave-transformation onto the image.'
1702
+ @button_apply_the_wave_transformation.on_clicked {
1703
+ do_apply_the_wave_transformation
1704
+ }
1705
+ # ======================================================================= #
1706
+ # === Button for the "normalize" functionality
1707
+ # ======================================================================= #
1708
+ @button_normalize_the_image = gtk_button('_Normalize')
1709
+ @button_normalize_the_image.hint = 'Click on this '\
1710
+ 'button to normalize the given image. This will often make an '\
1711
+ 'image "prettier". Give it a try!'
1712
+ @button_normalize_the_image.on_clicked {
1713
+ do_normalize_the_image
1714
+ }
1715
+ # ======================================================================= #
1716
+ # === Create the crop-button
1717
+ # ======================================================================= #
1718
+ @button_crop_the_image = gtk_button('Crop')
1719
+ @button_crop_the_image.hint = 'Click on this '\
1720
+ 'to crop the image.'
1721
+ @button_crop_the_image.on_clicked {
1722
+ do_crop_the_image
1723
+ }
1724
+ # ======================================================================= #
1725
+ # === Create the make-screenshot button
1726
+ # ======================================================================= #
1727
+ @button_make_a_screenshot = gtk_button('Screenshot')
1728
+ @button_make_a_screenshot.hint = 'This button will '\
1729
+ 'make a screenshot of what is currently shown on '\
1730
+ 'the screen.'
1731
+ @button_make_a_screenshot.on_clicked {
1732
+ do_make_a_screenshot
1733
+ }
1734
+ @button_make_a_screenshot.width_height(20, 20)
1735
+
1736
+ @button_greyscale_this_image = gtk_button('Grayscale the image')
1737
+ @button_greyscale_this_image.hint = 'This button will '\
1738
+ 'remove all colours from the image. It will thus be a '\
1739
+ 'grey, white and black image.'
1740
+ @button_greyscale_this_image.on_clicked {
1741
+ do_greyscale_the_main_image
1742
+ }
1743
+ #@button_to_ascii = gtk_button('Convert to ASCII')
1744
+ #@button_to_ascii.hint = 'This button will convert the image '\
1745
+ # 'to an ASCII approximation of said image.'
1746
+ #@button_to_ascii.on_clicked {
1747
+ # do_convert_the_image_to_an_ASCII_representation
1748
+ #}
1749
+ @button_flip_the_image = gtk_button('Flip horizontally')
1750
+ @button_flip_the_image.hint = 'Click on this button if '\
1751
+ 'you wish to flip the image at hand 180°.'
1752
+ @button_flip_the_image.on_clicked {
1753
+ do_flip_the_main_image
1754
+ }
1755
+ # ======================================================================= #
1756
+ # === Create the "Make transparent" button next
1757
+ # ======================================================================= #
1758
+ @button_make_the_image_transparent = gtk_button('Make transparent')
1759
+ @button_make_the_image_transparent.hint = 'Click on this button '\
1760
+ 'to make the image transparent.'
1761
+ @button_make_the_image_transparent.on_clicked {
1762
+ do_make_the_main_image_transparent
1763
+ }
1764
+ # ======================================================================= #
1765
+ # === Create the "circle mask" button next
1766
+ # ======================================================================= #
1767
+ @button_circle_mask = gtk_button('Circle mask')
1768
+ @button_circle_mask.hint = 'Click on this button '\
1769
+ 'to change the image to a roundish shap.'
1770
+ @button_circle_mask.on_clicked {
1771
+ do_apply_a_circle_mask
1772
+ }
1773
+ # ======================================================================= #
1774
+ # === Create the "raise" button next
1775
+ # ======================================================================= #
1776
+ @button_raise = gtk_button('Raise')
1777
+ @button_raise.hint = 'Click on this button '\
1778
+ 'to raise the image.'
1779
+ @button_raise.on_clicked {
1780
+ do_raise_the_image
1781
+ }
1782
+ # ======================================================================= #
1783
+ # === Create the "torn paper" button next
1784
+ # ======================================================================= #
1785
+ @button_torn_paper_effect = gtk_button('Torn paper effect')
1786
+ @button_torn_paper_effect.hint = 'Click on this button '\
1787
+ 'to change the image to display a torn-paper effect.'
1788
+ @button_torn_paper_effect.on_clicked {
1789
+ do_apply_a_torn_paper_effect
1790
+ }
1791
+ # ======================================================================= #
1792
+ # === Create the "shadow effect" button next
1793
+ # ======================================================================= #
1794
+ @button_shadow_effect = gtk_button('Shadow effect')
1795
+ @button_shadow_effect.hint = 'Click on this button '\
1796
+ 'to create a shadow-effect on the main image.'
1797
+ @button_shadow_effect.on_clicked {
1798
+ do_apply_a_shadow_effect
1799
+ }
1800
+ # ======================================================================= #
1801
+ # === Create the "shear effect" button next
1802
+ # ======================================================================= #
1803
+ @button_shear_effect = gtk_button('Shear effect')
1804
+ @button_shear_effect.hint = 'Click on this button '\
1805
+ 'to shear the main image.'
1806
+ @button_shear_effect.on_clicked {
1807
+ do_apply_a_shear_effect
1808
+ }
1809
+ # ======================================================================= #
1810
+ # === Create the "chop away n pixel" button next
1811
+ # ======================================================================= #
1812
+ @button_chop_away_n_pixel = gtk_button('Chop away n pixel')
1813
+ @button_chop_away_n_pixel.hint = 'Click on this button '\
1814
+ 'to chop away n pixel. n is determined by the entry '\
1815
+ 'for the border-size (in px).'
1816
+ @button_chop_away_n_pixel.on_clicked {
1817
+ do_chop_away_outer_pixels
1818
+ }
1819
+ # ======================================================================= #
1820
+ # === Create the negate-button next
1821
+ # ======================================================================= #
1822
+ @button_negate = gtk_button('_Negate')
1823
+ @button_negate.do_use_underline
1824
+ @button_negate.hint = 'Colour-flip the image (negate).'
1825
+ @button_negate.on_clicked {
1826
+ do_negate_the_main_image
1827
+ }
1828
+ # ======================================================================= #
1829
+ # === Create the drop-shadow effect
1830
+ # ======================================================================= #
1831
+ @button_create_drop_shadow_effect = gtk_button('Drop-shadow effect')
1832
+ @button_create_drop_shadow_effect.hint = 'Create a drop-shadow effect.'
1833
+ @button_create_drop_shadow_effect.on_clicked {
1834
+ do_create_a_drop_shadow_effect
1835
+ }
1836
+ # ======================================================================= #
1837
+ # === @button_rotate_the_image
1838
+ # ======================================================================= #
1839
+ @button_rotate_the_image = gtk_button('Rotate the image')
1840
+ @button_rotate_the_image.bblack1
1841
+ @button_rotate_the_image.hint = HINT_MESSAGE_FOR_ROTATING_THE_IMAGE
1842
+ @button_rotate_the_image.on_clicked {
1843
+ do_rotate_the_image
1844
+ }
1845
+ # ======================================================================= #
1846
+ # === Create the create-new-image-button next
1847
+ # ======================================================================= #
1848
+ @button_create_a_new_image = gtk_button('New Image')
1849
+ @button_create_a_new_image.hint = 'Create a new image. This will take '\
1850
+ 'width and height supplied by the two entries that allow you '\
1851
+ 'to input numbers, on the right hand side of this widget. The '\
1852
+ 'first value will become the width, the second value will become '\
1853
+ 'the height.'
1854
+ @button_create_a_new_image.on_clicked {
1855
+ do_create_a_new_image
1856
+ }
1857
+ # ======================================================================= #
1858
+ # === Create the create-border button next
1859
+ # ======================================================================= #
1860
+ @button_create_border = gtk_button('Create a _border')
1861
+ @button_create_border.apply_mnemonic
1862
+ @button_create_border.hint = 'Create a border '\
1863
+ 'around the image. The colour of this border '\
1864
+ 'defaults to black, but you can designate '\
1865
+ 'another colour in the entry that designates which colour '\
1866
+ 'will be used (on the right side of the main widget).'
1867
+ @button_create_border.on_clicked {
1868
+ do_create_a_border_around_the_image
1869
+ }
1870
+ @button_create_magic_card_corner = gtk_button('Magic card corner')
1871
+ @button_create_magic_card_corner.apply_mnemonic
1872
+ @button_create_magic_card_corner.hint = HINT_MAGIC_CARD_CORNER
1873
+ @button_create_magic_card_corner.on_clicked {
1874
+ do_create_a_magic_card_corner_effect
1875
+ }
1876
+ # ======================================================================= #
1877
+ # === Create the resize-image button
1878
+ # ======================================================================= #
1879
+ @button_resize_the_image = gtk_button('Resize the image')
1880
+ @button_resize_the_image.hint = 'Resize the image via '\
1881
+ 'this button.'
1882
+ @button_resize_the_image.on_clicked {
1883
+ do_resize_the_main_image
1884
+ }
1885
+ # ======================================================================= #
1886
+ # === Create the thumbnail-button
1887
+ # ======================================================================= #
1888
+ @button_create_a_thumbnail = gtk_button('Create a thumbnail')
1889
+ @button_create_a_thumbnail.disallow_resizing
1890
+ @button_create_a_thumbnail.width_height(80, 25)
1891
+ @button_create_a_thumbnail.hint = 'This will create '\
1892
+ 'a thumbnail from the image.'
1893
+ @button_create_a_thumbnail.on_clicked {
1894
+ do_create_a_thumbnail_from_the_main_image
1895
+ }
1896
+ # ======================================================================= #
1897
+ # === Create the charcoal-button
1898
+ # ======================================================================= #
1899
+ @button_charcoal = gtk_button('Charcoal')
1900
+ @button_charcoal.disallow_resizing
1901
+ @button_charcoal.width_height(80, 25)
1902
+ @button_charcoal.hint = 'This will '\
1903
+ 'apply a charcoal effect on the image.'
1904
+ @button_charcoal.on_clicked {
1905
+ do_charcoal_the_main_image
1906
+ }
1907
+ # ======================================================================= #
1908
+ # === Create the blur button next
1909
+ # ======================================================================= #
1910
+ @button_blur = gtk_button('Blur the image')
1911
+ @button_blur.hint = "Click on this button to apply a gaussian blur "\
1912
+ "onto the image at hand.\n"\
1913
+ "The number of pixels for this is "\
1914
+ "#{@spin_button_for_the_first_argument.text?}, at the least initially."
1915
+ @button_blur.on_clicked {
1916
+ do_blur_the_image
1917
+ }
1918
+ # ======================================================================= #
1919
+ # Uniformly style all buttons in this application.
1920
+ # ======================================================================= #
1921
+ return_all_buttons.each {|this_button|
1922
+ this_button.bblack1
1923
+ this_button.use_this_font = :dejavu_15
1924
+ }
1925
+ end
1926
+
1927
+ # ========================================================================= #
1928
+ # === do_blur_the_image
1929
+ # ========================================================================= #
1930
+ def do_blur_the_image(
1931
+ i = main_file?
1932
+ )
1933
+ output_file = increment_the_name_of_this_image(i)
1934
+ ::ImageParadise.blur(
1935
+ i,
1936
+ @spin_button_for_the_first_argument.text?, # 5px
1937
+ output_file
1938
+ )
1939
+ if File.exist? output_file
1940
+ this_is_the_new_image(File.absolute_path(output_file))
1941
+ end
1942
+ end
1943
+
1944
+ # ========================================================================= #
1945
+ # === run (run tag)
1946
+ # ========================================================================= #
1947
+ def run
1948
+ super()
1949
+ apply_the_css_string
1950
+ Thread.new { # This is a small hack. We avoid the "select everything" problem.
1951
+ sleep 0.001
1952
+ @entry_work_on_the_following_image.set_editable(true)
1953
+ cd_to_the_log_directory
1954
+ menu # Process the commandline arguments next.
1955
+ update_the_info_box
1956
+ }
1957
+ end
1958
+
1959
+ # ========================================================================= #
1960
+ # === return_hbox_containing_the_entry_work_on_the_following_image_and_the_open_in_browser_event_box
1961
+ # ========================================================================= #
1962
+ def return_hbox_containing_the_entry_work_on_the_following_image_and_the_open_in_browser_event_box
1963
+ hbox_containing_the_entry_work_on_the_following_image_and_the_open_in_browser_event_box = gtk_hbox
1964
+ _ = text('Work on the following image:')
1965
+ _.use_this_font = :deja_vu_15
1966
+ hbox_containing_the_entry_work_on_the_following_image_and_the_open_in_browser_event_box.minimal(
1967
+ _, 2
1968
+ )
1969
+ hbox_containing_the_entry_work_on_the_following_image_and_the_open_in_browser_event_box.maximal(
1970
+ @entry_work_on_the_following_image, 2
1971
+ )
1972
+ label_with_arrow = return_label_with_arrow_clock_wise_semi_circle
1973
+ event_box = gtk_event_box(label_with_arrow)
1974
+ event_box.hint = HINT_FOR_BUTTON_OPEN_THE_IMAGE_IN_THE_BROWSER
1975
+ event_box.on_clicked {
1976
+ do_open_the_current_image_in_the_browser
1977
+ }
1978
+ hbox_containing_the_entry_work_on_the_following_image_and_the_open_in_browser_event_box.minimal(
1979
+ event_box, 2
1980
+ )
1981
+ return hbox_containing_the_entry_work_on_the_following_image_and_the_open_in_browser_event_box
1982
+ end
1983
+
1984
+ # ========================================================================= #
1985
+ # === ImageParadise::GUI::Gtk::ImageEditor.run
1986
+ # ========================================================================= #
1987
+ def self.run(
1988
+ i = ARGV
1989
+ )
1990
+ require 'gtk_paradise/app/app.rb'
1991
+ _ = ::ImageParadise::GUI::Gtk::ImageEditor.new(i)
1992
+ r = ::Gtk.run
1993
+ r << _
1994
+ r.automatic_size_then_automatic_title
1995
+ r.enable_quick_exit
1996
+ r.top_left_then_run
1997
+ end
1998
+
1999
+ end; end; end; end
2000
+
2001
+ if __FILE__ == $PROGRAM_NAME
2002
+ ImageParadise::GUI::Gtk::ImageEditor.run(ARGV)
2003
+ end