pxlsrt 1.6.3 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 61530233928fdf5537158612c19fb3709da5281d
4
- data.tar.gz: fbda0d61a84d109a8f97865db731a9cf369f6db8
3
+ metadata.gz: 5a70f5d32502428d68f198d43c0ee703814b0827
4
+ data.tar.gz: 213ac35f136cf0de3cc07329e7ced721a47df470
5
5
  SHA512:
6
- metadata.gz: b94363170de2be0c0dc41dc5c8d9430edb443c5981e33df4480895740c5108ee9f192857d59c053bba645df8097bee539470c14fb54746836f395004e9e38c49
7
- data.tar.gz: d503edbbbdd822c1f4f6f2894a1d7983e1f21735d414a090759e5f9f5817c624cbc8982de1fa2a1bfc791dbecaacd8ec91de7522fc8e68ea84c3e22a2bc0852a
6
+ metadata.gz: 8b492703dd354aead349520473721db2a8ef810e9495fa7b8e4b6e2d362a4083496b563be6c8204d5cee8c6cb915a08ac933bbe77253a9b767ea2e95d407a9af
7
+ data.tar.gz: 9f2c0daebb6336b7dd56222c8eb04b03957d0cc3b5e9735a5e77593b56de6bb71e1de6e3309638390eaa49109f28ae7ddd743c30f6391b6e9398c4adfbf8d5f8
data/bin/pxlsrt CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'rubygems'
4
3
  require 'pxlsrt'
5
4
  require 'thor'
6
5
 
@@ -14,14 +13,14 @@ require 'thor'
14
13
  # * verbose - Have pxlsrt tell you what it's working on.
15
14
  # * help - More in depth commands.
16
15
  class CLI < Thor
17
- class_option :reverse, :default => false, :aliases => "-r"
18
- class_option :vertical, :type => :boolean, :default => false, :aliases => "-v"
19
- class_option :diagonal, :type => :boolean, :default => false, :aliases => "-d"
20
- class_option :smooth, :type => :boolean, :default => false, :aliases => "-s"
21
- class_option :method, :type => :string, :default => "sum-rgb", :banner => "[sum-rgb | red | green | blue | sum-hsb | hue | saturation | brightness | uniqueness | luma | random | cyan | magenta | yellow | alpha | sum-rgba | sum-hsba]", :aliases => "-m", :enum => ["sum-rgb", "red", "green", "blue", "sum-hsb", "hue", "saturation", "brightness", "uniqueness", "luma", "random", "cyan", "magenta", "yellow", "alpha", "sum-rgba", "sum-hsba"]
22
16
  class_option :verbose, :type => :boolean, :default => false, :aliases => "-V"
23
- class_option :middle, :default => false, :aliases => "-M"
24
17
 
18
+ option :reverse, :default => false, :aliases => "-r"
19
+ option :vertical, :type => :boolean, :default => false, :aliases => "-v"
20
+ option :diagonal, :type => :boolean, :default => false, :aliases => "-d"
21
+ option :smooth, :type => :boolean, :default => false, :aliases => "-s"
22
+ option :method, :type => :string, :default => "sum-rgb", :banner => "[#{Pxlsrt::Colors::METHODS.join(" | ")}]", :aliases => "-m", :enum => Pxlsrt::Colors::METHODS
23
+ option :middle, :default => false, :aliases => "-M"
25
24
  option :min, :type => :numeric, :default => Float::INFINITY, :banner => "MINIMUM BANDWIDTH"
26
25
  option :max, :type => :numeric, :default => Float::INFINITY, :banner => "MAXIMUM BANDWIDTH"
27
26
  desc "brute INPUT OUTPUT [options]", "Brute pixel sorting"
@@ -37,6 +36,12 @@ class CLI < Thor
37
36
  Pxlsrt::Brute.suite(input, output, k)
38
37
  end
39
38
 
39
+ option :reverse, :default => false, :aliases => "-r"
40
+ option :vertical, :type => :boolean, :default => false, :aliases => "-v"
41
+ option :diagonal, :type => :boolean, :default => false, :aliases => "-d"
42
+ option :smooth, :type => :boolean, :default => false, :aliases => "-s"
43
+ option :method, :type => :string, :default => "sum-rgb", :banner => "[#{Pxlsrt::Colors::METHODS.join(" | ")}]", :aliases => "-m", :enum => Pxlsrt::Colors::METHODS
44
+ option :middle, :default => false, :aliases => "-M"
40
45
  option :absolute, :type => :boolean, :default => false, :aliases => "-a", :banner => "ABSOLUTE EDGE FINDING"
41
46
  option :threshold, :type => :numeric, :default => 20, :aliases => "-t"
42
47
  desc "smart INPUT OUTPUT [options]", "Smart pixel sorting"
@@ -51,6 +56,17 @@ class CLI < Thor
51
56
  end
52
57
  Pxlsrt::Smart.suite(input, output, k)
53
58
  end
59
+
60
+ option :method, :type => :string, :default => "brightness", :aliases => "-m", :enum => ["brightness", "white", "black"]
61
+ option :value, :type => :numeric, :aliases => "-v"
62
+ desc "kim INPUT OUTPUT [outputs]", "Uses Kim Asendorf's algorithm"
63
+ def kim(input, output)
64
+ k= {:trusted => true}
65
+ for o in options.keys
66
+ k[o.to_sym] = options[o]
67
+ end
68
+ Pxlsrt::Kim.suite(input, output, k)
69
+ end
54
70
  end
55
71
 
56
72
  CLI.start(ARGV)
@@ -4,4 +4,5 @@ require "pxlsrt/lines"
4
4
  require "pxlsrt/image"
5
5
  require "pxlsrt/colors"
6
6
  require "pxlsrt/brute"
7
- require "pxlsrt/smart"
7
+ require "pxlsrt/smart"
8
+ require "pxlsrt/kim"
@@ -1,4 +1,3 @@
1
- require 'rubygems'
2
1
  require 'oily_png'
3
2
 
4
3
  module Pxlsrt
@@ -15,7 +14,7 @@ module Pxlsrt
15
14
  end
16
15
  end
17
16
  ##
18
- # The main attraction of the Brute class. Returns a ChunkyPNG::Image that is sorted according to the options provided. Will return nil if it encounters an errors.
17
+ # The main attraction of the Brute class. Returns a ChunkyPNG::Image that is sorted according to the options provided. Will raise any error that occurs.
19
18
  def self.brute(input, o={})
20
19
  startTime=Time.now
21
20
  defOptions={
@@ -35,7 +34,7 @@ module Pxlsrt
35
34
  :vertical => [false, true],
36
35
  :diagonal => [false, true],
37
36
  :smooth => [false, true],
38
- :method => ["sum-rgb", "red", "green", "blue", "sum-hsb", "hue", "saturation", "brightness", "uniqueness", "luma", "random", "cyan", "magenta", "yellow", "alpha", "sum-rgba", "sum-hsba"],
37
+ :method => Pxlsrt::Colors::METHODS,
39
38
  :verbose => [false, true],
40
39
  :min => [Float::INFINITY, {:class => [Fixnum]}],
41
40
  :max => [Float::INFINITY, {:class => [Fixnum]}],
@@ -53,17 +52,14 @@ module Pxlsrt
53
52
  else
54
53
  Pxlsrt::Helpers.error("File #{input} is not a valid PNG.") if options[:verbose]
55
54
  raise "Invalid PNG"
56
- return
57
55
  end
58
56
  else
59
57
  Pxlsrt::Helpers.error("File #{input} doesn't exist!") if options[:verbose]
60
58
  raise "File doesn't exit"
61
- return
62
59
  end
63
60
  elsif input.class!=String and input.class!=ChunkyPNG::Image
64
61
  Pxlsrt::Helpers.error("Input is not a filename or ChunkyPNG::Image") if options[:verbose]
65
62
  raise "Invalid input (must be filename or ChunkyPNG::Image)"
66
- return
67
63
  end
68
64
  Pxlsrt::Helpers.verbose("Brute mode.") if options[:verbose]
69
65
  Pxlsrt::Helpers.verbose("Creating Pxlsrt::Image object") if options[:verbose]
@@ -86,7 +82,9 @@ module Pxlsrt
86
82
  else
87
83
  iterator = lines.keys
88
84
  end
89
- Pxlsrt::Helpers.verbose("Dividing and pixel sorting lines") if options[:verbose]
85
+ prr = 0
86
+ len = iterator.to_a.length
87
+ Pxlsrt::Helpers.progress("Dividing and pixel sorting lines", prr, len) if options[:verbose]
90
88
  for k in iterator
91
89
  line = lines[k]
92
90
  divisions = Pxlsrt::Lines.randomSlices(line.length,options[:min],options[:max])
@@ -102,6 +100,8 @@ module Pxlsrt
102
100
  png.replaceDiagonal(k, newLine) if !options[:vertical]
103
101
  png.replaceRDiagonal(k, newLine) if options[:vertical]
104
102
  end
103
+ prr += 1
104
+ Pxlsrt::Helpers.progress("Dividing and pixel sorting lines", prr, len) if options[:verbose]
105
105
  end
106
106
  endTime=Time.now
107
107
  timeElapsed=endTime-startTime
@@ -117,7 +117,6 @@ module Pxlsrt
117
117
  else
118
118
  Pxlsrt::Helpers.error("Options specified do not follow the correct format.") if options[:verbose]
119
119
  raise "Bad options"
120
- return
121
120
  end
122
121
  end
123
122
  end
@@ -4,6 +4,9 @@ module Pxlsrt
4
4
  ##
5
5
  # Includes color operations.
6
6
  class Colors
7
+ ##
8
+ # List of sorting methods.
9
+ METHODS = ["sum-rgb", "red", "green", "blue", "sum-hsb", "hue", "saturation", "brightness", "uniqueness", "luma", "random", "cyan", "magenta", "yellow", "alpha", "sum-rgba", "sum-hsba"]
7
10
  ##
8
11
  # Converts a ChunkyPNG pixel into an array of the red, green, blue, and alpha values
9
12
  def self.getRGBA(pxl)
@@ -15,38 +18,6 @@ module Pxlsrt
15
18
  return File.open(path, 'rb').read(9).include?('PNG')
16
19
  end
17
20
  ##
18
- # Converts an RGB-like array ([red, green, blue]) into an HSB-like array ([hue, saturation, brightness]).
19
- def self.rgb2hsb(rgb)
20
- r = rgb[0] / 255.0
21
- g = rgb[1] / 255.0
22
- b = rgb[2] / 255.0
23
- max = [r, g, b].max
24
- min = [r, g, b].min
25
- delta = max - min
26
- v = max * 100
27
- if (max != 0.0)
28
- s = delta / max *100
29
- else
30
- s = 0.0
31
- end
32
- if (s == 0.0)
33
- h = 0.0
34
- else
35
- if (r == max)
36
- h = (g - b) / delta
37
- elsif (g == max)
38
- h = 2 + (b - r) / delta
39
- elsif (b == max)
40
- h = 4 + (r - g) / delta
41
- end
42
- h *= 60.0
43
- if (h < 0)
44
- h += 360.0
45
- end
46
- end
47
- return [h,s,v]
48
- end
49
- ##
50
21
  # Averages an array of RGB-like arrays.
51
22
  def self.colorAverage(ca, chunky = false)
52
23
  if ca.length==1
@@ -106,49 +77,49 @@ module Pxlsrt
106
77
  Pxlsrt::Helpers.error(list) if list.length == 0
107
78
  case how.downcase
108
79
  when "sum-rgb"
109
- mhm= list.sort_by { |c| ChunkyPNG::Color.r(c)+ChunkyPNG::Color.g(c)+ChunkyPNG::Color.b(c) }
80
+ mhm = list.sort_by { |c| ChunkyPNG::Color.r(c)+ChunkyPNG::Color.g(c)+ChunkyPNG::Color.b(c) }
110
81
  when "sum-rgba"
111
- mhm=list.sort_by { |c| ChunkyPNG::Color.r(c)+ChunkyPNG::Color.g(c)+ChunkyPNG::Color.b(c)+ChunkyPNG::Color.a(c) }
82
+ mhm =list.sort_by { |c| ChunkyPNG::Color.r(c)+ChunkyPNG::Color.g(c)+ChunkyPNG::Color.b(c)+ChunkyPNG::Color.a(c) }
112
83
  when "red"
113
- mhm= list.sort_by { |c| ChunkyPNG::Color.r(c) }
84
+ mhm = list.sort_by { |c| ChunkyPNG::Color.r(c) }
114
85
  when "yellow"
115
- mhm=list.sort_by { |c| ChunkyPNG::Color.r(c)+ChunkyPNG::Color.g(c) }
86
+ mhm =list.sort_by { |c| ChunkyPNG::Color.r(c)+ChunkyPNG::Color.g(c) }
116
87
  when "green"
117
- mhm= list.sort_by { |c| ChunkyPNG::Color.g(c) }
88
+ mhm = list.sort_by { |c| ChunkyPNG::Color.g(c) }
118
89
  when "cyan"
119
- mhm=list.sort_by { |c| ChunkyPNG::Color.g(c)+ChunkyPNG::Color.b(c) }
90
+ mhm =list.sort_by { |c| ChunkyPNG::Color.g(c)+ChunkyPNG::Color.b(c) }
120
91
  when "blue"
121
- mhm= list.sort_by { |c| ChunkyPNG::Color.b(c) }
92
+ mhm = list.sort_by { |c| ChunkyPNG::Color.b(c) }
122
93
  when "magenta"
123
- mhm=list.sort_by { |c| ChunkyPNG::Color.r(c)+ChunkyPNG::Color.b(c) }
94
+ mhm =list.sort_by { |c| ChunkyPNG::Color.r(c)+ChunkyPNG::Color.b(c) }
124
95
  when "hue"
125
- mhm= list.sort_by { |c| d = Pxlsrt::Colors.getRGBA(c); Pxlsrt::Colors.rgb2hsb(d)[0] }
96
+ mhm = list.sort_by { |c| ChunkyPNG::Color.to_hsb(c)[0] % 360 }
126
97
  when "saturation"
127
- mhm= list.sort_by { |c| d = Pxlsrt::Colors.getRGBA(c); Pxlsrt::Colors.rgb2hsb(d)[1] }
98
+ mhm = list.sort_by { |c| ChunkyPNG::Color.to_hsb(c)[1] }
128
99
  when "brightness"
129
- mhm= list.sort_by { |c| d = Pxlsrt::Colors.getRGBA(c); Pxlsrt::Colors.rgb2hsb(d)[2] }
100
+ mhm = list.sort_by { |c| ChunkyPNG::Color.to_hsb(c)[2] }
130
101
  when "sum-hsb"
131
- mhm= list.sort_by { |c| d = Pxlsrt::Colors.getRGBA(c); k=Pxlsrt::Colors.rgb2hsb(d); k[0]*100.0/360+k[1]+k[2] }
102
+ mhm = list.sort_by { |c| k = ChunkyPNG::Color.to_hsb(c); (k[0] % 360) / 360.0 + k[1] + k[2] }
132
103
  when "sum-hsba"
133
- mhm= list.sort_by { |c| d = Pxlsrt::Colors.getRGBA(c); k=Pxlsrt::Colors.rgb2hsb(d); k[0]*100.0/360+k[1]+k[2]+d.a*100.0/255 }
104
+ mhm = list.sort_by { |c| k = ChunkyPNG::Color.to_hsb(c); (k[0] % 360) / 360.0 + k[1] + k[2] + ChunkyPNG::Color.a(c) / 255.0 }
134
105
  when "uniqueness"
135
- avg=Pxlsrt::Colors.colorAverage(list, true)
136
- mhm=list.sort_by { |c| Pxlsrt::Colors.colorUniqueness(c, [avg], true) }
106
+ avg = Pxlsrt::Colors.colorAverage(list, true)
107
+ mhm = list.sort_by { |c| Pxlsrt::Colors.colorUniqueness(c, [avg], true) }
137
108
  when "luma"
138
- mhm=list.sort_by { |c| ChunkyPNG::Color.r(c)*0.2126+ChunkyPNG::Color.g(c)*0.7152+ChunkyPNG::Color.b(c)*0.0722 }
109
+ mhm = list.sort_by { |c| ChunkyPNG::Color.r(c) * 0.2126 + ChunkyPNG::Color.g(c) * 0.7152 + ChunkyPNG::Color.b(c) * 0.0722 + ChunkyPNG::Color.a(c) }
139
110
  when "random"
140
- mhm=list.shuffle
111
+ mhm = list.shuffle
141
112
  when "alpha"
142
- mhm=list.sort_by{ |c| ChunkyPNG::Color.a(c) }
113
+ mhm = list.sort_by{ |c| ChunkyPNG::Color.a(c) }
143
114
  else
144
- mhm= list.sort_by { |c| ChunkyPNG::Color.r(c)+ChunkyPNG::Color.g(c)+ChunkyPNG::Color.b(c) }
115
+ mhm = list.sort_by { |c| ChunkyPNG::Color.r(c)+ChunkyPNG::Color.g(c)+ChunkyPNG::Color.b(c) }
145
116
  end
146
117
  if reverse == 0
147
118
  return mhm
148
119
  elsif reverse == 1
149
120
  return mhm.reverse
150
121
  else
151
- return rand(0..1)==0 ? mhm : mhm.reverse
122
+ return [true, false].sample ? mhm : mhm.reverse
152
123
  end
153
124
  end
154
125
  ##
@@ -18,6 +18,16 @@ module Pxlsrt
18
18
  return "\e[36m#{what}\e[0m"
19
19
  end
20
20
  ##
21
+ # Used to output a yellow string to the terminal.
22
+ def self.yellow(what)
23
+ return "\e[33m#{what}\e[0m"
24
+ end
25
+ ##
26
+ # Used to output a green string to the terminal.
27
+ def self.green(what)
28
+ return "\e[32m#{what}\e[0m"
29
+ end
30
+ ##
21
31
  # Determines if a string can be a float or integer.
22
32
  def self.isNumeric?(s)
23
33
  true if Float(s) rescue false
@@ -90,5 +100,16 @@ module Pxlsrt
90
100
  def self.verbose(what)
91
101
  puts "#{Pxlsrt::Helpers.cyan("pxlsrt")} #{what}"
92
102
  end
103
+ ##
104
+ # Progress indication.
105
+ def self.progress(what, amount, outof)
106
+ progress = (amount.to_f * 100.0 / outof.to_f).to_i
107
+ if progress == 100
108
+ puts "\r#{Pxlsrt::Helpers.green("pxlsrt")} #{what} (#{Pxlsrt::Helpers.green("#{progress}%")})"
109
+ else
110
+ $stdout.write "\r#{Pxlsrt::Helpers.yellow("pxlsrt")} #{what} (#{Pxlsrt::Helpers.yellow("#{progress}%")})"
111
+ $stdout.flush
112
+ end
113
+ end
93
114
  end
94
115
  end
@@ -158,6 +158,16 @@ module Pxlsrt
158
158
  def []=(x, y, color)
159
159
  @modified[x, y] = color
160
160
  end
161
+ def i(i)
162
+ x = i % @width
163
+ y = (i / @width).floor
164
+ return self[x, y]
165
+ end
166
+ def i=(i, color)
167
+ x = i % @width
168
+ y = (i / @width).floor
169
+ self[x, y] = color
170
+ end
161
171
  ##
162
172
  # Return the original, unmodified image.
163
173
  def returnOriginal
@@ -168,5 +178,11 @@ module Pxlsrt
168
178
  def returnModified
169
179
  return @modified
170
180
  end
181
+ def getWidth
182
+ return @width
183
+ end
184
+ def getHeight
185
+ return @height
186
+ end
171
187
  end
172
188
  end
@@ -0,0 +1,263 @@
1
+ require 'oily_png'
2
+
3
+ module Pxlsrt
4
+ ##
5
+ # Uses Kim Asendorf's pixel sorting algorithm, orginally written in Processing. https://github.com/kimasendorf/ASDFPixelSort
6
+ class Kim
7
+ ##
8
+ # Uses Pxlsrt::Kim.kim to input and output from one method.
9
+ def self.suite(inputFileName, outputFileName, o={})
10
+ kml=Pxlsrt::Kim.kim(inputFileName, o)
11
+ if Pxlsrt::Helpers.contented(kml)
12
+ kml.save(outputFileName)
13
+ end
14
+ end
15
+ ##
16
+ # The main attraction of the Kim class. Returns a ChunkyPNG::Image that is sorted according to the options provided. Will raise any error that occurs.
17
+ def self.kim(input, o = {})
18
+ startTime = Time.now
19
+ defOptions={
20
+ :method => "brightness",
21
+ :verbose => false,
22
+ :value => false,
23
+ :trusted => false
24
+ }
25
+ defRules = {
26
+ :method => ["brightness", "black", "white"],
27
+ :verbose => [false, true],
28
+ :value => [false, {:class => [Fixnum]}],
29
+ :trusted => [false, true]
30
+ }
31
+ options = defOptions.merge(o)
32
+ if o.length == 0 or options[:trusted] == true or (options[:trusted] == false and o.length != 0 and Pxlsrt::Helpers.checkOptions(options, defRules) != false)
33
+ if input.class == String
34
+ Pxlsrt::Helpers.verbose("Getting image from file...") if options[:verbose]
35
+ if File.file?(input)
36
+ if Pxlsrt::Colors.isPNG?(input)
37
+ input = ChunkyPNG::Image.from_file(input)
38
+ else
39
+ Pxlsrt::Helpers.error("File #{input} is not a valid PNG.") if options[:verbose]
40
+ raise "Invalid PNG"
41
+ end
42
+ else
43
+ Pxlsrt::Helpers.error("File #{input} doesn't exist!") if options[:verbose]
44
+ raise "File doesn't exit"
45
+ end
46
+ elsif input.class != String and input.class != ChunkyPNG::Image
47
+ Pxlsrt::Helpers.error("Input is not a filename or ChunkyPNG::Image") if options[:verbose]
48
+ raise "Invalid input (must be filename or ChunkyPNG::Image)"
49
+ end
50
+ Pxlsrt::Helpers.verbose("Kim Asendorf mode.") if options[:verbose]
51
+ Pxlsrt::Helpers.verbose("Creating Pxlsrt::Image object") if options[:verbose]
52
+ png = Pxlsrt::Image.new(input)
53
+ column = 0
54
+ row = 0
55
+ options[:value] ||= ChunkyPNG::Color.rgba(11, 220, 0, 1) if options[:method] == "black"
56
+ options[:value] ||= 60 if options[:method] == "brightness"
57
+ options[:value] ||= ChunkyPNG::Color.rgba(57, 167, 192, 1) if options[:method] == "white"
58
+ Pxlsrt::Helpers.progress("Sorting columns", column, png.getWidth) if options[:verbose]
59
+ while column < png.getWidth
60
+ x = column
61
+ y = 0
62
+ yend = 0
63
+ while yend < png.getHeight
64
+ case options[:method]
65
+ when "black"
66
+ y = self.getFirstNotBlackY(png, x, y, options[:value])
67
+ yend = self.getNextBlackY(png, x, y, options[:value])
68
+ when "brightness"
69
+ y = self.getFirstBrightY(png, x, y, options[:value])
70
+ yend = self.getNextDarkY(png, x, y, options[:value])
71
+ when "white"
72
+ y = self.getFirstNotWhiteY(png, x, y, options[:value])
73
+ yend = self.getNextWhiteY(png, x, y, options[:value])
74
+ end
75
+ if y < 0
76
+ break
77
+ end
78
+ sortLength = yend - y;
79
+ unsorted = []
80
+ sorted = []
81
+ for i in (0...sortLength)
82
+ unsorted[i] = png[x, y + i];
83
+ end
84
+ sorted = unsorted.sort
85
+ for i in (0...sortLength)
86
+ png[x, y + i] = sorted[i];
87
+ end
88
+ y = yend + 1;
89
+ end
90
+ column += 1
91
+ Pxlsrt::Helpers.progress("Sorting columns", column, png.getWidth) if options[:verbose]
92
+ end
93
+ Pxlsrt::Helpers.progress("Sorting rows", row, png.getHeight) if options[:verbose]
94
+ while row < png.getHeight
95
+ x = 0
96
+ y = row
97
+ xend = 0
98
+ while xend < png.getWidth
99
+ case options[:method]
100
+ when "black"
101
+ x = self.getFirstNotBlackX(png, x, y, options[:value])
102
+ xend = self.getNextBlackX(png, x, y, options[:value])
103
+ when "brightness"
104
+ x = self.getFirstBrightX(png, x, y, options[:value])
105
+ xend = self.getNextDarkX(png, x, y, options[:value])
106
+ when "white"
107
+ x = self.getFirstNotWhiteX(png, x, y, options[:value])
108
+ xend = self.getNextWhiteX(png, x, y, options[:value])
109
+ end
110
+ if x < 0
111
+ break
112
+ end
113
+ sortLength = xend - x
114
+ unsorted = []
115
+ sorted = []
116
+ for i in (0...sortLength)
117
+ unsorted[i] = png[x + i, y]
118
+ end
119
+ sorted = unsorted.sort
120
+ for i in (0...sortLength)
121
+ png[x + i, y] = sorted[i];
122
+ end
123
+ x = xend + 1;
124
+ end
125
+ row += 1
126
+ Pxlsrt::Helpers.progress("Sorting rows", row, png.getHeight) if options[:verbose]
127
+ end
128
+ endTime=Time.now
129
+ timeElapsed=endTime-startTime
130
+ if timeElapsed < 60
131
+ Pxlsrt::Helpers.verbose("Took #{timeElapsed.round(4)} second#{ timeElapsed!=1.0 ? "s" : "" }.") if options[:verbose]
132
+ else
133
+ minutes=(timeElapsed/60).floor
134
+ seconds=(timeElapsed % 60).round(4)
135
+ Pxlsrt::Helpers.verbose("Took #{minutes} minute#{ minutes!=1 ? "s" : "" } and #{seconds} second#{ seconds!=1.0 ? "s" : "" }.") if options[:verbose]
136
+ end
137
+ Pxlsrt::Helpers.verbose("Returning ChunkyPNG::Image...") if options[:verbose]
138
+ return png.returnModified
139
+ else
140
+ Pxlsrt::Helpers.error("Options specified do not follow the correct format.") if options[:verbose]
141
+ raise "Bad options"
142
+ end
143
+ end
144
+ # Helper methods
145
+ # Black
146
+ def self.getFirstNotBlackX(img, x, y, blackValue)
147
+ if x < img.getWidth
148
+ while img[x, y] < blackValue
149
+ x += 1
150
+ return -1 if x >= img.getWidth
151
+ end
152
+ end
153
+ return x
154
+ end
155
+ def self.getFirstNotBlackY(img, x, y, blackValue)
156
+ if y < img.getHeight
157
+ while img[x, y] < blackValue
158
+ y += 1
159
+ return -1 if y >= img.getHeight
160
+ end
161
+ end
162
+ return y
163
+ end
164
+ def self.getNextBlackX(img, x, y, blackValue)
165
+ x += 1
166
+ if x < img.getWidth
167
+ while img[x, y] > blackValue
168
+ x += 1
169
+ return (img.getWidth - 1) if x >= img.getWidth
170
+ end
171
+ end
172
+ return x - 1
173
+ end
174
+ def self.getNextBlackY(img, x, y, blackValue)
175
+ y += 1
176
+ if y < img.getHeight
177
+ while img[x, y] > blackValue
178
+ y += 1
179
+ return (img.getHeight - 1) if y >= img.getHeight
180
+ end
181
+ end
182
+ return y - 1
183
+ end
184
+ # Brightness
185
+ def self.getFirstBrightX(img, x, y, brightnessValue)
186
+ if x < img.getWidth
187
+ while ChunkyPNG::Color.to_hsb(img[x, y])[2] * 255 < brightnessValue
188
+ x += 1;
189
+ return -1 if x >= img.getWidth
190
+ end
191
+ end
192
+ return x
193
+ end
194
+ def self.getFirstBrightY(img, x, y, brightnessValue)
195
+ if y < img.getHeight
196
+ while ChunkyPNG::Color.to_hsb(img[x, y])[2] * 255 < brightnessValue
197
+ y += 1;
198
+ return -1 if y >= img.getHeight
199
+ end
200
+ end
201
+ return y
202
+ end
203
+ def self.getNextDarkX(img, x, y, brightnessValue)
204
+ x += 1
205
+ if x < img.getWidth
206
+ while ChunkyPNG::Color.to_hsb(img[x, y])[2] * 255 > brightnessValue
207
+ x += 1
208
+ return (img.getWidth - 1) if x >= img.getWidth
209
+ end
210
+ end
211
+ return x - 1
212
+ end
213
+ def self.getNextDarkY(img, x, y, brightnessValue)
214
+ y += 1
215
+ if y < img.getHeight
216
+ while ChunkyPNG::Color.to_hsb(img[x, y])[2] * 255 > brightnessValue
217
+ y += 1
218
+ return (img.getHeight - 1) if y >= img.getHeight
219
+ end
220
+ end
221
+ return y - 1
222
+ end
223
+ # White
224
+ def self.getFirstNotWhiteX(img, x, y, whiteValue)
225
+ if x < img.getWidth
226
+ while img[x, y] > whiteValue
227
+ x += 1
228
+ return -1 if x >= img.getWidth
229
+ end
230
+ end
231
+ return x
232
+ end
233
+ def self.getFirstNotWhiteY(img, x, y, whiteValue)
234
+ if y < img.getHeight
235
+ while img[x, y] > whiteValue
236
+ y += 1
237
+ return -1 if y >= img.getHeight
238
+ end
239
+ end
240
+ return y
241
+ end
242
+ def self.getNextWhiteX(img, x, y, whiteValue)
243
+ x += 1
244
+ if x < img.getWidth
245
+ while img[x, y] < whiteValue
246
+ x += 1
247
+ return (img.getWidth - 1) if x >= img.getWidth
248
+ end
249
+ end
250
+ return x - 1
251
+ end
252
+ def self.getNextWhiteY(img, x, y, whiteValue)
253
+ y += 1
254
+ if y < img.getHeight
255
+ while img[x, y] < whiteValue
256
+ y += 1
257
+ return (img.getHeight - 1) if y >= img.getHeight
258
+ end
259
+ end
260
+ return y - 1
261
+ end
262
+ end
263
+ end
@@ -1,4 +1,3 @@
1
- require 'rubygems'
2
1
  require 'oily_png'
3
2
 
4
3
  module Pxlsrt
@@ -16,7 +15,7 @@ module Pxlsrt
16
15
  end
17
16
  end
18
17
  ##
19
- # The main attraction of the Smart class. Returns a ChunkyPNG::Image that is sorted according to the options provided. Will return nil if it encounters an errors.
18
+ # The main attraction of the Smart class. Returns a ChunkyPNG::Image that is sorted according to the options provided. Will raise any error that occurs.
20
19
  def self.smart(input, o={})
21
20
  startTime=Time.now
22
21
  defOptions={
@@ -36,7 +35,7 @@ module Pxlsrt
36
35
  :vertical => [false, true],
37
36
  :diagonal => [false, true],
38
37
  :smooth => [false, true],
39
- :method => ["sum-rgb", "red", "green", "blue", "sum-hsb", "hue", "saturation", "brightness", "uniqueness", "luma", "random", "cyan", "magenta", "yellow", "alpha", "sum-rgba", "sum-hsba"],
38
+ :method => Pxlsrt::Colors::METHODS,
40
39
  :verbose => [false, true],
41
40
  :absolute => [false, true],
42
41
  :threshold => [{:class => [Float, Fixnum]}],
@@ -54,17 +53,14 @@ module Pxlsrt
54
53
  else
55
54
  Pxlsrt::Helpers.error("File #{input} is not a valid PNG.") if options[:verbose]
56
55
  raise "Invalid PNG"
57
- return
58
56
  end
59
57
  else
60
58
  Pxlsrt::Helpers.error("File #{input} doesn't exist!") if options[:verbose]
61
59
  raise "File doesn't exist"
62
- return
63
60
  end
64
61
  elsif input.class!=String and input.class!=ChunkyPNG::Image
65
62
  Pxlsrt::Helpers.error("Input is not a filename or ChunkyPNG::Image") if options[:verbose]
66
63
  raise "Invalid input (must be filename or ChunkyPNG::Image)"
67
- return
68
64
  end
69
65
  Pxlsrt::Helpers.verbose("Smart mode.") if options[:verbose]
70
66
  png=Pxlsrt::Image.new(input)
@@ -88,7 +84,9 @@ module Pxlsrt
88
84
  else
89
85
  iterator = lines.keys
90
86
  end
91
- Pxlsrt::Helpers.verbose("Dividing and pixel sorting lines") if options[:verbose]
87
+ prr = 0
88
+ len = iterator.to_a.length
89
+ Pxlsrt::Helpers.progress("Dividing and pixel sorting lines", prr, len) if options[:verbose]
92
90
  for k in iterator
93
91
  line = lines[k]
94
92
  divisions = []
@@ -133,6 +131,8 @@ module Pxlsrt
133
131
  png.replaceDiagonal(k, newLine) if !options[:vertical]
134
132
  png.replaceRDiagonal(k, newLine) if options[:vertical]
135
133
  end
134
+ prr += 1
135
+ Pxlsrt::Helpers.progress("Dividing and pixel sorting lines", prr, len) if options[:verbose]
136
136
  end
137
137
  endTime=Time.now
138
138
  timeElapsed=endTime-startTime
@@ -148,7 +148,6 @@ module Pxlsrt
148
148
  else
149
149
  Pxlsrt::Helpers.error("Options specified do not follow the correct format.") if options[:verbose]
150
150
  raise "Bad options"
151
- return
152
151
  end
153
152
  end
154
153
  end
@@ -1,5 +1,5 @@
1
1
  ##
2
2
  # The main module, your best friend.
3
3
  module Pxlsrt
4
- VERSION = "1.6.3"
4
+ VERSION = "1.7.0"
5
5
  end
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.6.3
4
+ version: 1.7.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-13 00:00:00.000000000 Z
11
+ date: 2014-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,7 @@ files:
80
80
  - lib/pxlsrt/colors.rb
81
81
  - lib/pxlsrt/helpers.rb
82
82
  - lib/pxlsrt/image.rb
83
+ - lib/pxlsrt/kim.rb
83
84
  - lib/pxlsrt/lines.rb
84
85
  - lib/pxlsrt/smart.rb
85
86
  - lib/pxlsrt/version.rb