pxlsrt 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2c2b3280ae7ad02daa4da266d7da0754a3d7723b
4
+ data.tar.gz: 626ec7cf24c9c746e2cdc39f65acd300e2485330
5
+ SHA512:
6
+ metadata.gz: 0e813eab6fb0931f8448cdc4c389c44fdc0cf958b32304ac8da870be94b5dd5422a925f1d72327b9c629b825eb41d31b6b88aa8d4f09e55c4d45d1a545880127
7
+ data.tar.gz: 77cb11792128cd2dfd458f76fa8f7adc0dbf1f0fed6bddd679a56bdfa5d8a81e93bb207e3f74a316c8b838052ee07c83d530d04a0bd89270dbc282a6de337cb7
data/bin/pxlsrt ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'pxlsrt'
5
+ require 'thor'
6
+
7
+ class PXLSRT < Thor
8
+ class_option :reverse, :type => :string, :default => "no", :banner => "[no | reverse | either]", :aliases => "-r", :enum => ["no", "reverse", "either"]
9
+ class_option :vertical, :type => :boolean, :default => false, :aliases => "-v"
10
+ class_option :diagonal, :type => :boolean, :default => false, :aliases => "-d"
11
+ class_option :smooth, :type => :boolean, :default => false, :aliases => "-s"
12
+ class_option :method, :type => :string, :default => "sum-rgb", :banner => "[sum-rgb | red | green | blue | sum-hsb | hue | saturation | brightness | uniqueness | luma | random]", :aliases => "-m", :enum => ["sum-rgb", "red", "green", "blue", "sum-hsb", "hue", "saturation", "brightness", "uniqueness", "luma", "random"]
13
+ class_option :diagonal, :type => :boolean, :default => false, :aliases => "-d"
14
+ class_option :verbose, :type => :boolean, :default => false, :aliases => "-V"
15
+
16
+ option :min, :type => :numeric, :default => Float::INFINITY, :banner => "MINIMUM BANDWIDTH"
17
+ option :max, :type => :numeric, :default => Float::INFINITY, :banner => "MAXIMUM BANDWIDTH"
18
+ desc "brute INPUT OUTPUT [options]", "Brute pixel sorting"
19
+ def brute(input, output)
20
+ k={}
21
+ for o in options.keys
22
+ k[o.to_sym]=options[o]
23
+ end
24
+ Pxlsrt::Brute.suite(input, output, true, k)
25
+ end
26
+
27
+ option :absolute, :type => :boolean, :default => false, :aliases => "-a", :banner => "ABSOLUTE EDGE FINDING"
28
+ option :threshold, :type => :numeric, :default => 20, :aliases => "-t"
29
+ option :edge, :type => :numeric, :default => 2, :aliases => "-e", :banner => "EDGE BUFFERING"
30
+ desc "smart INPUT OUTPUT [options]", "Smart pixel sorting"
31
+ def smart(input, output)
32
+ k={}
33
+ for o in options.keys
34
+ k[o.to_sym]=options[o]
35
+ end
36
+ Pxlsrt::Smart.suite(input, output, true, k)
37
+ end
38
+ end
39
+
40
+ PXLSRT.start(ARGV)
@@ -0,0 +1,137 @@
1
+ require 'rubygems'
2
+ require 'oily_png'
3
+
4
+ module Pxlsrt
5
+ class Brute
6
+ def self.suite(inputFileName, outputFileName, trusted, o={})
7
+ kml=Pxlsrt::Brute.brute(inputFileName, trusted, o)
8
+ if Pxlsrt::Helpers.contented(kml)
9
+ kml.save(outputFileName)
10
+ end
11
+ end
12
+ def self.brute(input, trusted, o={})
13
+ startTime=Time.now
14
+ defOptions={
15
+ :reverse => "no",
16
+ :vertical => false,
17
+ :diagonal => false,
18
+ :smooth => false,
19
+ :method => "sum-rgb",
20
+ :verbose => false,
21
+ :min => Float::INFINITY,
22
+ :max => Float::INFINITY
23
+ }
24
+ defRules={
25
+ :reverse => ["no", "reverse", "either"],
26
+ :vertical => [false, true],
27
+ :diagonal => [false, true],
28
+ :smooth => [false, true],
29
+ :method => ["sum-rgb", "red", "green", "blue", "sum-hsb", "hue", "saturation", "brightness", "uniqueness", "luma", "random"],
30
+ :verbose => [false, true],
31
+ :min => [Float::INFINITY, {:class => [Fixnum]}],
32
+ :max => [Float::INFINITY, {:class => [Fixnum]}]
33
+ }
34
+ options=defOptions.merge(o)
35
+ if o.length==0 or trusted==true or (trusted==false and o.length!=0 and Pxlsrt::Helpers.checkOptions(options, defRules)!=false)
36
+ Pxlsrt::Helpers.verbose("Options are all good.") if options[:verbose]
37
+ if input.class==String
38
+ Pxlsrt::Helpers.verbose("Getting image from file...") if options[:verbose]
39
+ input=ChunkyPNG::Image.from_file(input)
40
+ elsif input.class!=String and input.class!=ChunkyPNG::Image
41
+ Pxlsrt::Helpers.error("Input is not a filename or ChunkyPNG::Image") if options[:verbose]
42
+ return
43
+ end
44
+ Pxlsrt::Helpers.verbose("Brute mode.") if options[:verbose]
45
+ case options[:reverse].downcase
46
+ when "reverse"
47
+ nre=1
48
+ when "either"
49
+ nre=-1
50
+ else
51
+ nre=0
52
+ end
53
+ png=input
54
+ w=png.dimension.width
55
+ h=png.dimension.height
56
+ sorted=ChunkyPNG::Image.new(w, h, ChunkyPNG::Color::TRANSPARENT)
57
+ Pxlsrt::Helpers.verbose("Retrieving RGB values of pixels...") if options[:verbose]
58
+ kml=[]
59
+ for xy in 0..(w*h-1)
60
+ kml.push(Pxlsrt::Colors.getRGB(png[xy % w,(xy/w).floor]))
61
+ end
62
+ if options[:vertical]==true
63
+ Pxlsrt::Helpers.verbose("Rotating image for vertical mode...") if options[:verbose]
64
+ kml=Pxlsrt::Colors.rotateImage(kml, w, h, 3)
65
+ w,h=h,w
66
+ end
67
+ toImage=[]
68
+ if !options[:diagonal]
69
+ Pxlsrt::Helpers.verbose("Pixel sorting using method '#{options[:method]}'...") if options[:verbose]
70
+ for m in Pxlsrt::Colors.imageRGBLines(kml, w)
71
+ sliceRanges=Pxlsrt::Colors.randomSlices(m, options[:min], options[:max])
72
+ newInTown=[]
73
+ if options[:smooth]!=true
74
+ for ranger in sliceRanges
75
+ newInTown.concat(Pxlsrt::Colors.pixelSort(m[ranger[0]..ranger[1]], options[:method].downcase, nre))
76
+ end
77
+ else
78
+ for ranger in sliceRanges
79
+ k=(m[ranger[0]..ranger[1]]).group_by { |x| x }
80
+ g=Pxlsrt::Colors.pixelSort(k.keys, options[:method].downcase, nre)
81
+ j=g.map { |x| k[x] }.flatten(1)
82
+ newInTown.concat(j)
83
+ end
84
+ end
85
+ toImage.concat(newInTown)
86
+ end
87
+ else
88
+ Pxlsrt::Helpers.verbose("Determining diagonals...") if options[:verbose]
89
+ dia=Pxlsrt::Colors.getDiagonals(kml,w,h)
90
+ Pxlsrt::Helpers.verbose("Pixel sorting using method '#{options[:method]}'...") if options[:verbose]
91
+ for m in dia.keys
92
+ sliceRanges=Pxlsrt::Colors.randomSlices(dia[m], options[:min], options[:max])
93
+ newInTown=[]
94
+ if options[:smooth]!=true
95
+ for ranger in sliceRanges
96
+ newInTown.concat(Pxlsrt::Colors.pixelSort(dia[m][ranger[0]..ranger[1]], options[:method].downcase, nre))
97
+ end
98
+ else
99
+ for ranger in sliceRanges
100
+ k=(dia[m][ranger[0]..ranger[1]]).group_by { |x| x }
101
+ g=Pxlsrt::Colors.pixelSort(k.keys, options[:method].downcase, nre)
102
+ j=g.map { |x| k[x] }.flatten(1)
103
+ newInTown.concat(j)
104
+ end
105
+ end
106
+ dia[m]=newInTown
107
+ end
108
+ Pxlsrt::Helpers.verbose("Setting diagonals back to standard lines...") if options[:verbose]
109
+ toImage=Pxlsrt::Colors.fromDiagonals(dia,w)
110
+ end
111
+ if options[:vertical]==true
112
+ Pxlsrt::Helpers.verbose("Rotating back (because of vertical mode).") if options[:verbose]
113
+ toImage=Pxlsrt::Colors.rotateImage(toImage, w,h,1)
114
+ w,h=h,w
115
+ end
116
+ Pxlsrt::Helpers.verbose("Giving pixels new RGB values...") if options[:verbose]
117
+ for xy in 0..(w*h-1)
118
+ sorted[xy % w, (xy/w).floor]=Pxlsrt::Colors.arrayToRGB(toImage[xy])
119
+ end
120
+ endTime=Time.now
121
+ timeElapsed=endTime-startTime
122
+ if timeElapsed < 60
123
+ Pxlsrt::Helpers.verbose("Took #{timeElapsed.round(4)} second#{ timeElapsed!=1.0 ? "s" : "" }.") if options[:verbose]
124
+ else
125
+ minutes=(timeElapsed/60).floor
126
+ seconds=(timeElapsed % 60).round(4)
127
+ Pxlsrt::Helpers.verbose("Took #{minutes} minute#{ minutes!=1 ? "s" : "" } and #{seconds} second#{ seconds!=1.0 ? "s" : "" }.") if options[:verbose]
128
+ end
129
+ Pxlsrt::Helpers.verbose("Returning ChunkyPNG::Image...") if options[:verbose]
130
+ return sorted
131
+ else
132
+ Pxlsrt::Helpers.error("Options specified do not follow the correct format.") if options[:verbose]
133
+ return
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,183 @@
1
+ require "oily_png"
2
+
3
+ module Pxlsrt
4
+ class Colors
5
+ def self.getRGB(pxl)
6
+ return [ChunkyPNG::Color.r(pxl), ChunkyPNG::Color.g(pxl), ChunkyPNG::Color.b(pxl)]
7
+ end
8
+ def self.rotateImage(what, width, height, a)
9
+ nu=[]
10
+ case a
11
+ when 0, 360, 4
12
+ nu=what
13
+ when 1, 90
14
+ for xy in 0..(what.length-1)
15
+ nu[((height-1)-(xy/width).floor)+(xy % width)*height]=what[xy]
16
+ end
17
+ when 2, 180
18
+ nu=what.reverse
19
+ when 3, 270
20
+ for xy in 0..(what.length-1)
21
+ nu[(xy/width).floor+((width-1)-(xy % width))*height]=what[xy]
22
+ end
23
+ end
24
+ return nu
25
+ end
26
+ def self.imageRGBLines(image, width)
27
+ return image.each_slice(width).to_a
28
+ end
29
+ def self.randomSlices(arr, minLength, maxLength)
30
+ len=arr.length-1
31
+ if len!=0
32
+ min=[minLength, maxLength].min
33
+ max=[maxLength, minLength].max
34
+ if min > len
35
+ min=len
36
+ end
37
+ if max > len
38
+ max=len
39
+ end
40
+ nu=[[0, rand(min..max)]]
41
+ last=nu.first[1]
42
+ sorting=true
43
+ while sorting do
44
+ if (len-last) <= max
45
+ nu.push([last+1, len])
46
+ sorting=false
47
+ else
48
+ nu.push([last+1, last+1+rand(min..max)])
49
+ last=nu.last[1]
50
+ end
51
+ end
52
+ else
53
+ nu=[[0,0]]
54
+ end
55
+ return nu
56
+ end
57
+ def self.pxldex(pxl)
58
+ return pxl[0]+pxl[1]+pxl[2]
59
+ end
60
+ def self.rgb2hsb(rgb)
61
+ r = rgb[0] / 255.0
62
+ g = rgb[1] / 255.0
63
+ b = rgb[2] / 255.0
64
+ max = [r, g, b].max
65
+ min = [r, g, b].min
66
+ delta = max - min
67
+ v = max * 100
68
+ if (max != 0.0)
69
+ s = delta / max *100
70
+ else
71
+ s = 0.0
72
+ end
73
+ if (s == 0.0)
74
+ h = 0.0
75
+ else
76
+ if (r == max)
77
+ h = (g - b) / delta
78
+ elsif (g == max)
79
+ h = 2 + (b - r) / delta
80
+ elsif (b == max)
81
+ h = 4 + (r - g) / delta
82
+ end
83
+ h *= 60.0
84
+ if (h < 0)
85
+ h += 360.0
86
+ end
87
+ end
88
+ return [h,s,v]
89
+ end
90
+ def self.colorAverage(ca)
91
+ if ca.length==1
92
+ return ca.first
93
+ end
94
+ r=((ca.collect { |c| c[0] }).inject{ |sum, el| sum+el }).to_f / ca.size
95
+ g=((ca.collect { |c| c[1] }).inject{ |sum, el| sum+el }).to_f / ca.size
96
+ b=((ca.collect { |c| c[2] }).inject{ |sum, el| sum+el }).to_f / ca.size
97
+ return [r,g,b]
98
+ end
99
+ def self.colorDistance(c1,c2)
100
+ return Math.sqrt((c1[0]-c2[0])**2+(c1[1]-c2[1])**2+(c1[2]-c2[2])**2)
101
+ end
102
+ def self.colorUniqueness(c, ca)
103
+ return Pxlsrt::Colors.colorDistance(c, Pxlsrt::Colors.colorAverage(ca))
104
+ end
105
+ def self.pixelSort(list, how, reverse)
106
+ mhm=[]
107
+ case how.downcase
108
+ when "sum-rgb"
109
+ mhm= list.sort_by { |c| Pxlsrt::Colors.pxldex(c) }
110
+ when "red"
111
+ mhm= list.sort_by { |c| c[0] }
112
+ when "green"
113
+ mhm= list.sort_by { |c| c[1] }
114
+ when "blue"
115
+ mhm= list.sort_by { |c| c[2] }
116
+ when "hue"
117
+ mhm= list.sort_by { |c| Pxlsrt::Colors.rgb2hsb(c)[0] }
118
+ when "saturation"
119
+ mhm= list.sort_by { |c| Pxlsrt::Colors.rgb2hsb(c)[1] }
120
+ when "brightness"
121
+ mhm= list.sort_by { |c| Pxlsrt::Colors.rgb2hsb(c)[2] }
122
+ when "sum-hsb"
123
+ mhm= list.sort_by { |c| k=Pxlsrt::Colors.rgb2hsb(c); k[0]*100/360+k[1]+k[2] }
124
+ when "uniqueness"
125
+ avg=Pxlsrt::Colors.colorAverage(list)
126
+ mhm=list.sort_by { |c| Pxlsrt::Colors.colorUniqueness(c, [avg]) }
127
+ when "luma"
128
+ mhm=list.sort_by { |c| Pxlsrt::Colors.pxldex([c[0]*0.2126, c[1]*0.7152, c[2]*0.0722]) }
129
+ when "random"
130
+ mhm=list.shuffle
131
+ else
132
+ mhm= list.sort_by { |c| Pxlsrt::Colors.pxldex(c) }
133
+ end
134
+ if reverse == 0
135
+ return mhm
136
+ elsif reverse == 1
137
+ return mhm.reverse
138
+ else
139
+ return rand(0..1)==0 ? mhm : mhm.reverse
140
+ end
141
+ end
142
+ def self.getDiagonals(array, width, height)
143
+ dias={}
144
+ for x in (1-height)..(width-1)
145
+ z=[]
146
+ for y in 0..(height-1)
147
+ if (x+(width+1)*y).between?(width*y, (width*(y+1)-1))
148
+ z.push(array[(x+(width+1)*y)])
149
+ end
150
+ end
151
+ dias[x.to_s]=z
152
+ end
153
+ return dias
154
+ end
155
+ def self.fromDiagonals(obj, width)
156
+ ell=[]
157
+ for k in obj.keys
158
+ r=k.to_i
159
+ n=r < 0
160
+ if n
161
+ x=0
162
+ y=r.abs
163
+ else
164
+ x=r
165
+ y=0
166
+ end
167
+ ell[x+y*width]=obj[k].first
168
+ for v in 1..(obj[k].length-1)
169
+ x+=1
170
+ y+=1
171
+ ell[x+y*width]=obj[k][v]
172
+ end
173
+ end
174
+ return ell
175
+ end
176
+ def self.arrayToRGB(a)
177
+ return ChunkyPNG::Color.rgb(a[0], a[1], a[2])
178
+ end
179
+ def self.sobelate(i, x,y)
180
+ return ChunkyPNG::Color.to_grayscale_bytes(i[x,y]).first
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,49 @@
1
+ module Pxlsrt
2
+ class Helpers
3
+ def self.contented(c)
4
+ return (c.class!=NilClass and ((defined? c)!="nil") and ((/(\S)/.match("#{c}"))!=nil))
5
+ end
6
+ def self.red(what)
7
+ return "\e[31m#{what}\e[0m"
8
+ end
9
+ def self.cyan(what)
10
+ return "\e[36m#{what}\e[0m"
11
+ end
12
+ def self.checkOptions(options, rules)
13
+ match=true
14
+ for o in options.keys
15
+ o_match=false
16
+ if rules[o].class==Array
17
+ if rules[o].include?(options[o])
18
+ o_match=true
19
+ else
20
+ for r in 0...rules[o].length
21
+ if rules[o][r].class==Hash
22
+ for n in rules[o][r][:class]
23
+ if n==options[o].class
24
+ o_match=match
25
+ break
26
+ end
27
+ end
28
+ end
29
+ if o_match==true
30
+ break
31
+ end
32
+ end
33
+ end
34
+ end
35
+ match=(match and o_match)
36
+ if match==false
37
+ break
38
+ end
39
+ end
40
+ return match
41
+ end
42
+ def self.error(what)
43
+ puts "#{Pxlsrt::Helpers.red("pxlsrt")} #{what}"
44
+ end
45
+ def self.verbose(what)
46
+ puts "#{Pxlsrt::Helpers.cyan("pxlsrt")} #{what}"
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,219 @@
1
+ require 'rubygems'
2
+ require 'oily_png'
3
+ require 'json'
4
+ require 'pathname'
5
+ require 'fileutils'
6
+ require 'base64'
7
+
8
+ module Pxlsrt
9
+ class Smart
10
+ def self.suite(inputFileName, outputFileName, trusted, o={})
11
+ kml=Pxlsrt::Smart.smart(inputFileName, trusted, o)
12
+ if Pxlsrt::Helpers.contented(kml)
13
+ kml.save(outputFileName)
14
+ end
15
+ end
16
+ def self.smart(input, trusted, o={})
17
+ startTime=Time.now
18
+ defOptions={
19
+ :reverse => "no",
20
+ :vertical => false,
21
+ :diagonal => false,
22
+ :smooth => false,
23
+ :method => "sum-rgb",
24
+ :verbose => false,
25
+ :absolute => false,
26
+ :threshold => 20,
27
+ :edge => 2
28
+ }
29
+ defRules={
30
+ :reverse => ["no", "reverse", "either"],
31
+ :vertical => [false, true],
32
+ :diagonal => [false, true],
33
+ :smooth => [false, true],
34
+ :method => ["sum-rgb", "red", "green", "blue", "sum-hsb", "hue", "saturation", "brightness", "uniqueness", "luma", "random"],
35
+ :verbose => [false, true],
36
+ :absolute => [false, true],
37
+ :threshold => [{:class => [Float, Fixnum]}],
38
+ :edge => [{:class => [Fixnum]}]
39
+ }
40
+ options=defOptions.merge(o)
41
+ if o.length==0 or trusted==true or (trusted==false and o.length!=0 and Pxlsrt::Helpers.checkOptions(options, defRules)!=false)
42
+ Pxlsrt::Helpers.verbose("Options are all good.") if options[:verbose]
43
+ if input.class==String
44
+ Pxlsrt::Helpers.verbose("Getting image from file...") if options[:verbose]
45
+ input=ChunkyPNG::Image.from_file(input)
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
+ return
49
+ end
50
+ Pxlsrt::Helpers.verbose("Smart mode.") if options[:verbose]
51
+ case options[:reverse].downcase
52
+ when "reverse"
53
+ nre=1
54
+ when "either"
55
+ nre=-1
56
+ else
57
+ nre=0
58
+ end
59
+ img=input
60
+ w,h=img.width,img.height
61
+ sobel_x = [[-1,0,1], [-2,0,2], [-1,0,1]]
62
+ sobel_y = [[-1,-2,-1], [ 0, 0, 0], [ 1, 2, 1]]
63
+ edge = ChunkyPNG::Image.new(w, h, ChunkyPNG::Color::TRANSPARENT)
64
+ valued="start"
65
+ k=[]
66
+ Pxlsrt::Helpers.verbose("Getting Sobel values and colors for pixels...") if options[:verbose]
67
+ for xy in 0..(w*h-1)
68
+ x=xy % w
69
+ y=(xy/w).floor
70
+ if x!=0 and x!=(w-1) and y!=0 and y!=(h-1)
71
+ pixel_x=(sobel_x[0][0]*Pxlsrt::Colors.sobelate(img,x-1,y-1))+(sobel_x[0][1]*Pxlsrt::Colors.sobelate(img,x,y-1))+(sobel_x[0][2]*Pxlsrt::Colors.sobelate(img,x+1,y-1))+(sobel_x[1][0]*Pxlsrt::Colors.sobelate(img,x-1,y))+(sobel_x[1][1]*Pxlsrt::Colors.sobelate(img,x,y))+(sobel_x[1][2]*Pxlsrt::Colors.sobelate(img,x+1,y))+(sobel_x[2][0]*Pxlsrt::Colors.sobelate(img,x-1,y+1))+(sobel_x[2][1]*Pxlsrt::Colors.sobelate(img,x,y+1))+(sobel_x[2][2]*Pxlsrt::Colors.sobelate(img,x+1,y+1))
72
+ pixel_y=(sobel_y[0][0]*Pxlsrt::Colors.sobelate(img,x-1,y-1))+(sobel_y[0][1]*Pxlsrt::Colors.sobelate(img,x,y-1))+(sobel_y[0][2]*Pxlsrt::Colors.sobelate(img,x+1,y-1))+(sobel_y[1][0]*Pxlsrt::Colors.sobelate(img,x-1,y))+(sobel_y[1][1]*Pxlsrt::Colors.sobelate(img,x,y))+(sobel_y[1][2]*Pxlsrt::Colors.sobelate(img,x+1,y))+(sobel_y[2][0]*Pxlsrt::Colors.sobelate(img,x-1,y+1))+(sobel_y[2][1]*Pxlsrt::Colors.sobelate(img,x,y+1))+(sobel_y[2][2]*Pxlsrt::Colors.sobelate(img,x+1,y+1))
73
+ val = Math.sqrt(pixel_x * pixel_x + pixel_y * pixel_y).ceil
74
+ else
75
+ val = 2000000000
76
+ end
77
+ k.push({ "sobel" => val, "pixel" => [x, y], "color" => Pxlsrt::Colors.getRGB(img[x, y]) })
78
+ end
79
+ if options[:vertical]==true
80
+ Pxlsrt::Helpers.verbose("Rotating image for vertical mode...") if options[:verbose]
81
+ k=Pxlsrt::Colors.rotateImage(k,w,h,3)
82
+ w,h=h,w
83
+ end
84
+ if !options[:diagonal]
85
+ lines=Pxlsrt::Colors.imageRGBLines(k, w)
86
+ Pxlsrt::Helpers.verbose("Determining bands with a#{options[:absolute] ? "n absolute" : " relative"} threshold of #{options[:threshold]}...") if options[:verbose]
87
+ bands=Array.new()
88
+ for j in lines
89
+ slicing=true
90
+ pixel=0
91
+ m=Array.new()
92
+ while slicing do
93
+ n=Array.new
94
+ if m.length > 1
95
+ while m.last.length < options[:edge]
96
+ if m.length > 1
97
+ m[-2].concat(m[-1])
98
+ m.pop
99
+ else
100
+ break
101
+ end
102
+ end
103
+ end
104
+ bandWorking=true
105
+ while bandWorking do
106
+ n.push(j[pixel]["color"])
107
+ if (options[:absolute] ? (j[pixel+1]["sobel"]) : (j[pixel+1]["sobel"]-j[pixel]["sobel"])) > options[:threshold]
108
+ bandWorking=false
109
+ end
110
+ if (pixel+1)==(j.length-1)
111
+ n.push(j[pixel+1]["color"])
112
+ slicing=false
113
+ bandWorking=false
114
+ end
115
+ pixel+=1
116
+ end
117
+ m.push(n)
118
+ end
119
+ bands.concat(m)
120
+ end
121
+ Pxlsrt::Helpers.verbose("Pixel sorting using method '#{options[:method]}'...") if options[:verbose]
122
+ image=[]
123
+ if options[:smooth]
124
+ for band in bands
125
+ u=band.group_by {|x| x}
126
+ image.concat(Pxlsrt::Colors.pixelSort(u.keys, options[:method], nre).map { |x| u[x] }.flatten(1))
127
+ end
128
+ else
129
+ for band in bands
130
+ image.concat(Pxlsrt::Colors.pixelSort(band, options[:method], nre))
131
+ end
132
+ end
133
+ else
134
+ Pxlsrt::Helpers.verbose("Determining diagonals...") if options[:verbose]
135
+ dia=Pxlsrt::Colors.getDiagonals(k,w,h)
136
+ Pxlsrt::Helpers.verbose("Determining bands with a#{options[:absolute] ? "n absolute" : " relative"} threshold of #{options[:threshold]}...") if options[:verbose]
137
+ for j in dia.keys
138
+ bands=[]
139
+ if dia[j].length>1
140
+ slicing=true
141
+ pixel=0
142
+ m=Array.new()
143
+ while slicing do
144
+ n=Array.new
145
+ if m.length > 1
146
+ while m.last.length < options[:edge]
147
+ if m.length > 1
148
+ m[-2].concat(m[-1])
149
+ m.pop
150
+ else
151
+ break
152
+ end
153
+ end
154
+ end
155
+ bandWorking=true
156
+ while bandWorking do
157
+ n.push(dia[j][pixel]["color"])
158
+ if (options[:absolute] ? (dia[j][pixel+1]["sobel"]) : (dia[j][pixel+1]["sobel"]-dia[j][pixel]["sobel"])) > options[:threshold]
159
+ bandWorking=false
160
+ end
161
+ if (pixel+1)==(dia[j].length-1)
162
+ n.push(dia[j][pixel+1]["color"])
163
+ slicing=false
164
+ bandWorking=false
165
+ end
166
+ pixel+=1
167
+ end
168
+ m.push(n)
169
+ end
170
+ else
171
+ m=[[dia[j].first["color"]]]
172
+ end
173
+ dia[j]=bands.concat(m)
174
+ end
175
+ Pxlsrt::Helpers.verbose("Pixel sorting using method '#{options[:method]}'...") if options[:verbose]
176
+ for j in dia.keys
177
+ ell=[]
178
+ if options[:smooth]
179
+ for band in dia[j]
180
+ u=band.group_by {|x| x}
181
+ ell.concat(Pxlsrt::Colors.pixelSort(u.keys, options[:method], nre).map { |x| u[x] }.flatten(1))
182
+ end
183
+ else
184
+ for band in dia[j]
185
+ ell.concat(Pxlsrt::Colors.pixelSort(band, options[:method], nre))
186
+ end
187
+ end
188
+ dia[j]=ell
189
+ end
190
+ Pxlsrt::Helpers.verbose("Setting diagonals back to standard lines...") if options[:verbose]
191
+ image=Pxlsrt::Colors.fromDiagonals(dia,w)
192
+ end
193
+ if options[:vertical]==true
194
+ Pxlsrt::Helpers.verbose("Rotating back (because of vertical mode).") if options[:verbose]
195
+ image=Pxlsrt::Colors.rotateImage(image,w,h,1)
196
+ w,h=h,w
197
+ end
198
+ Pxlsrt::Helpers.verbose("Giving pixels new RGB values...") if options[:verbose]
199
+ for px in 0..(w*h-1)
200
+ edge[px % w, (px/w).floor]=Pxlsrt::Colors.arrayToRGB(image[px])
201
+ end
202
+ endTime=Time.now
203
+ timeElapsed=endTime-startTime
204
+ if timeElapsed < 60
205
+ Pxlsrt::Helpers.verbose("Took #{timeElapsed.round(4)} second#{ timeElapsed.round(4)!=1.0 ? "s" : "" }.") if options[:verbose]
206
+ else
207
+ minutes=(timeElapsed/60).floor
208
+ seconds=(timeElapsed % 60).round(4)
209
+ Pxlsrt::Helpers.verbose("Took #{minutes} minute#{ minutes!=1 ? "s" : "" } and #{seconds} second#{ seconds!=1.0 ? "s" : "" }.") if options[:verbose]
210
+ end
211
+ Pxlsrt::Helpers.verbose("Returning ChunkyPNG::Image...") if options[:verbose]
212
+ return edge
213
+ else
214
+ Pxlsrt::Helpers.error("Options specified do not follow the correct format.") if options[:verbose]
215
+ return
216
+ end
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,3 @@
1
+ module Pxlsrt
2
+ VERSION = "1.0.0"
3
+ end
data/lib/pxlsrt.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "pxlsrt/version"
2
+ require "pxlsrt/colors"
3
+ require "pxlsrt/helpers"
4
+ require "pxlsrt/brute"
5
+ require "pxlsrt/smart"
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pxlsrt
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - EVA-01
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: oily_png
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 1.1.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.1.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: thor
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.18'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.18'
69
+ description: Pixel sort PNG files with ease!
70
+ email:
71
+ - j.bruno.che@gmail.com
72
+ executables:
73
+ - pxlsrt
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - bin/pxlsrt
78
+ - lib/pxlsrt.rb
79
+ - lib/pxlsrt/brute.rb
80
+ - lib/pxlsrt/colors.rb
81
+ - lib/pxlsrt/helpers.rb
82
+ - lib/pxlsrt/smart.rb
83
+ - lib/pxlsrt/version.rb
84
+ homepage: https://github.com/EVA-01/pxlsrt
85
+ licenses:
86
+ - MIT
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 2.2.2
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: Pixel sort PNG files.
108
+ test_files: []