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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +1 -0
- data/.yardoc/checksums +14 -0
- data/.yardoc/complete +0 -0
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/.yardoc/proxy_types +0 -0
- data/Gemfile +8 -0
- data/LICENSE +9 -0
- data/README.md +51 -0
- data/doc/ShatteredMachine.html +135 -0
- data/doc/ShatteredMachine/Brush.html +375 -0
- data/doc/ShatteredMachine/ChangeByte.html +367 -0
- data/doc/ShatteredMachine/Converter.html +327 -0
- data/doc/ShatteredMachine/Defect.html +369 -0
- data/doc/ShatteredMachine/Exchange.html +373 -0
- data/doc/ShatteredMachine/Glitcher.html +365 -0
- data/doc/ShatteredMachine/Io.html +569 -0
- data/doc/ShatteredMachine/Io/Paths.html +310 -0
- data/doc/ShatteredMachine/PixelSorter.html +381 -0
- data/doc/ShatteredMachine/RustyEngine.html +111 -0
- data/doc/ShatteredMachine/Sampler.html +361 -0
- data/doc/ShatteredMachine/Slim.html +389 -0
- data/doc/ShatteredMachine/Transpose.html +369 -0
- data/doc/ShatteredMachine/WrongFilter.html +367 -0
- data/doc/_index.html +288 -0
- data/doc/class_list.html +51 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +58 -0
- data/doc/css/style.css +497 -0
- data/doc/file_list.html +56 -0
- data/doc/frames.html +17 -0
- data/doc/index.html +123 -0
- data/doc/js/app.js +314 -0
- data/doc/js/full_list.js +216 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +275 -0
- data/doc/top-level-namespace.html +110 -0
- data/lib/rusty_engine/librusty_engine.dll +0 -0
- data/lib/rusty_engine/librusty_engine.dylib +0 -0
- data/lib/rusty_engine/librusty_engine.so +0 -0
- data/lib/rusty_engine/rusty_engine.rb +39 -0
- data/lib/shattered_machine.rb +11 -0
- data/lib/shattered_machine/brush.rb +28 -0
- data/lib/shattered_machine/change_byte.rb +41 -0
- data/lib/shattered_machine/converter.rb +20 -0
- data/lib/shattered_machine/defect.rb +38 -0
- data/lib/shattered_machine/exchange.rb +59 -0
- data/lib/shattered_machine/glitcher.rb +35 -0
- data/lib/shattered_machine/io.rb +74 -0
- data/lib/shattered_machine/pixel_sorter.rb +50 -0
- data/lib/shattered_machine/sampler.rb +100 -0
- data/lib/shattered_machine/slim.rb +55 -0
- data/lib/shattered_machine/transpose.rb +50 -0
- data/lib/shattered_machine/wrong_filter.rb +39 -0
- data/shattered_machine.gemspec +16 -0
- data/spec/brush_spec.rb +28 -0
- data/spec/change_byte_spec.rb +26 -0
- data/spec/converter_spec.rb +24 -0
- data/spec/defect_spec.rb +26 -0
- data/spec/exchange_spec.rb +26 -0
- data/spec/glitcher_spec.rb +26 -0
- data/spec/images/bar.PNG +0 -0
- data/spec/images/bar.jpeg +0 -0
- data/spec/images/foo.jpg +0 -0
- data/spec/images/foo.png +0 -0
- data/spec/images/fuzz.JPG +0 -0
- data/spec/images/pouet.JPEG +0 -0
- data/spec/io_spec.rb +74 -0
- data/spec/lib/rusty_engine_spec.rb +20 -0
- data/spec/pixel_sorter_spec.rb +26 -0
- data/spec/sampler_spec.rb +37 -0
- data/spec/slim_spec.rb +26 -0
- data/spec/spec_helper.rb +61 -0
- data/spec/transpose_spec.rb +26 -0
- data/spec/wrong_filter_spec.rb +26 -0
- 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
|
+
— 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> »
|
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
|
Binary file
|
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,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
|