pxlsrt 1.6.1 → 1.6.2
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 +4 -4
- data/bin/pxlsrt +55 -55
- data/lib/pxlsrt/brute.rb +119 -119
- data/lib/pxlsrt/colors.rb +159 -159
- data/lib/pxlsrt/helpers.rb +93 -93
- data/lib/pxlsrt/lines.rb +156 -156
- data/lib/pxlsrt/smart.rb +150 -150
- data/lib/pxlsrt/version.rb +5 -5
- metadata +7 -7
data/lib/pxlsrt/lines.rb
CHANGED
@@ -1,157 +1,157 @@
|
|
1
|
-
module Pxlsrt
|
2
|
-
##
|
3
|
-
# "Line" operations used on arrays f colors.
|
4
|
-
class Lines
|
5
|
-
##
|
6
|
-
# ChunkyPNG's rotation was a little slow and doubled runtime.
|
7
|
-
# This "rotates" an array, based on the width and height.
|
8
|
-
# It uses math and it's really cool, trust me.
|
9
|
-
def self.rotateImage(what, width, height, a)
|
10
|
-
nu=[]
|
11
|
-
case a
|
12
|
-
when 0, 360, 4
|
13
|
-
nu=what
|
14
|
-
when 1, 90
|
15
|
-
for xy in 0..(what.length-1)
|
16
|
-
nu[((height-1)-(xy/width).floor)+(xy % width)*height]=what[xy]
|
17
|
-
end
|
18
|
-
when 2, 180
|
19
|
-
nu=what.reverse
|
20
|
-
when 3, 270
|
21
|
-
for xy in 0..(what.length-1)
|
22
|
-
nu[(xy/width).floor+((width-1)-(xy % width))*height]=what[xy]
|
23
|
-
end
|
24
|
-
end
|
25
|
-
return nu
|
26
|
-
end
|
27
|
-
##
|
28
|
-
# Some fancy rearranging.
|
29
|
-
# [a, b, c, d, e] -> [d, b, a, c, e]
|
30
|
-
# [a, b, c, d] -> [c, a, b, d]
|
31
|
-
def self.middlate(arr)
|
32
|
-
a=[]
|
33
|
-
for e in 0...arr.length
|
34
|
-
if (arr.length+e) % 2 == 1
|
35
|
-
a[0.5*(arr.length+e-1)]=arr[e]
|
36
|
-
elsif (arr.length+e) % 2 == 0
|
37
|
-
a[0.5*(arr.length-e)-1]=arr[e]
|
38
|
-
end
|
39
|
-
end
|
40
|
-
return a
|
41
|
-
end
|
42
|
-
##
|
43
|
-
# Some fancy unrearranging.
|
44
|
-
# [d, b, a, c, e] -> [a, b, c, d, e]
|
45
|
-
# [c, a, b, d] -> [a, b, c, d]
|
46
|
-
def self.reverseMiddlate(arr)
|
47
|
-
a=[]
|
48
|
-
for e in 0...arr.length
|
49
|
-
if e == ((arr.length/2.0).ceil - 1)
|
50
|
-
a[0] = arr[e]
|
51
|
-
elsif e < ((arr.length/2.0).ceil - 1)
|
52
|
-
a[arr.length - 2*e - 2] = arr[e]
|
53
|
-
elsif e > ((arr.length/2.0).ceil - 1)
|
54
|
-
a[2*e - arr.length + 1] = arr[e]
|
55
|
-
end
|
56
|
-
end
|
57
|
-
return a
|
58
|
-
end
|
59
|
-
##
|
60
|
-
# Handle middlate requests
|
61
|
-
def self.handleMiddlate(arr, d)
|
62
|
-
n = Pxlsrt::Helpers.isNumeric?(d)
|
63
|
-
if n and d.to_i > 0
|
64
|
-
k = arr
|
65
|
-
for l in 0...(d.to_i)
|
66
|
-
k = Pxlsrt::Lines.middlate(k)
|
67
|
-
end
|
68
|
-
return k
|
69
|
-
elsif n and d.to_i < 0
|
70
|
-
k = arr
|
71
|
-
for l in 0...(d.to_i.abs)
|
72
|
-
k = Pxlsrt::Lines.reverseMiddlate(k)
|
73
|
-
end
|
74
|
-
return k
|
75
|
-
elsif d == "" or d == "middle"
|
76
|
-
return Pxlsrt::Lines.middlate(arr)
|
77
|
-
else
|
78
|
-
return arr
|
79
|
-
end
|
80
|
-
end
|
81
|
-
##
|
82
|
-
# Gets "rows" of an array based on a width
|
83
|
-
def self.imageRGBLines(image, width)
|
84
|
-
return image.each_slice(width).to_a
|
85
|
-
end
|
86
|
-
##
|
87
|
-
# Outputs random slices of an array.
|
88
|
-
# Because of the requirements of pxlsrt, it doesn't actually slice the array, but returns a range-like array. Example:
|
89
|
-
# [[0, 5], [6, 7], [8, 10]]
|
90
|
-
def self.randomSlices(mainLength, minLength, maxLength)
|
91
|
-
if mainLength <= 1
|
92
|
-
return [[0, 0]]
|
93
|
-
else
|
94
|
-
min = [minLength, maxLength].min
|
95
|
-
max = [minLength, maxLength].max
|
96
|
-
min = mainLength if min > mainLength
|
97
|
-
max = mainLength if max > mainLength
|
98
|
-
min = 1 if min < 1
|
99
|
-
max = 1 if max < 1
|
100
|
-
nu = [[0, rand(min..max) - 1]]
|
101
|
-
last = nu.last.last
|
102
|
-
sorting = true
|
103
|
-
i = 0
|
104
|
-
while sorting do
|
105
|
-
if (mainLength - last) <= max
|
106
|
-
if last + 1 <= mainLength - 1
|
107
|
-
nu.push([last + 1, mainLength - 1])
|
108
|
-
end
|
109
|
-
sorting = false
|
110
|
-
else
|
111
|
-
nu.push([last+1, last + rand(min..max)])
|
112
|
-
end
|
113
|
-
last = nu.last.last
|
114
|
-
end
|
115
|
-
return nu
|
116
|
-
end
|
117
|
-
end
|
118
|
-
##
|
119
|
-
# Uses math to turn an array into an array of diagonals.
|
120
|
-
def self.getDiagonals(array, width, height)
|
121
|
-
dias={}
|
122
|
-
for x in (1-height)..(width-1)
|
123
|
-
z=[]
|
124
|
-
for y in 0..(height-1)
|
125
|
-
if (x+(width+1)*y).between?(width*y, (width*(y+1)-1))
|
126
|
-
z.push(array[(x+(width+1)*y)])
|
127
|
-
end
|
128
|
-
end
|
129
|
-
dias[x.to_s]=z
|
130
|
-
end
|
131
|
-
return dias
|
132
|
-
end
|
133
|
-
##
|
134
|
-
# Uses math to turn an array of diagonals into a linear array.
|
135
|
-
def self.fromDiagonals(obj, width)
|
136
|
-
ell=[]
|
137
|
-
for k in obj.keys
|
138
|
-
r=k.to_i
|
139
|
-
n=r < 0
|
140
|
-
if n
|
141
|
-
x=0
|
142
|
-
y=r.abs
|
143
|
-
else
|
144
|
-
x=r
|
145
|
-
y=0
|
146
|
-
end
|
147
|
-
ell[x+y*width]=obj[k].first
|
148
|
-
for v in 1..(obj[k].length-1)
|
149
|
-
x+=1
|
150
|
-
y+=1
|
151
|
-
ell[x+y*width]=obj[k][v]
|
152
|
-
end
|
153
|
-
end
|
154
|
-
return ell
|
155
|
-
end
|
156
|
-
end
|
1
|
+
module Pxlsrt
|
2
|
+
##
|
3
|
+
# "Line" operations used on arrays f colors.
|
4
|
+
class Lines
|
5
|
+
##
|
6
|
+
# ChunkyPNG's rotation was a little slow and doubled runtime.
|
7
|
+
# This "rotates" an array, based on the width and height.
|
8
|
+
# It uses math and it's really cool, trust me.
|
9
|
+
def self.rotateImage(what, width, height, a)
|
10
|
+
nu=[]
|
11
|
+
case a
|
12
|
+
when 0, 360, 4
|
13
|
+
nu=what
|
14
|
+
when 1, 90
|
15
|
+
for xy in 0..(what.length-1)
|
16
|
+
nu[((height-1)-(xy/width).floor)+(xy % width)*height]=what[xy]
|
17
|
+
end
|
18
|
+
when 2, 180
|
19
|
+
nu=what.reverse
|
20
|
+
when 3, 270
|
21
|
+
for xy in 0..(what.length-1)
|
22
|
+
nu[(xy/width).floor+((width-1)-(xy % width))*height]=what[xy]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
return nu
|
26
|
+
end
|
27
|
+
##
|
28
|
+
# Some fancy rearranging.
|
29
|
+
# [a, b, c, d, e] -> [d, b, a, c, e]
|
30
|
+
# [a, b, c, d] -> [c, a, b, d]
|
31
|
+
def self.middlate(arr)
|
32
|
+
a=[]
|
33
|
+
for e in 0...arr.length
|
34
|
+
if (arr.length+e) % 2 == 1
|
35
|
+
a[0.5*(arr.length+e-1)]=arr[e]
|
36
|
+
elsif (arr.length+e) % 2 == 0
|
37
|
+
a[0.5*(arr.length-e)-1]=arr[e]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
return a
|
41
|
+
end
|
42
|
+
##
|
43
|
+
# Some fancy unrearranging.
|
44
|
+
# [d, b, a, c, e] -> [a, b, c, d, e]
|
45
|
+
# [c, a, b, d] -> [a, b, c, d]
|
46
|
+
def self.reverseMiddlate(arr)
|
47
|
+
a=[]
|
48
|
+
for e in 0...arr.length
|
49
|
+
if e == ((arr.length/2.0).ceil - 1)
|
50
|
+
a[0] = arr[e]
|
51
|
+
elsif e < ((arr.length/2.0).ceil - 1)
|
52
|
+
a[arr.length - 2*e - 2] = arr[e]
|
53
|
+
elsif e > ((arr.length/2.0).ceil - 1)
|
54
|
+
a[2*e - arr.length + 1] = arr[e]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
return a
|
58
|
+
end
|
59
|
+
##
|
60
|
+
# Handle middlate requests
|
61
|
+
def self.handleMiddlate(arr, d)
|
62
|
+
n = Pxlsrt::Helpers.isNumeric?(d)
|
63
|
+
if n and d.to_i > 0
|
64
|
+
k = arr
|
65
|
+
for l in 0...(d.to_i)
|
66
|
+
k = Pxlsrt::Lines.middlate(k)
|
67
|
+
end
|
68
|
+
return k
|
69
|
+
elsif n and d.to_i < 0
|
70
|
+
k = arr
|
71
|
+
for l in 0...(d.to_i.abs)
|
72
|
+
k = Pxlsrt::Lines.reverseMiddlate(k)
|
73
|
+
end
|
74
|
+
return k
|
75
|
+
elsif d == "" or d == "middle"
|
76
|
+
return Pxlsrt::Lines.middlate(arr)
|
77
|
+
else
|
78
|
+
return arr
|
79
|
+
end
|
80
|
+
end
|
81
|
+
##
|
82
|
+
# Gets "rows" of an array based on a width
|
83
|
+
def self.imageRGBLines(image, width)
|
84
|
+
return image.each_slice(width).to_a
|
85
|
+
end
|
86
|
+
##
|
87
|
+
# Outputs random slices of an array.
|
88
|
+
# Because of the requirements of pxlsrt, it doesn't actually slice the array, but returns a range-like array. Example:
|
89
|
+
# [[0, 5], [6, 7], [8, 10]]
|
90
|
+
def self.randomSlices(mainLength, minLength, maxLength)
|
91
|
+
if mainLength <= 1
|
92
|
+
return [[0, 0]]
|
93
|
+
else
|
94
|
+
min = [minLength, maxLength].min
|
95
|
+
max = [minLength, maxLength].max
|
96
|
+
min = mainLength if min > mainLength
|
97
|
+
max = mainLength if max > mainLength
|
98
|
+
min = 1 if min < 1
|
99
|
+
max = 1 if max < 1
|
100
|
+
nu = [[0, rand(min..max) - 1]]
|
101
|
+
last = nu.last.last
|
102
|
+
sorting = true
|
103
|
+
i = 0
|
104
|
+
while sorting do
|
105
|
+
if (mainLength - last) <= max
|
106
|
+
if last + 1 <= mainLength - 1
|
107
|
+
nu.push([last + 1, mainLength - 1])
|
108
|
+
end
|
109
|
+
sorting = false
|
110
|
+
else
|
111
|
+
nu.push([last+1, last + rand(min..max)])
|
112
|
+
end
|
113
|
+
last = nu.last.last
|
114
|
+
end
|
115
|
+
return nu
|
116
|
+
end
|
117
|
+
end
|
118
|
+
##
|
119
|
+
# Uses math to turn an array into an array of diagonals.
|
120
|
+
def self.getDiagonals(array, width, height)
|
121
|
+
dias={}
|
122
|
+
for x in (1-height)..(width-1)
|
123
|
+
z=[]
|
124
|
+
for y in 0..(height-1)
|
125
|
+
if (x+(width+1)*y).between?(width*y, (width*(y+1)-1))
|
126
|
+
z.push(array[(x+(width+1)*y)])
|
127
|
+
end
|
128
|
+
end
|
129
|
+
dias[x.to_s]=z
|
130
|
+
end
|
131
|
+
return dias
|
132
|
+
end
|
133
|
+
##
|
134
|
+
# Uses math to turn an array of diagonals into a linear array.
|
135
|
+
def self.fromDiagonals(obj, width)
|
136
|
+
ell=[]
|
137
|
+
for k in obj.keys
|
138
|
+
r=k.to_i
|
139
|
+
n=r < 0
|
140
|
+
if n
|
141
|
+
x=0
|
142
|
+
y=r.abs
|
143
|
+
else
|
144
|
+
x=r
|
145
|
+
y=0
|
146
|
+
end
|
147
|
+
ell[x+y*width]=obj[k].first
|
148
|
+
for v in 1..(obj[k].length-1)
|
149
|
+
x+=1
|
150
|
+
y+=1
|
151
|
+
ell[x+y*width]=obj[k][v]
|
152
|
+
end
|
153
|
+
end
|
154
|
+
return ell
|
155
|
+
end
|
156
|
+
end
|
157
157
|
end
|
data/lib/pxlsrt/smart.rb
CHANGED
@@ -1,151 +1,151 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'oily_png'
|
3
|
-
|
4
|
-
module Pxlsrt
|
5
|
-
##
|
6
|
-
# Smart sorting uses sorted-finding algorithms to create bands to sort,
|
7
|
-
# as opposed to brute sorting which doesn't care for the content or
|
8
|
-
# sorteds, just a specified range to create bands.
|
9
|
-
class Smart
|
10
|
-
##
|
11
|
-
# Uses Pxlsrt::Smart.smart to input and output from pne method.
|
12
|
-
def self.suite(inputFileName, outputFileName, o={})
|
13
|
-
kml=Pxlsrt::Smart.smart(inputFileName, o)
|
14
|
-
if Pxlsrt::Helpers.contented(kml)
|
15
|
-
kml.save(outputFileName)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
##
|
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.
|
20
|
-
def self.smart(input, o={})
|
21
|
-
startTime=Time.now
|
22
|
-
defOptions={
|
23
|
-
:reverse => false,
|
24
|
-
:vertical => false,
|
25
|
-
:diagonal => false,
|
26
|
-
:smooth => false,
|
27
|
-
:method => "sum-rgb",
|
28
|
-
:verbose => false,
|
29
|
-
:absolute => false,
|
30
|
-
:threshold => 20,
|
31
|
-
:trusted => false,
|
32
|
-
:middle => false
|
33
|
-
}
|
34
|
-
defRules={
|
35
|
-
:reverse => :anything,
|
36
|
-
:vertical => [false, true],
|
37
|
-
:diagonal => [false, true],
|
38
|
-
: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"],
|
40
|
-
:verbose => [false, true],
|
41
|
-
:absolute => [false, true],
|
42
|
-
:threshold => [{:class => [Float, Fixnum]}],
|
43
|
-
:trusted => [false, true],
|
44
|
-
:middle => :anything
|
45
|
-
}
|
46
|
-
options=defOptions.merge(o)
|
47
|
-
if o.length==0 or options[:trusted]==true or (options[:trusted]==false and o.length!=0 and Pxlsrt::Helpers.checkOptions(options, defRules)!=false)
|
48
|
-
Pxlsrt::Helpers.verbose("Options are all good.") if options[:verbose]
|
49
|
-
if input.class==String
|
50
|
-
Pxlsrt::Helpers.verbose("Getting image from file...") if options[:verbose]
|
51
|
-
if File.file?(input)
|
52
|
-
if Pxlsrt::Colors.isPNG?(input)
|
53
|
-
input=ChunkyPNG::Image.from_file(input)
|
54
|
-
else
|
55
|
-
Pxlsrt::Helpers.error("File #{input} is not a valid PNG.") if options[:verbose]
|
56
|
-
return
|
57
|
-
end
|
58
|
-
else
|
59
|
-
Pxlsrt::Helpers.error("File #{input} doesn't exist!") if options[:verbose]
|
60
|
-
return
|
61
|
-
end
|
62
|
-
elsif input.class!=String and input.class!=ChunkyPNG::Image
|
63
|
-
Pxlsrt::Helpers.error("Input is not a filename or ChunkyPNG::Image") if options[:verbose]
|
64
|
-
return
|
65
|
-
end
|
66
|
-
Pxlsrt::Helpers.verbose("Smart mode.") if options[:verbose]
|
67
|
-
png=Pxlsrt::Image.new(input)
|
68
|
-
if !options[:vertical] and !options[:diagonal]
|
69
|
-
Pxlsrt::Helpers.verbose("Retrieving rows") if options[:verbose]
|
70
|
-
lines = png.horizontalLines
|
71
|
-
elsif options[:vertical] and !options[:diagonal]
|
72
|
-
Pxlsrt::Helpers.verbose("Retrieving columns") if options[:verbose]
|
73
|
-
lines = png.verticalLines
|
74
|
-
elsif !options[:vertical] and options[:diagonal]
|
75
|
-
Pxlsrt::Helpers.verbose("Retrieving diagonals") if options[:verbose]
|
76
|
-
lines = png.diagonalLines
|
77
|
-
elsif options[:vertical] and options[:diagonal]
|
78
|
-
Pxlsrt::Helpers.verbose("Retrieving diagonals") if options[:verbose]
|
79
|
-
lines = png.rDiagonalLines
|
80
|
-
end
|
81
|
-
Pxlsrt::Helpers.verbose("Retrieving edges") if options[:verbose]
|
82
|
-
png.getSobels
|
83
|
-
if !options[:diagonal]
|
84
|
-
iterator = 0...(lines.length)
|
85
|
-
else
|
86
|
-
iterator = lines.keys
|
87
|
-
end
|
88
|
-
Pxlsrt::Helpers.verbose("Dividing and pixel sorting lines") if options[:verbose]
|
89
|
-
for k in iterator
|
90
|
-
line = lines[k]
|
91
|
-
divisions = []
|
92
|
-
division = []
|
93
|
-
if line.length > 1
|
94
|
-
for pixel in 0...(line.length)
|
95
|
-
if !options[:vertical] and !options[:diagonal]
|
96
|
-
xy = png.horizontalXY(k, pixel)
|
97
|
-
elsif options[:vertical] and !options[:diagonal]
|
98
|
-
xy = png.verticalXY(k, pixel)
|
99
|
-
elsif !options[:vertical] and options[:diagonal]
|
100
|
-
xy = png.diagonalXY(k, pixel)
|
101
|
-
elsif options[:vertical] and options[:diagonal]
|
102
|
-
xy = png.rDiagonalXY(k, pixel)
|
103
|
-
end
|
104
|
-
pxlSobel = png.getSobelAndColor(xy["x"], xy["y"])
|
105
|
-
if division.length == 0 or (options[:absolute] ? pxlSobel["sobel"] : pxlSobel["sobel"] - division.last["sobel"]) <= options[:threshold]
|
106
|
-
division.push(pxlSobel)
|
107
|
-
else
|
108
|
-
divisions.push(division)
|
109
|
-
division = [pxlSobel]
|
110
|
-
end
|
111
|
-
if pixel == line.length - 1
|
112
|
-
divisions.push(division)
|
113
|
-
division = []
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
newLine = []
|
118
|
-
for band in divisions
|
119
|
-
newLine.concat(
|
120
|
-
Pxlsrt::Helpers.handlePixelSort(
|
121
|
-
band.map { |sobelAndColor| sobelAndColor["color"] },
|
122
|
-
options
|
123
|
-
)
|
124
|
-
)
|
125
|
-
end
|
126
|
-
if !options[:diagonal]
|
127
|
-
png.replaceHorizontal(k, newLine) if !options[:vertical]
|
128
|
-
png.replaceVertical(k, newLine) if options[:vertical]
|
129
|
-
else
|
130
|
-
png.replaceDiagonal(k, newLine) if !options[:vertical]
|
131
|
-
png.replaceRDiagonal(k, newLine) if options[:vertical]
|
132
|
-
end
|
133
|
-
end
|
134
|
-
endTime=Time.now
|
135
|
-
timeElapsed=endTime-startTime
|
136
|
-
if timeElapsed < 60
|
137
|
-
Pxlsrt::Helpers.verbose("Took #{timeElapsed.round(4)} second#{ timeElapsed.round(4)!=1.0 ? "s" : "" }.") if options[:verbose]
|
138
|
-
else
|
139
|
-
minutes=(timeElapsed/60).floor
|
140
|
-
seconds=(timeElapsed % 60).round(4)
|
141
|
-
Pxlsrt::Helpers.verbose("Took #{minutes} minute#{ minutes!=1 ? "s" : "" } and #{seconds} second#{ seconds!=1.0 ? "s" : "" }.") if options[:verbose]
|
142
|
-
end
|
143
|
-
Pxlsrt::Helpers.verbose("Returning ChunkyPNG::Image...") if options[:verbose]
|
144
|
-
return png.returnModified
|
145
|
-
else
|
146
|
-
Pxlsrt::Helpers.error("Options specified do not follow the correct format.") if options[:verbose]
|
147
|
-
return
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
1
|
+
require 'rubygems'
|
2
|
+
require 'oily_png'
|
3
|
+
|
4
|
+
module Pxlsrt
|
5
|
+
##
|
6
|
+
# Smart sorting uses sorted-finding algorithms to create bands to sort,
|
7
|
+
# as opposed to brute sorting which doesn't care for the content or
|
8
|
+
# sorteds, just a specified range to create bands.
|
9
|
+
class Smart
|
10
|
+
##
|
11
|
+
# Uses Pxlsrt::Smart.smart to input and output from pne method.
|
12
|
+
def self.suite(inputFileName, outputFileName, o={})
|
13
|
+
kml=Pxlsrt::Smart.smart(inputFileName, o)
|
14
|
+
if Pxlsrt::Helpers.contented(kml)
|
15
|
+
kml.save(outputFileName)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
##
|
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.
|
20
|
+
def self.smart(input, o={})
|
21
|
+
startTime=Time.now
|
22
|
+
defOptions={
|
23
|
+
:reverse => false,
|
24
|
+
:vertical => false,
|
25
|
+
:diagonal => false,
|
26
|
+
:smooth => false,
|
27
|
+
:method => "sum-rgb",
|
28
|
+
:verbose => false,
|
29
|
+
:absolute => false,
|
30
|
+
:threshold => 20,
|
31
|
+
:trusted => false,
|
32
|
+
:middle => false
|
33
|
+
}
|
34
|
+
defRules={
|
35
|
+
:reverse => :anything,
|
36
|
+
:vertical => [false, true],
|
37
|
+
:diagonal => [false, true],
|
38
|
+
: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"],
|
40
|
+
:verbose => [false, true],
|
41
|
+
:absolute => [false, true],
|
42
|
+
:threshold => [{:class => [Float, Fixnum]}],
|
43
|
+
:trusted => [false, true],
|
44
|
+
:middle => :anything
|
45
|
+
}
|
46
|
+
options=defOptions.merge(o)
|
47
|
+
if o.length==0 or options[:trusted]==true or (options[:trusted]==false and o.length!=0 and Pxlsrt::Helpers.checkOptions(options, defRules)!=false)
|
48
|
+
Pxlsrt::Helpers.verbose("Options are all good.") if options[:verbose]
|
49
|
+
if input.class==String
|
50
|
+
Pxlsrt::Helpers.verbose("Getting image from file...") if options[:verbose]
|
51
|
+
if File.file?(input)
|
52
|
+
if Pxlsrt::Colors.isPNG?(input)
|
53
|
+
input=ChunkyPNG::Image.from_file(input)
|
54
|
+
else
|
55
|
+
Pxlsrt::Helpers.error("File #{input} is not a valid PNG.") if options[:verbose]
|
56
|
+
return
|
57
|
+
end
|
58
|
+
else
|
59
|
+
Pxlsrt::Helpers.error("File #{input} doesn't exist!") if options[:verbose]
|
60
|
+
return
|
61
|
+
end
|
62
|
+
elsif input.class!=String and input.class!=ChunkyPNG::Image
|
63
|
+
Pxlsrt::Helpers.error("Input is not a filename or ChunkyPNG::Image") if options[:verbose]
|
64
|
+
return
|
65
|
+
end
|
66
|
+
Pxlsrt::Helpers.verbose("Smart mode.") if options[:verbose]
|
67
|
+
png=Pxlsrt::Image.new(input)
|
68
|
+
if !options[:vertical] and !options[:diagonal]
|
69
|
+
Pxlsrt::Helpers.verbose("Retrieving rows") if options[:verbose]
|
70
|
+
lines = png.horizontalLines
|
71
|
+
elsif options[:vertical] and !options[:diagonal]
|
72
|
+
Pxlsrt::Helpers.verbose("Retrieving columns") if options[:verbose]
|
73
|
+
lines = png.verticalLines
|
74
|
+
elsif !options[:vertical] and options[:diagonal]
|
75
|
+
Pxlsrt::Helpers.verbose("Retrieving diagonals") if options[:verbose]
|
76
|
+
lines = png.diagonalLines
|
77
|
+
elsif options[:vertical] and options[:diagonal]
|
78
|
+
Pxlsrt::Helpers.verbose("Retrieving diagonals") if options[:verbose]
|
79
|
+
lines = png.rDiagonalLines
|
80
|
+
end
|
81
|
+
Pxlsrt::Helpers.verbose("Retrieving edges") if options[:verbose]
|
82
|
+
png.getSobels
|
83
|
+
if !options[:diagonal]
|
84
|
+
iterator = 0...(lines.length)
|
85
|
+
else
|
86
|
+
iterator = lines.keys
|
87
|
+
end
|
88
|
+
Pxlsrt::Helpers.verbose("Dividing and pixel sorting lines") if options[:verbose]
|
89
|
+
for k in iterator
|
90
|
+
line = lines[k]
|
91
|
+
divisions = []
|
92
|
+
division = []
|
93
|
+
if line.length > 1
|
94
|
+
for pixel in 0...(line.length)
|
95
|
+
if !options[:vertical] and !options[:diagonal]
|
96
|
+
xy = png.horizontalXY(k, pixel)
|
97
|
+
elsif options[:vertical] and !options[:diagonal]
|
98
|
+
xy = png.verticalXY(k, pixel)
|
99
|
+
elsif !options[:vertical] and options[:diagonal]
|
100
|
+
xy = png.diagonalXY(k, pixel)
|
101
|
+
elsif options[:vertical] and options[:diagonal]
|
102
|
+
xy = png.rDiagonalXY(k, pixel)
|
103
|
+
end
|
104
|
+
pxlSobel = png.getSobelAndColor(xy["x"], xy["y"])
|
105
|
+
if division.length == 0 or (options[:absolute] ? pxlSobel["sobel"] : pxlSobel["sobel"] - division.last["sobel"]) <= options[:threshold]
|
106
|
+
division.push(pxlSobel)
|
107
|
+
else
|
108
|
+
divisions.push(division)
|
109
|
+
division = [pxlSobel]
|
110
|
+
end
|
111
|
+
if pixel == line.length - 1
|
112
|
+
divisions.push(division)
|
113
|
+
division = []
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
newLine = []
|
118
|
+
for band in divisions
|
119
|
+
newLine.concat(
|
120
|
+
Pxlsrt::Helpers.handlePixelSort(
|
121
|
+
band.map { |sobelAndColor| sobelAndColor["color"] },
|
122
|
+
options
|
123
|
+
)
|
124
|
+
)
|
125
|
+
end
|
126
|
+
if !options[:diagonal]
|
127
|
+
png.replaceHorizontal(k, newLine) if !options[:vertical]
|
128
|
+
png.replaceVertical(k, newLine) if options[:vertical]
|
129
|
+
else
|
130
|
+
png.replaceDiagonal(k, newLine) if !options[:vertical]
|
131
|
+
png.replaceRDiagonal(k, newLine) if options[:vertical]
|
132
|
+
end
|
133
|
+
end
|
134
|
+
endTime=Time.now
|
135
|
+
timeElapsed=endTime-startTime
|
136
|
+
if timeElapsed < 60
|
137
|
+
Pxlsrt::Helpers.verbose("Took #{timeElapsed.round(4)} second#{ timeElapsed.round(4)!=1.0 ? "s" : "" }.") if options[:verbose]
|
138
|
+
else
|
139
|
+
minutes=(timeElapsed/60).floor
|
140
|
+
seconds=(timeElapsed % 60).round(4)
|
141
|
+
Pxlsrt::Helpers.verbose("Took #{minutes} minute#{ minutes!=1 ? "s" : "" } and #{seconds} second#{ seconds!=1.0 ? "s" : "" }.") if options[:verbose]
|
142
|
+
end
|
143
|
+
Pxlsrt::Helpers.verbose("Returning ChunkyPNG::Image...") if options[:verbose]
|
144
|
+
return png.returnModified
|
145
|
+
else
|
146
|
+
Pxlsrt::Helpers.error("Options specified do not follow the correct format.") if options[:verbose]
|
147
|
+
return
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
151
|
end
|
data/lib/pxlsrt/version.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
##
|
2
|
-
# The main module, your best friend.
|
3
|
-
module Pxlsrt
|
4
|
-
VERSION = "1.6.
|
5
|
-
end
|
1
|
+
##
|
2
|
+
# The main module, your best friend.
|
3
|
+
module Pxlsrt
|
4
|
+
VERSION = "1.6.2"
|
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.
|
4
|
+
version: 1.6.2
|
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-
|
11
|
+
date: 2014-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -42,16 +42,16 @@ dependencies:
|
|
42
42
|
name: oily_png
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 1.1.
|
47
|
+
version: 1.1.2
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 1.1.
|
54
|
+
version: 1.1.2
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: thor
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -103,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
103
|
version: '0'
|
104
104
|
requirements: []
|
105
105
|
rubyforge_project:
|
106
|
-
rubygems_version: 2.4.
|
106
|
+
rubygems_version: 2.4.5
|
107
107
|
signing_key:
|
108
108
|
specification_version: 4
|
109
109
|
summary: Pixel sort PNG files.
|