shattered_machine 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +1 -0
  4. data/.yardoc/checksums +14 -0
  5. data/.yardoc/complete +0 -0
  6. data/.yardoc/object_types +0 -0
  7. data/.yardoc/objects/root.dat +0 -0
  8. data/.yardoc/proxy_types +0 -0
  9. data/Gemfile +8 -0
  10. data/LICENSE +9 -0
  11. data/README.md +51 -0
  12. data/doc/ShatteredMachine.html +135 -0
  13. data/doc/ShatteredMachine/Brush.html +375 -0
  14. data/doc/ShatteredMachine/ChangeByte.html +367 -0
  15. data/doc/ShatteredMachine/Converter.html +327 -0
  16. data/doc/ShatteredMachine/Defect.html +369 -0
  17. data/doc/ShatteredMachine/Exchange.html +373 -0
  18. data/doc/ShatteredMachine/Glitcher.html +365 -0
  19. data/doc/ShatteredMachine/Io.html +569 -0
  20. data/doc/ShatteredMachine/Io/Paths.html +310 -0
  21. data/doc/ShatteredMachine/PixelSorter.html +381 -0
  22. data/doc/ShatteredMachine/RustyEngine.html +111 -0
  23. data/doc/ShatteredMachine/Sampler.html +361 -0
  24. data/doc/ShatteredMachine/Slim.html +389 -0
  25. data/doc/ShatteredMachine/Transpose.html +369 -0
  26. data/doc/ShatteredMachine/WrongFilter.html +367 -0
  27. data/doc/_index.html +288 -0
  28. data/doc/class_list.html +51 -0
  29. data/doc/css/common.css +1 -0
  30. data/doc/css/full_list.css +58 -0
  31. data/doc/css/style.css +497 -0
  32. data/doc/file_list.html +56 -0
  33. data/doc/frames.html +17 -0
  34. data/doc/index.html +123 -0
  35. data/doc/js/app.js +314 -0
  36. data/doc/js/full_list.js +216 -0
  37. data/doc/js/jquery.js +4 -0
  38. data/doc/method_list.html +275 -0
  39. data/doc/top-level-namespace.html +110 -0
  40. data/lib/rusty_engine/librusty_engine.dll +0 -0
  41. data/lib/rusty_engine/librusty_engine.dylib +0 -0
  42. data/lib/rusty_engine/librusty_engine.so +0 -0
  43. data/lib/rusty_engine/rusty_engine.rb +39 -0
  44. data/lib/shattered_machine.rb +11 -0
  45. data/lib/shattered_machine/brush.rb +28 -0
  46. data/lib/shattered_machine/change_byte.rb +41 -0
  47. data/lib/shattered_machine/converter.rb +20 -0
  48. data/lib/shattered_machine/defect.rb +38 -0
  49. data/lib/shattered_machine/exchange.rb +59 -0
  50. data/lib/shattered_machine/glitcher.rb +35 -0
  51. data/lib/shattered_machine/io.rb +74 -0
  52. data/lib/shattered_machine/pixel_sorter.rb +50 -0
  53. data/lib/shattered_machine/sampler.rb +100 -0
  54. data/lib/shattered_machine/slim.rb +55 -0
  55. data/lib/shattered_machine/transpose.rb +50 -0
  56. data/lib/shattered_machine/wrong_filter.rb +39 -0
  57. data/shattered_machine.gemspec +16 -0
  58. data/spec/brush_spec.rb +28 -0
  59. data/spec/change_byte_spec.rb +26 -0
  60. data/spec/converter_spec.rb +24 -0
  61. data/spec/defect_spec.rb +26 -0
  62. data/spec/exchange_spec.rb +26 -0
  63. data/spec/glitcher_spec.rb +26 -0
  64. data/spec/images/bar.PNG +0 -0
  65. data/spec/images/bar.jpeg +0 -0
  66. data/spec/images/foo.jpg +0 -0
  67. data/spec/images/foo.png +0 -0
  68. data/spec/images/fuzz.JPG +0 -0
  69. data/spec/images/pouet.JPEG +0 -0
  70. data/spec/io_spec.rb +74 -0
  71. data/spec/lib/rusty_engine_spec.rb +20 -0
  72. data/spec/pixel_sorter_spec.rb +26 -0
  73. data/spec/sampler_spec.rb +37 -0
  74. data/spec/slim_spec.rb +26 -0
  75. data/spec/spec_helper.rb +61 -0
  76. data/spec/transpose_spec.rb +26 -0
  77. data/spec/wrong_filter_spec.rb +26 -0
  78. metadata +147 -0
@@ -0,0 +1,110 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>
7
+ Top Level Namespace
8
+
9
+ &mdash; Documentation by YARD 0.9.26
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" />
16
+
17
+ <script type="text/javascript">
18
+ pathId = "";
19
+ relpath = '';
20
+ </script>
21
+
22
+
23
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
24
+
25
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
26
+
27
+
28
+ </head>
29
+ <body>
30
+ <div class="nav_wrap">
31
+ <iframe id="nav" src="class_list.html?1"></iframe>
32
+ <div id="resizer"></div>
33
+ </div>
34
+
35
+ <div id="main" tabindex="-1">
36
+ <div id="header">
37
+ <div id="menu">
38
+
39
+ <a href="_index.html">Index</a> &raquo;
40
+
41
+
42
+ <span class="title">Top Level Namespace</span>
43
+
44
+ </div>
45
+
46
+ <div id="search">
47
+
48
+ <a class="full_list_link" id="class_list_link"
49
+ href="class_list.html">
50
+
51
+ <svg width="24" height="24">
52
+ <rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
53
+ <rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
54
+ <rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
55
+ </svg>
56
+ </a>
57
+
58
+ </div>
59
+ <div class="clear"></div>
60
+ </div>
61
+
62
+ <div id="content"><h1>Top Level Namespace
63
+
64
+
65
+
66
+ </h1>
67
+ <div class="box_info">
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+ </div>
80
+
81
+ <h2>Defined Under Namespace</h2>
82
+ <p class="children">
83
+
84
+
85
+ <strong class="modules">Modules:</strong> <span class='object_link'><a href="ShatteredMachine.html" title="ShatteredMachine (module)">ShatteredMachine</a></span>
86
+
87
+
88
+
89
+
90
+ </p>
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+ </div>
101
+
102
+ <div id="footer">
103
+ Generated on Sun May 23 13:30:10 2021 by
104
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
105
+ 0.9.26 (ruby-2.6.6).
106
+ </div>
107
+
108
+ </div>
109
+ </body>
110
+ </html>
Binary file
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+
5
+ module ShatteredMachine
6
+ module RustyEngine
7
+ extend FFI::Library
8
+ lib_name = "librusty_engine.#{FFI::Platform::LIBSUFFIX}"
9
+ ffi_lib File.expand_path(lib_name, __dir__)
10
+
11
+ # Params : input output
12
+ attach_function :convert, %i[string string], :void, { blocking: true }
13
+
14
+ # Params : input output proba min max direction
15
+ # Directions : 1 -> horizontal
16
+ # 2 -> vertical
17
+ # 3 -> horizontal_inverted
18
+ # 4 -> vertical_inverted
19
+ attach_function :brush, %i[string string string string string string], :void, { blocking: true }
20
+
21
+ # Params : input, output, proba, probability_area, direction, colors, color_with_proba
22
+ # Directions : 1 -> up_to_down
23
+ # 2 -> down_to_up
24
+ # 3 -> left_to_right
25
+ # 4 -> right_to_left
26
+ attach_function :slim, %i[string string string string string string string], :void, { blocking: true }
27
+
28
+ # Params : input, output, direction, smart_sorting, detection_type, min, max, multiple_range, min_2, max_2, sorting_by
29
+ # directions : 0 -> up_to_down
30
+ # 1 -> down_to_up
31
+ # 2 -> left_to_right
32
+ # 3 -> right_to_left
33
+ # detection_type : 0 -> hues
34
+ # 1 -> colors
35
+ # sorting_by : 0 -> hue
36
+ # 1 -> saturation
37
+ attach_function :sort, %i[string string string string string string string string string string string], :void, { blocking: true }
38
+ end
39
+ end
@@ -0,0 +1,11 @@
1
+ # lib/shattered_machine.rb
2
+ require 'shattered_machine/converter'
3
+ require 'shattered_machine/glitcher'
4
+ require 'shattered_machine/io'
5
+
6
+ module ShatteredMachine
7
+ VERSION = '0.0.1'
8
+
9
+ class << self
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../rusty_engine/rusty_engine'
4
+
5
+ module ShatteredMachine
6
+ # Brush pixels of a given png image.
7
+ # The logic for the brush come from the Rusty Engine.
8
+ class Brush
9
+ # @param options [Hash] options for brush algorithm
10
+ def initialize(options = {})
11
+ @direction = options[:direction] || :horizontal_inverted
12
+ @probability = (options[:probability] || 18).to_s
13
+ @min_pixels = (options[:min_pixels] || 1).to_s
14
+ @max_pixels = (options[:max_pixels] || 10).to_s
15
+ end
16
+
17
+ # @param input_image [string] path for image
18
+ # @param output_image [string] path for output brushed image
19
+ # @return [boolean] status of brush
20
+ def call(input_image, output_image)
21
+ ruby_to_rust_directions = { horizontal: '1', vertical: '2',
22
+ horizontal_inverted: '3',
23
+ vertical_inverted: '4' }
24
+ RustyEngine.brush(input_image, output_image, @probability, @min_pixels,
25
+ @max_pixels, ruby_to_rust_directions[@direction])
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pnglitch'
4
+ module ShatteredMachine
5
+ # Use the change byte algorithm from pnglitch on a given png image.
6
+ class ChangeByte
7
+ # @param options [Hash] options for change byte algorithm
8
+ def initialize(options = {})
9
+ @byte_numbers = options[:byte_numbers].to_i || 0
10
+ end
11
+
12
+ # @param input_image [string] path for image
13
+ # @param output_image [string] path for output changed byte image
14
+ # @return [boolean] status of change byte
15
+ def call(input_image, output_image)
16
+ PNGlitch.open(input_image) do |png|
17
+ filtered_glitch(png).save output_image
18
+ end
19
+ output_image
20
+ end
21
+
22
+ private
23
+
24
+ def filtered_glitch(png)
25
+ png.each_scanline do |scanline|
26
+ change_byte(scanline)
27
+ end
28
+ end
29
+
30
+ def change_byte(scanline)
31
+ scanline.register_filter_encoder do |data, prev|
32
+ data.size.times.reverse_each do |i|
33
+ x = data.getbyte(i)
34
+ v = prev ? prev.getbyte(i - @byte_numbers) : 0
35
+ data.setbyte(i, (x - v) & 0xff)
36
+ end
37
+ data
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../rusty_engine/rusty_engine'
4
+
5
+ module ShatteredMachine
6
+ # Convert jpg image in png image
7
+ class Converter
8
+ # @param io [ShatteredMachine::Io] Io containing paths for images to convert
9
+ def initialize(io)
10
+ @io = io
11
+ end
12
+
13
+ # @return [boolean] status of conversion
14
+ def call
15
+ @io.jpg_images.each do |jpg|
16
+ RustyEngine.convert(jpg.input, jpg.output)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pnglitch'
4
+ module ShatteredMachine
5
+ # Use the defect algorithm from pnglitch on a given png image.
6
+ class Defect
7
+ # @param options [Hash] options for defect algorithm
8
+ def initialize(options = {})
9
+ @random = options[:random] || false
10
+ @iterations = options[:iterations] || 1
11
+ end
12
+
13
+ # @param input_image [string] path for input image
14
+ # @param output_image [string] path for output defected image
15
+ # @return [boolean] status of defect
16
+ def call(input_image, output_image)
17
+ PNGlitch.open(input_image) do |png|
18
+ filtered_glitch(png).save output_image
19
+ end
20
+ output_image
21
+ end
22
+
23
+ private
24
+
25
+ def filtered_glitch(png)
26
+ png.glitch do |data|
27
+ if !@random
28
+ data.gsub(/\d/, '')
29
+ else
30
+ @iterations.times do
31
+ data[rand(data.size)] = ''
32
+ end
33
+ data
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pnglitch'
4
+ module ShatteredMachine
5
+ # Use the exchange algorithm from pnglitch on a given png image.
6
+ class Exchange
7
+ # @param options [Hash] options for exchange algorithm
8
+ def initialize(options = {})
9
+ @filter = define_filter(options[:filter]) || 'average'
10
+ @random = options[:random] || false
11
+ @range = options[:range] || 0
12
+ @seed = options[:seed] || 'x'
13
+ end
14
+
15
+ # @param input_image [string] path for input image
16
+ # @param output_image [string] path for output exchanged image
17
+ # @return [boolean] status of exchange
18
+ def call(input_image, output_image)
19
+ PNGlitch.open(input_image) do |png|
20
+ filtered_glitch(png, @filter).save output_image
21
+ end
22
+ output_image
23
+ end
24
+
25
+ private
26
+
27
+ def define_filter(filter_from_options)
28
+ return filter_from_options unless filter_from_options == 'random'
29
+
30
+ available_filters = %w(none sub up average paeth)
31
+ available_filters[rand(5)]
32
+ end
33
+
34
+ def give_me_a_letter(index = rand(26))
35
+ ('a'..'z').to_a[index]
36
+ end
37
+
38
+ def filtered_glitch(png, custom_filter)
39
+ png.each_scanline do |scanline|
40
+ scanline.change_filter custom_filter
41
+ end
42
+ png.glitch do |data|
43
+ exchange_data(data)
44
+ end
45
+ end
46
+
47
+ def exchange_data(data)
48
+ if @range.zero?
49
+ letter = @random ? give_me_a_letter.to_s : @seed
50
+ data.gsub(/\d/, letter)
51
+ else
52
+ @range.times do
53
+ data[rand(data.size)] = give_me_a_letter.to_s
54
+ end
55
+ data
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShatteredMachine
4
+ # Main class to call from glitching image.
5
+ class Glitcher
6
+ # @param glitch_library [string] Name of the library to call to glitch image
7
+ # @param io [ShatteredMachine::Io] Io containing paths for images to glitch
8
+ # @param options [Hash] options for the glitch algorithm
9
+ def initialize(glitch_library, io, options = {})
10
+ @glitch_library = glitch_library
11
+ @io = io
12
+ @options = options
13
+ end
14
+
15
+ # @return [boolean] status of glitching
16
+ def call
17
+ @io.png_images.each do |item|
18
+ create_glitch(item.input, item.output)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def glitch_library_name
25
+ "ShatteredMachine::#{@glitch_library}"
26
+ end
27
+
28
+ def create_glitch(input_path, output_filename)
29
+ Object.const_get(glitch_library_name)
30
+ .new(@options)
31
+ .call(input_path, output_filename)
32
+ return true
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShatteredMachine
4
+ # Find all png or jpg image in a given directory.
5
+ # Generate output filename that doesn't overwrite existing file.
6
+ class Io
7
+ attr_accessor :output_filename
8
+
9
+ PNG_EXTENSIONS = ['.png', '.PNG'].freeze
10
+ JPG_EXTENSIONS = ['.jpg', '.jpeg', '.JPG', '.JPEG'].freeze
11
+ Paths = Struct.new(:input, :output)
12
+
13
+ # @param input_path [string] input file or directory
14
+ # @param output_folder [string] output directory
15
+ # @param output_filename [string] output file name
16
+ def initialize(input_path, output_folder, output_filename)
17
+ @input_path = input_path
18
+ @output_folder = output_folder
19
+ @output_filename = output_filename
20
+ end
21
+
22
+ # @return [Array<Paths>] list of all png images in input_path
23
+ def png_images
24
+ return single_image_io if extension_included?(PNG_EXTENSIONS, @input_path)
25
+
26
+ images_in_directory(PNG_EXTENSIONS).map do |img|
27
+ Paths.new("#{@input_path}/#{img}", generate_output_filename(img))
28
+ end
29
+ end
30
+
31
+ # @return [Array<Paths>] list of all jpg images in input_path
32
+ def jpg_images
33
+ return single_image_io if extension_included?(JPG_EXTENSIONS, @input_path)
34
+
35
+ images_in_directory(JPG_EXTENSIONS).map do |img|
36
+ Paths.new("#{@input_path}/#{img}", generate_output_filename(img))
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def single_image_io
43
+ [Paths.new(@input_path, generate_output_filename)]
44
+ end
45
+
46
+ def generate_output_filename(img = '')
47
+ img_name = File.basename(img, File.extname(img))
48
+ if File.file?("#{@output_folder}/#{@output_filename}#{img_name}.png")
49
+ "#{@output_folder}/#{@output_filename}#{img_name}_#{time_utc_string}.png"
50
+ else
51
+ "#{@output_folder}/#{@output_filename}#{img_name}.png"
52
+ end
53
+ end
54
+
55
+ def time_utc_string
56
+ t = Time.now.getutc
57
+ t.strftime '%Y%m%d_%H%M%S'
58
+ end
59
+
60
+ def extension_included?(extensions, file)
61
+ extensions.include? File.extname(file)
62
+ end
63
+
64
+ def images_in_directory(extensions)
65
+ children = []
66
+ Dir.foreach(@input_path) do |file|
67
+ next unless extension_included?(extensions, file)
68
+
69
+ children << file
70
+ end
71
+ children
72
+ end
73
+ end
74
+ end