shattered_machine 0.0.6 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +34 -0
- data/Gemfile +1 -1
- data/README.md +19 -0
- data/doc/ShatteredMachine.html +5 -7
- data/doc/ShatteredMachine/Brush.html +2 -2
- data/doc/ShatteredMachine/ChangeByte.html +1 -1
- data/doc/ShatteredMachine/Converter.html +2 -2
- data/doc/ShatteredMachine/Defect.html +1 -1
- data/doc/ShatteredMachine/Exchange.html +1 -1
- data/doc/ShatteredMachine/Glitcher.html +13 -13
- data/doc/ShatteredMachine/Io.html +23 -44
- data/doc/ShatteredMachine/Io/Paths.html +1 -187
- data/doc/ShatteredMachine/PixelSorter.html +2 -2
- data/doc/ShatteredMachine/ProgressivePixelSorter.html +318 -0
- data/doc/ShatteredMachine/Sampler.html +14 -29
- data/doc/ShatteredMachine/Slim.html +3 -3
- data/doc/ShatteredMachine/Transpose.html +1 -1
- data/doc/ShatteredMachine/WrongFilter.html +1 -1
- data/doc/_index.html +5 -13
- data/doc/class_list.html +1 -1
- data/doc/index.html +50 -17
- data/doc/method_list.html +48 -48
- data/doc/top-level-namespace.html +1 -1
- data/icon.png +0 -0
- data/icon.svg +122 -0
- data/lib/shattered_machine.rb +2 -1
- data/lib/shattered_machine/glitcher.rb +8 -0
- data/lib/shattered_machine/io.rb +4 -4
- data/lib/shattered_machine/pixel_sorter.rb +1 -1
- data/lib/shattered_machine/progressive_pixel_sorter.rb +66 -0
- data/lib/shattered_machine/sampler.rb +4 -5
- data/lib/shattered_machine/slim.rb +4 -2
- data/lib/shattered_machine/transpose.rb +2 -2
- data/shattered_machine.gemspec +9 -3
- metadata +7 -22
- data/spec/brush_spec.rb +0 -25
- data/spec/change_byte_spec.rb +0 -25
- data/spec/converter_spec.rb +0 -23
- data/spec/defect_spec.rb +0 -25
- data/spec/exchange_spec.rb +0 -25
- data/spec/glitcher_spec.rb +0 -25
- 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 +0 -73
- data/spec/pixel_sorter_spec.rb +0 -25
- data/spec/sampler_spec.rb +0 -45
- data/spec/slim_spec.rb +0 -25
- data/spec/spec_helper.rb +0 -27
- data/spec/transpose_spec.rb +0 -25
- data/spec/wrong_filter_spec.rb +0 -25
data/lib/shattered_machine.rb
CHANGED
@@ -3,11 +3,12 @@
|
|
3
3
|
require 'shattered_machine/converter'
|
4
4
|
require 'shattered_machine/glitcher'
|
5
5
|
require 'shattered_machine/io'
|
6
|
+
require 'shattered_machine/progressive_pixel_sorter'
|
6
7
|
require 'shattered_machine/sampler'
|
7
8
|
|
8
9
|
# main file for ShatteredMachine gem
|
9
10
|
module ShatteredMachine
|
10
|
-
VERSION = '0.0
|
11
|
+
VERSION = '0.1.0'
|
11
12
|
|
12
13
|
class << self
|
13
14
|
end
|
@@ -1,5 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'brush'
|
4
|
+
require_relative 'change_byte'
|
5
|
+
require_relative 'defect'
|
6
|
+
require_relative 'exchange'
|
7
|
+
require_relative 'pixel_sorter'
|
8
|
+
require_relative 'slim'
|
9
|
+
require_relative 'transpose'
|
10
|
+
require_relative 'wrong_filter'
|
3
11
|
module ShatteredMachine
|
4
12
|
# Main class to call from glitching image.
|
5
13
|
class Glitcher
|
data/lib/shattered_machine/io.rb
CHANGED
@@ -6,10 +6,6 @@ module ShatteredMachine
|
|
6
6
|
class Io
|
7
7
|
attr_accessor :output_filename
|
8
8
|
|
9
|
-
PNG_EXTENSIONS = ['.png', '.PNG'].freeze
|
10
|
-
JPG_EXTENSIONS = ['.jpg', '.jpeg', '.JPG', '.JPEG'].freeze
|
11
|
-
Paths = Struct.new(:input, :output)
|
12
|
-
|
13
9
|
# @param input_path [string] input file or directory
|
14
10
|
# @param output_folder [string] output directory
|
15
11
|
# @param output_filename [string] output file name
|
@@ -39,6 +35,10 @@ module ShatteredMachine
|
|
39
35
|
|
40
36
|
private
|
41
37
|
|
38
|
+
PNG_EXTENSIONS = ['.png', '.PNG'].freeze
|
39
|
+
JPG_EXTENSIONS = ['.jpg', '.jpeg', '.JPG', '.JPEG'].freeze
|
40
|
+
Paths = Struct.new(:input, :output)
|
41
|
+
|
42
42
|
def single_image_io
|
43
43
|
[Paths.new(@input_path, generate_output_filename)]
|
44
44
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'pixel_sorter'
|
4
|
+
module ShatteredMachine
|
5
|
+
# Call the pixel sorter multiple time in steps for given png image(s)
|
6
|
+
class ProgressivePixelSorter
|
7
|
+
# @param io [ShatteredMachine::Io] Io containing paths for images to glitch
|
8
|
+
# @param options [Hash] options for the pixel sorting algorithm
|
9
|
+
def initialize(io, options)
|
10
|
+
@io = io
|
11
|
+
@options = options
|
12
|
+
@images_count = @io.png_images.count
|
13
|
+
@steps = define_steps
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
@io.png_images.sort_by { |path| [path.input[/\d+/].to_i, path.input] }.each_with_index do |item, index|
|
18
|
+
PixelSorter.new(sorter_options(index)).call(item.input, item.output)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def sorter_options(index)
|
25
|
+
return @options unless @options[:smart_sorting]
|
26
|
+
|
27
|
+
step_options = @options.clone
|
28
|
+
step_options[:multiple_ranges] = false
|
29
|
+
step_options[:detection_min] = (define_new_min_limit(index)).round.to_s
|
30
|
+
step_options[:detection_max] = (define_new_max_limit(index)).round.to_s
|
31
|
+
step_options
|
32
|
+
end
|
33
|
+
|
34
|
+
def define_steps
|
35
|
+
{ min: min_step, max: max_step }
|
36
|
+
end
|
37
|
+
|
38
|
+
def min_step
|
39
|
+
positive_subtraction(@options[:detection_min].to_f, @options[:detection_min_two].to_f) / (@images_count - 1)
|
40
|
+
end
|
41
|
+
|
42
|
+
def max_step
|
43
|
+
positive_subtraction(@options[:detection_max].to_f, @options[:detection_max_two].to_f) / (@images_count - 1)
|
44
|
+
end
|
45
|
+
|
46
|
+
def positive_subtraction(value1, value2)
|
47
|
+
value1 > value2 ? value1 - value2 : value2 - value1
|
48
|
+
end
|
49
|
+
|
50
|
+
def define_new_min_limit(index)
|
51
|
+
if @options[:detection_min].to_f > @options[:detection_min_two].to_f
|
52
|
+
(@options[:detection_min].to_f - (index * @steps[:min]))
|
53
|
+
else
|
54
|
+
(@options[:detection_min].to_f + (index * @steps[:min]))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def define_new_max_limit(index)
|
59
|
+
if @options[:detection_max].to_f > @options[:detection_max_two].to_f
|
60
|
+
(@options[:detection_max].to_f - (index * @steps[:max]))
|
61
|
+
else
|
62
|
+
(@options[:detection_max].to_f + (index * @steps[:max]))
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -11,7 +11,7 @@ module ShatteredMachine
|
|
11
11
|
# @param options [Hash] options for specifying which
|
12
12
|
def initialize(io, options = {})
|
13
13
|
@io = io
|
14
|
-
@base_output_filename =
|
14
|
+
@base_output_filename = io.output_filename.empty? ? 'sample' : io.output_filename
|
15
15
|
@algorithms_to_sample = options[:algorithms_to_sample] || ALL_ALGORITHMS
|
16
16
|
end
|
17
17
|
|
@@ -30,8 +30,7 @@ module ShatteredMachine
|
|
30
30
|
private
|
31
31
|
|
32
32
|
FILTERS = %w[none sub up average paeth].freeze
|
33
|
-
|
34
|
-
BRUSH_DIRECTION = %w[vertical vertical_inverted horizontal horizontal_inverted].freeze
|
33
|
+
DIRECTION = %w[vertical vertical_inverted horizontal horizontal_inverted].freeze
|
35
34
|
|
36
35
|
def update_io(output_filename_appendix)
|
37
36
|
@io.output_filename = "#{@base_output_filename}_#{output_filename_appendix}"
|
@@ -65,7 +64,7 @@ module ShatteredMachine
|
|
65
64
|
def sample_slim
|
66
65
|
return unless @algorithms_to_sample.include? 'slim'
|
67
66
|
|
68
|
-
|
67
|
+
DIRECTION.each do |direction|
|
69
68
|
update_io("slim_#{direction}")
|
70
69
|
slim_options = { direction: direction.to_sym }
|
71
70
|
Glitcher.new('Slim', @io, slim_options).call
|
@@ -75,7 +74,7 @@ module ShatteredMachine
|
|
75
74
|
def sample_brush
|
76
75
|
return unless @algorithms_to_sample.include? 'brush'
|
77
76
|
|
78
|
-
|
77
|
+
DIRECTION.each do |direction|
|
79
78
|
update_io("brush_#{direction}")
|
80
79
|
brush_options = { direction: direction.to_sym }
|
81
80
|
Glitcher.new('Brush', @io, brush_options).call
|
@@ -11,7 +11,7 @@ module ShatteredMachine
|
|
11
11
|
# @param options [Hash] options for slim algorithm
|
12
12
|
def initialize(options = {})
|
13
13
|
@colors = options[:colors] || ALL_COLORS
|
14
|
-
@direction = options[:direction] || :
|
14
|
+
@direction = options[:direction] || :vertical_inverted
|
15
15
|
@probability = (options[:probability] || 95).to_s
|
16
16
|
@probability_area = options[:probability_area] || 'global'
|
17
17
|
@colors_with_proba = colors_with_proba(options[:colors_with_proba])
|
@@ -38,7 +38,9 @@ module ShatteredMachine
|
|
38
38
|
|
39
39
|
def rust_formatted_direction
|
40
40
|
ruby_to_rust_directions = { up_to_down: '1', down_to_up: '2',
|
41
|
-
left_to_right: '3', right_to_left: '4'
|
41
|
+
left_to_right: '3', right_to_left: '4',
|
42
|
+
vertical: '1', vertical_inverted: '2',
|
43
|
+
horizontal: '3', horizontal_inverted: '4' }
|
42
44
|
ruby_to_rust_directions[@direction]
|
43
45
|
end
|
44
46
|
|
@@ -47,11 +47,11 @@ module ShatteredMachine
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def half_transpose(data, qis)
|
50
|
-
data[0, qis] + data[qis * 2, qis] + data[qis * 1, qis] + data[qis * 3
|
50
|
+
data[0, qis] + data[qis * 2, qis] + data[qis * 1, qis] + data[qis * 3..-1]
|
51
51
|
end
|
52
52
|
|
53
53
|
def full_transpose(data, qis)
|
54
|
-
data[qis * 2, qis] + data[0, qis] + data[qis * 3
|
54
|
+
data[qis * 2, qis] + data[0, qis] + data[qis * 3..-1] + data[qis * 1, qis]
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
data/shattered_machine.gemspec
CHANGED
@@ -1,17 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'English'
|
4
|
+
|
1
5
|
Gem::Specification.new do |s|
|
2
6
|
s.name = 'shattered_machine'
|
3
|
-
s.version = '0.0
|
7
|
+
s.version = '0.1.0'
|
4
8
|
s.required_ruby_version = '>= 2.0.0'
|
5
9
|
s.required_rubygems_version = '>= 1.8.11'
|
6
10
|
s.summary = 'Shattered Machine core engine'
|
7
11
|
s.description = 'Shattered Machine is an easy way to glitch PNG images using different algorithms'
|
8
12
|
s.authors = ['Flo Girardo']
|
9
13
|
s.email = 'florian@barbrousse.net'
|
10
|
-
s.files
|
14
|
+
s.files = `git ls-files`.split($RS).reject do |file|
|
15
|
+
file =~ %r{^spec/}
|
16
|
+
end
|
11
17
|
s.test_files = ['spec']
|
12
18
|
s.require_paths = ['lib']
|
13
19
|
s.homepage =
|
14
|
-
'https://
|
20
|
+
'https://git.sr.ht/~pouet/shattered_machine'
|
15
21
|
s.license = 'MIT'
|
16
22
|
s.add_dependency 'rusty_engine_ffi', '>=0.0.2'
|
17
23
|
s.add_development_dependency('rspec', '~> 3')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shattered_machine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Flo Girardo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rusty_engine_ffi
|
@@ -75,6 +75,7 @@ files:
|
|
75
75
|
- doc/ShatteredMachine/Io.html
|
76
76
|
- doc/ShatteredMachine/Io/Paths.html
|
77
77
|
- doc/ShatteredMachine/PixelSorter.html
|
78
|
+
- doc/ShatteredMachine/ProgressivePixelSorter.html
|
78
79
|
- doc/ShatteredMachine/Sampler.html
|
79
80
|
- doc/ShatteredMachine/Slim.html
|
80
81
|
- doc/ShatteredMachine/Transpose.html
|
@@ -92,6 +93,8 @@ files:
|
|
92
93
|
- doc/js/jquery.js
|
93
94
|
- doc/method_list.html
|
94
95
|
- doc/top-level-namespace.html
|
96
|
+
- icon.png
|
97
|
+
- icon.svg
|
95
98
|
- lib/shattered_machine.rb
|
96
99
|
- lib/shattered_machine/brush.rb
|
97
100
|
- lib/shattered_machine/change_byte.rb
|
@@ -101,31 +104,13 @@ files:
|
|
101
104
|
- lib/shattered_machine/glitcher.rb
|
102
105
|
- lib/shattered_machine/io.rb
|
103
106
|
- lib/shattered_machine/pixel_sorter.rb
|
107
|
+
- lib/shattered_machine/progressive_pixel_sorter.rb
|
104
108
|
- lib/shattered_machine/sampler.rb
|
105
109
|
- lib/shattered_machine/slim.rb
|
106
110
|
- lib/shattered_machine/transpose.rb
|
107
111
|
- lib/shattered_machine/wrong_filter.rb
|
108
112
|
- shattered_machine.gemspec
|
109
|
-
|
110
|
-
- spec/change_byte_spec.rb
|
111
|
-
- spec/converter_spec.rb
|
112
|
-
- spec/defect_spec.rb
|
113
|
-
- spec/exchange_spec.rb
|
114
|
-
- spec/glitcher_spec.rb
|
115
|
-
- spec/images/bar.PNG
|
116
|
-
- spec/images/bar.jpeg
|
117
|
-
- spec/images/foo.jpg
|
118
|
-
- spec/images/foo.png
|
119
|
-
- spec/images/fuzz.JPG
|
120
|
-
- spec/images/pouet.JPEG
|
121
|
-
- spec/io_spec.rb
|
122
|
-
- spec/pixel_sorter_spec.rb
|
123
|
-
- spec/sampler_spec.rb
|
124
|
-
- spec/slim_spec.rb
|
125
|
-
- spec/spec_helper.rb
|
126
|
-
- spec/transpose_spec.rb
|
127
|
-
- spec/wrong_filter_spec.rb
|
128
|
-
homepage: https://framagit.org/Radoteur/shattered-machine
|
113
|
+
homepage: https://git.sr.ht/~pouet/shattered_machine
|
129
114
|
licenses:
|
130
115
|
- MIT
|
131
116
|
metadata: {}
|
data/spec/brush_spec.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe ShatteredMachine::Brush do
|
6
|
-
describe '#call' do
|
7
|
-
let(:output_file) { 'spec/images/brush.png' }
|
8
|
-
let(:input_file) { 'spec/images/foo.png' }
|
9
|
-
let(:io) do
|
10
|
-
ShatteredMachine::Io.new(input_file, 'spec/images', 'brush')
|
11
|
-
end
|
12
|
-
let(:in_img) { io.png_images.first.input }
|
13
|
-
let(:out_img) { io.png_images.first.output }
|
14
|
-
subject { ShatteredMachine::Brush.new.call(in_img, out_img) }
|
15
|
-
|
16
|
-
after do
|
17
|
-
File.delete(output_file) if File.exist?(output_file)
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'brush image' do
|
21
|
-
subject
|
22
|
-
expect(File.exist?(output_file)).to be true
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/spec/change_byte_spec.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe ShatteredMachine::ChangeByte do
|
6
|
-
describe '#call' do
|
7
|
-
let(:output_file) { 'spec/images/change_byte.png' }
|
8
|
-
let(:input_file) { 'spec/images/foo.png' }
|
9
|
-
let(:io) do
|
10
|
-
ShatteredMachine::Io.new(input_file, 'spec/images', 'change_byte')
|
11
|
-
end
|
12
|
-
let(:in_img) { io.png_images.first.input }
|
13
|
-
let(:out_img) { io.png_images.first.output }
|
14
|
-
subject { ShatteredMachine::ChangeByte.new.call(in_img, out_img) }
|
15
|
-
|
16
|
-
after do
|
17
|
-
File.delete(output_file) if File.exist?(output_file)
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'change byte on image' do
|
21
|
-
subject
|
22
|
-
expect(File.exist?(output_file)).to be true
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/spec/converter_spec.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe ShatteredMachine::Converter do
|
6
|
-
describe '#call' do
|
7
|
-
let(:converted_file) { 'spec/images/converted.png' }
|
8
|
-
let(:input_file) { 'spec/images/foo.jpg' }
|
9
|
-
let(:io) do
|
10
|
-
ShatteredMachine::Io.new(input_file, 'spec/images', 'converted')
|
11
|
-
end
|
12
|
-
subject { ShatteredMachine::Converter.new(io).call }
|
13
|
-
|
14
|
-
after do
|
15
|
-
File.delete(converted_file) if File.exist?(converted_file)
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'convert image' do
|
19
|
-
subject
|
20
|
-
expect(File.exist?(converted_file)).to be true
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/spec/defect_spec.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe ShatteredMachine::Defect do
|
6
|
-
describe '#call' do
|
7
|
-
let(:output_file) { 'spec/images/defect.png' }
|
8
|
-
let(:input_file) { 'spec/images/foo.png' }
|
9
|
-
let(:io) do
|
10
|
-
ShatteredMachine::Io.new(input_file, 'spec/images', 'defect')
|
11
|
-
end
|
12
|
-
let(:in_img) { io.png_images.first.input }
|
13
|
-
let(:out_img) { io.png_images.first.output }
|
14
|
-
subject { ShatteredMachine::Defect.new.call(in_img, out_img) }
|
15
|
-
|
16
|
-
after do
|
17
|
-
File.delete(output_file) if File.exist?(output_file)
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'defect image' do
|
21
|
-
subject
|
22
|
-
expect(File.exist?(output_file)).to be true
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/spec/exchange_spec.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe ShatteredMachine::Exchange do
|
6
|
-
describe '#call' do
|
7
|
-
let(:output_file) { 'spec/images/exchange.png' }
|
8
|
-
let(:input_file) { 'spec/images/foo.png' }
|
9
|
-
let(:io) do
|
10
|
-
ShatteredMachine::Io.new(input_file, 'spec/images', 'exchange')
|
11
|
-
end
|
12
|
-
let(:in_img) { io.png_images.first.input }
|
13
|
-
let(:out_img) { io.png_images.first.output }
|
14
|
-
subject { ShatteredMachine::Exchange.new.call(in_img, out_img) }
|
15
|
-
|
16
|
-
after do
|
17
|
-
File.delete(output_file) if File.exist?(output_file)
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'exchange image' do
|
21
|
-
subject
|
22
|
-
expect(File.exist?(output_file)).to be true
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/spec/glitcher_spec.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe ShatteredMachine::Glitcher do
|
6
|
-
describe '#call' do
|
7
|
-
let(:output_file) { 'spec/images/glitch.png' }
|
8
|
-
let(:input_file) { 'spec/images/foo.png' }
|
9
|
-
let(:io) do
|
10
|
-
ShatteredMachine::Io.new(input_file, 'spec/images', 'glitch')
|
11
|
-
end
|
12
|
-
subject do
|
13
|
-
ShatteredMachine::Glitcher.new('Slim', io).call
|
14
|
-
end
|
15
|
-
|
16
|
-
after do
|
17
|
-
File.delete(output_file) if File.exist?(output_file)
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'slim image' do
|
21
|
-
subject
|
22
|
-
expect(File.exist?(output_file)).to be true
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|