pxlsrt 1.7.1 → 1.8.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d5307d37f9c289e44ebcef491140425fb87cc323
4
- data.tar.gz: 81efa6032e867501ed264d23c9c2d4947c9ea5d6
3
+ metadata.gz: fa77df27b6a2bcd94f0b1e23855baa5219e25f16
4
+ data.tar.gz: a3b71ee3d6f67fb348628bd917491db1193474bf
5
5
  SHA512:
6
- metadata.gz: 50ac440bddb401a3c52d563f2d99c8ad46dcbec066b09047faa4cbe0cafc8997521a42a6cb920c6191543773311795d62d4a8609db1cc746c34048f33f9a28ea
7
- data.tar.gz: 7f12f4968efc0759d276536eeea135efb4e02ef334fb2067d717c29ad641d44c13c300f80e4cc920538301f4d652ee06e3bac33b211375a8f53359f0d6706409
6
+ metadata.gz: 6dd4f1a8187e9ccf3bab9e7735a190f53491404caa40bc3ae776b53077b4193cb820a62ce6973151aa613bf0beed0b3d76193c69bdd53b66644445155197a72f
7
+ data.tar.gz: 43d0246a46cebfce1a22e4e817a65c8ead7fb5efd40f8daa4a0a5850ba054030b3f485701cc1191ec42bb846baf8a849e85eb8af99ef190534383eb98fdfa0ac
data/bin/pxlsrt CHANGED
@@ -59,7 +59,7 @@ class CLI < Thor
59
59
 
60
60
  option :method, :type => :string, :default => "brightness", :aliases => "-m", :enum => ["brightness", "white", "black"]
61
61
  option :value, :type => :numeric, :aliases => "-v"
62
- desc "kim INPUT OUTPUT [outputs]", "Uses Kim Asendorf's algorithm"
62
+ desc "kim INPUT OUTPUT [options]", "Uses Kim Asendorf's algorithm"
63
63
  def kim(input, output)
64
64
  k= {:trusted => true}
65
65
  for o in options.keys
@@ -67,6 +67,32 @@ class CLI < Thor
67
67
  end
68
68
  Pxlsrt::Kim.suite(input, output, k)
69
69
  end
70
+
71
+ option :reverse, :default => false, :aliases => "-r"
72
+ option :smooth, :type => :boolean, :default => false, :aliases => "-s"
73
+ option :method, :type => :string, :default => "sum-rgb", :banner => "[#{Pxlsrt::Colors::METHODS.join(" | ")}]", :aliases => "-m", :enum => Pxlsrt::Colors::METHODS
74
+ option :middle, :default => false, :aliases => "-M"
75
+ option :random, :default => false, :aliases => "-R"
76
+ option :distance, :default => 100, :aliases => "-d"
77
+ option :threshold, :default => 0.1, :aliases => "-t", :type => :numeric
78
+ desc "seed INPUT OUTPUT [options]", "Seed pixel sorting"
79
+ def seed(input, output)
80
+ k={:trusted=>true}
81
+ for o in options.keys
82
+ k[o.to_sym]=options[o]
83
+ end
84
+ if Pxlsrt::Helpers.isNumeric?(k[:random])
85
+ k[:random] = k[:random].to_i
86
+ else
87
+ k[:random] = false
88
+ end
89
+ if Pxlsrt::Helpers.isNumeric?(k[:distance])
90
+ k[:distance] = k[:distance].to_i
91
+ else
92
+ k[:distance] = false
93
+ end
94
+ Pxlsrt::Seed.suite(input, output, k)
95
+ end
70
96
  end
71
97
 
72
98
  CLI.start(ARGV)
@@ -0,0 +1,209 @@
1
+ require 'oily_png'
2
+
3
+ module Pxlsrt
4
+ ##
5
+ # Plant seeds, have them spiral out and sort.
6
+ class Seed
7
+ ##
8
+ # Uses Pxlsrt::Seed.seed to input and output from one method.
9
+ def self.suite(inputFileName, outputFileName, o={})
10
+ kml = Pxlsrt::Seed.seed(inputFileName, o)
11
+ if Pxlsrt::Helpers.contented(kml)
12
+ kml.save(outputFileName)
13
+ end
14
+ end
15
+ ##
16
+ # The main attraction of the Seed class. Returns a ChunkyPNG::Image that is sorted according to the options provided. Will raise any error that occurs.
17
+ def self.seed(input, o = {})
18
+ startTime = Time.now
19
+ defOptions = {
20
+ :reverse => false,
21
+ :smooth => false,
22
+ :method => "sum-rgb",
23
+ :verbose => false,
24
+ :trusted => false,
25
+ :middle => false,
26
+ :random => false,
27
+ :distance => 100,
28
+ :threshold => 0.1
29
+ }
30
+ defRules = {
31
+ :reverse => :anything,
32
+ :smooth => [false, true],
33
+ :method => Pxlsrt::Colors::METHODS,
34
+ :verbose => [false, true],
35
+ :trusted => [false, true],
36
+ :middle => :anything,
37
+ :random => [false, {:class => [Fixnum]}],
38
+ :distance => [false, {:class => [Fixnum]}],
39
+ :threshold => [{:class => [Float, Fixnum]}]
40
+ }
41
+ options = defOptions.merge(o)
42
+ if o.length == 0 or options[:trusted] == true or (options[:trusted] == false and o.length != 0 and Pxlsrt::Helpers.checkOptions(options, defRules) != false)
43
+ if input.class == String
44
+ Pxlsrt::Helpers.verbose("Getting image from file...") if options[:verbose]
45
+ if File.file?(input)
46
+ if Pxlsrt::Colors.isPNG?(input)
47
+ input = ChunkyPNG::Image.from_file(input)
48
+ else
49
+ Pxlsrt::Helpers.error("File #{input} is not a valid PNG.") if options[:verbose]
50
+ raise "Invalid PNG"
51
+ end
52
+ else
53
+ Pxlsrt::Helpers.error("File #{input} doesn't exist!") if options[:verbose]
54
+ raise "File doesn't exit"
55
+ end
56
+ elsif input.class != String and input.class != ChunkyPNG::Image
57
+ Pxlsrt::Helpers.error("Input is not a filename or ChunkyPNG::Image") if options[:verbose]
58
+ raise "Invalid input (must be filename or ChunkyPNG::Image)"
59
+ end
60
+ Pxlsrt::Helpers.verbose("Seed mode.") if options[:verbose]
61
+ Pxlsrt::Helpers.verbose("Creating Pxlsrt::Image object") if options[:verbose]
62
+ png = Pxlsrt::Image.new(input)
63
+ traversed = [false] * (png.getWidth * png.getHeight)
64
+ count = 0
65
+ seeds = []
66
+ if options[:random] != false
67
+ Pxlsrt::Helpers.progress("Planting seeds", 0, options[:random]) if options[:verbose]
68
+ for s in (0...options[:random])
69
+ x = (0...png.getWidth).to_a.sample
70
+ y = (0...png.getHeight).to_a.sample
71
+ seeds.push({
72
+ :spiral => Pxlsrt::Spiral.new(x, y),
73
+ :pixels => [png[x, y]],
74
+ :xy => [{:x => x, :y=>y}],
75
+ :placed => true,
76
+ :retired => false,
77
+ :anchor => {
78
+ :x => x,
79
+ :y => y
80
+ }
81
+ })
82
+ Pxlsrt::Helpers.progress("Planting seeds", s + 1, options[:random]) if options[:verbose]
83
+ end
84
+ else
85
+ Pxlsrt::Helpers.progress("Planting seeds", 0, png.getWidth * png.getHeight) if options[:verbose]
86
+ kernel = [[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]]
87
+ i = (png.getWidth + png.getHeight - 2) * 2
88
+ for y in (1...(png.getHeight - 1))
89
+ for x in (1...(png.getWidth - 1))
90
+ sum = 0
91
+ for ky in ((-1)..1)
92
+ for kx in ((-1)..1)
93
+ sum += kernel[ky + 1][kx + 1] * (ChunkyPNG::Color.r(png[x + kx, y + ky]))
94
+ end
95
+ end
96
+ if sum < options[:threshold]
97
+ seeds.push({
98
+ :spiral => Pxlsrt::Spiral.new(x, y),
99
+ :pixels => [png[x, y]],
100
+ :xy => [{:x => x, :y=>y}],
101
+ :placed => true,
102
+ :retired => false,
103
+ :anchor => {
104
+ :x => x,
105
+ :y => y
106
+ }
107
+ })
108
+ end
109
+ i += 1
110
+ Pxlsrt::Helpers.progress("Planting seeds", i, png.getWidth * png.getHeight) if options[:verbose]
111
+ end
112
+ end
113
+ if options[:distance] != false
114
+ Pxlsrt::Helpers.progress("Removing seed clusters", 0, seeds.length) if options[:verbose]
115
+ results = []
116
+ i = 0
117
+ for current in seeds
118
+ add = true
119
+ for other in results
120
+ d = Math.sqrt((current[:anchor][:x] - other[:anchor][:x]) ** 2 + (current[:anchor][:y] - other[:anchor][:y]) ** 2)
121
+ add = false if d > 0 and d < options[:distance]
122
+ end
123
+ if add
124
+ results.push(current)
125
+ end
126
+ i += 1
127
+ Pxlsrt::Helpers.progress("Removing seed clusters", i, seeds.length) if options[:verbose]
128
+ end
129
+ seeds = results
130
+ end
131
+ end
132
+ for r in (0...seeds.length)
133
+ traversed[seeds[r][:anchor][:x] + seeds[r][:anchor][:y] * png.getWidth] = r
134
+ count += 1
135
+ end
136
+ Pxlsrt::Helpers.verbose("Planted #{seeds.length} seeds") if options[:verbose]
137
+ step = 0
138
+ Pxlsrt::Helpers.progress("Watch them grow!", count, traversed.length) if options[:verbose]
139
+ while count < traversed.length and seeds.length != 0
140
+ r = 0
141
+ retired = []
142
+ for seed in seeds
143
+ if !seed[:retired]
144
+ n = seed[:spiral].next
145
+ if n[:x] >= 0 and n[:y] >= 0 and n[:x] < png.getWidth and n[:y] < png.getHeight and !traversed[n[:x] + n[:y] * png.getWidth]
146
+ seed[:pixels].push(png[n[:x], n[:y]])
147
+ traversed[n[:x] + n[:y] * png.getWidth] = r
148
+ seed[:xy].push(n)
149
+ seed[:placed] = true
150
+ count += 1
151
+ else
152
+ if seed[:placed] == true
153
+ seed[:placed] = {
154
+ :count => 1,
155
+ :direction => seed[:spiral].direction,
156
+ :cycle => seed[:spiral].cycles
157
+ }
158
+ case seed[:placed][:direction]
159
+ when "up", "down"
160
+ seed[:placed][:value] = seed[:spiral].pos[:y]
161
+ seed[:placed][:valueS] = :y
162
+ when "left", "right"
163
+ seed[:placed][:value] = seed[:spiral].pos[:x]
164
+ seed[:placed][:valueS] = :x
165
+ end
166
+ else
167
+ seed[:placed][:count] += 1
168
+ if seed[:spiral].cycles != seed[:placed][:cycle] and seed[:placed][:direction] == seed[:spiral].direction and seed[:placed][:value] == seed[:spiral].pos[seed[:placed][:valueS]]
169
+ seed[:retired] = true
170
+ end
171
+ end
172
+ end
173
+ end
174
+ r += 1
175
+ end
176
+ step += 1
177
+ Pxlsrt::Helpers.progress("Watch them grow!", count, traversed.length) if options[:verbose]
178
+ end
179
+ Pxlsrt::Helpers.progress("Sort seeds and place pixels", 0, seeds.length) if options[:verbose]
180
+ r = 0
181
+ for seed in seeds
182
+ spiral = Pxlsrt::Spiral.new(seed[:anchor][:x], seed[:anchor][:y])
183
+ band = Pxlsrt::Helpers.handlePixelSort(seed[:pixels], options)
184
+ i = 0
185
+ for k in seed[:xy]
186
+ png[k[:x], k[:y]] = band[i]
187
+ i += 1
188
+ end
189
+ r += 1
190
+ Pxlsrt::Helpers.progress("Sort seeds and place pixels", r, seeds.length) if options[:verbose]
191
+ end
192
+ endTime=Time.now
193
+ timeElapsed=endTime-startTime
194
+ if timeElapsed < 60
195
+ Pxlsrt::Helpers.verbose("Took #{timeElapsed.round(4)} second#{ timeElapsed!=1.0 ? "s" : "" }.") if options[:verbose]
196
+ else
197
+ minutes=(timeElapsed/60).floor
198
+ seconds=(timeElapsed % 60).round(4)
199
+ Pxlsrt::Helpers.verbose("Took #{minutes} minute#{ minutes!=1 ? "s" : "" } and #{seconds} second#{ seconds!=1.0 ? "s" : "" }.") if options[:verbose]
200
+ end
201
+ Pxlsrt::Helpers.verbose("Returning ChunkyPNG::Image...") if options[:verbose]
202
+ return png.returnModified
203
+ else
204
+ Pxlsrt::Helpers.error("Options specified do not follow the correct format.") if options[:verbose]
205
+ raise "Bad options"
206
+ end
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,84 @@
1
+ module Pxlsrt
2
+ ##
3
+ # Spiral iteration.
4
+ class Spiral
5
+ def initialize(x, y)
6
+ @x = x
7
+ @y = y
8
+ @direction = "up"
9
+ @step = 1
10
+ @at = 0
11
+ @count = 0
12
+ @cycles = -1
13
+ end
14
+ ##
15
+ # Return current x value.
16
+ def x
17
+ return @x
18
+ end
19
+ ##
20
+ # Return current y value.
21
+ def y
22
+ return @y
23
+ end
24
+ ##
25
+ # Return current direction.
26
+ def direction
27
+ return @direction
28
+ end
29
+ ##
30
+ # Return amount iterated.
31
+ def count
32
+ return @count
33
+ end
34
+ ##
35
+ # Return cycles gone through completely.
36
+ def cycles
37
+ return @cycles
38
+ end
39
+ ##
40
+ # Return current position.
41
+ def pos
42
+ return {:x => @x, :y => @y}
43
+ end
44
+ ##
45
+ # Goes to next position. Returns position.
46
+ def next
47
+ case @direction
48
+ when "left"
49
+ @x -= 1
50
+ @at += 1
51
+ if @at == @step
52
+ @direction = "down"
53
+ @at = 0
54
+ @step += 1
55
+ end
56
+ when "down"
57
+ @y += 1
58
+ @at += 1
59
+ if @at == @step
60
+ @direction = "right"
61
+ @at = 0
62
+ end
63
+ when "right"
64
+ @x += 1
65
+ @at += 1
66
+ if @at == @step
67
+ @direction = "up"
68
+ @at = 0
69
+ @step += 1
70
+ end
71
+ when "up"
72
+ @cycles += 1 if @at == 0
73
+ @y -= 1
74
+ @at += 1
75
+ if @at == @step
76
+ @direction = "left"
77
+ @at = 0
78
+ end
79
+ end
80
+ @count += 1
81
+ return pos
82
+ end
83
+ end
84
+ end
@@ -1,5 +1,5 @@
1
1
  ##
2
2
  # The main module, your best friend.
3
3
  module Pxlsrt
4
- VERSION = "1.7.1"
4
+ VERSION = "1.8.0"
5
5
  end
data/lib/pxlsrt.rb CHANGED
@@ -5,4 +5,6 @@ require "pxlsrt/image"
5
5
  require "pxlsrt/colors"
6
6
  require "pxlsrt/brute"
7
7
  require "pxlsrt/smart"
8
- require "pxlsrt/kim"
8
+ require "pxlsrt/kim"
9
+ require "pxlsrt/spiral"
10
+ require "pxlsrt/seed"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pxlsrt
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.1
4
+ version: 1.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - EVA-01
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-18 00:00:00.000000000 Z
11
+ date: 2014-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -82,7 +82,9 @@ files:
82
82
  - lib/pxlsrt/image.rb
83
83
  - lib/pxlsrt/kim.rb
84
84
  - lib/pxlsrt/lines.rb
85
+ - lib/pxlsrt/seed.rb
85
86
  - lib/pxlsrt/smart.rb
87
+ - lib/pxlsrt/spiral.rb
86
88
  - lib/pxlsrt/version.rb
87
89
  homepage: https://github.com/EVA-01/pxlsrt
88
90
  licenses: