pxlsrt 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/pxlsrt +20 -3
- data/lib/pxlsrt/brute.rb +18 -1
- data/lib/pxlsrt/colors.rb +39 -0
- data/lib/pxlsrt/helpers.rb +14 -0
- data/lib/pxlsrt/smart.rb +19 -5
- data/lib/pxlsrt/version.rb +3 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 09e1b556ac3be235df077e4ad203c8bf39074ba2
|
4
|
+
data.tar.gz: 51cc893e04a3e59da9a58e942b850c37aed51b6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd2733444b7330897b0ae12211e413c723b7c17558aa5c5bccad62330a492d8fd907d9cce52e61240789e967a89d0b740e6b6d96561c0836829d3b8a727b1607
|
7
|
+
data.tar.gz: 585c68c42645e7dfda6e0ea51d83fb1f3ca73f1f34c4bb0822124b22c5cde7d2ace4f5a828c1ea6c15302664f04a3ce6cd4bbed9a923a7f7e72b1bbeb1a0d726
|
data/bin/pxlsrt
CHANGED
@@ -4,18 +4,30 @@ require 'rubygems'
|
|
4
4
|
require 'pxlsrt'
|
5
5
|
require 'thor'
|
6
6
|
|
7
|
-
|
7
|
+
##
|
8
|
+
# The command line. Created using Thor. Universal options:
|
9
|
+
# * reverse - Reverses the bands or randomly reverses or doesn't reverse.
|
10
|
+
# * vertical - Sorts vertically.
|
11
|
+
# * diagonal - Sorts diagonally. Use with vertical to change the diagonals' orientation.
|
12
|
+
# * smooth - "Smoothes" sorted values by grouping identical pixels together.
|
13
|
+
# * method - What method to use to sort pixels.
|
14
|
+
# * verbose - Have pxlsrt tell you what it's working on.
|
15
|
+
# * help - More in depth commands.
|
16
|
+
class CLI < Thor
|
8
17
|
class_option :reverse, :type => :string, :default => "no", :banner => "[no | reverse | either]", :aliases => "-r", :enum => ["no", "reverse", "either"]
|
9
18
|
class_option :vertical, :type => :boolean, :default => false, :aliases => "-v"
|
10
19
|
class_option :diagonal, :type => :boolean, :default => false, :aliases => "-d"
|
11
20
|
class_option :smooth, :type => :boolean, :default => false, :aliases => "-s"
|
12
21
|
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
22
|
class_option :verbose, :type => :boolean, :default => false, :aliases => "-V"
|
15
23
|
|
16
24
|
option :min, :type => :numeric, :default => Float::INFINITY, :banner => "MINIMUM BANDWIDTH"
|
17
25
|
option :max, :type => :numeric, :default => Float::INFINITY, :banner => "MAXIMUM BANDWIDTH"
|
18
26
|
desc "brute INPUT OUTPUT [options]", "Brute pixel sorting"
|
27
|
+
##
|
28
|
+
# Specific options:
|
29
|
+
# * min - Minimum bandwidth.
|
30
|
+
# * max - Maximum bandwidth.
|
19
31
|
def brute(input, output)
|
20
32
|
k={}
|
21
33
|
for o in options.keys
|
@@ -28,6 +40,11 @@ class PXLSRT < Thor
|
|
28
40
|
option :threshold, :type => :numeric, :default => 20, :aliases => "-t"
|
29
41
|
option :edge, :type => :numeric, :default => 2, :aliases => "-e", :banner => "EDGE BUFFERING"
|
30
42
|
desc "smart INPUT OUTPUT [options]", "Smart pixel sorting"
|
43
|
+
##
|
44
|
+
# Specific options:
|
45
|
+
# * threshold - Number used in edge finding. Specifics explained under "absolute".
|
46
|
+
# * absolute - Make edge finding absolute over relative. For example, define a range as a collection of values under the threshold. Relative edge finding is when the contrast of the next pixel is larger than the threshold.
|
47
|
+
# * edge - Buffers edge.
|
31
48
|
def smart(input, output)
|
32
49
|
k={}
|
33
50
|
for o in options.keys
|
@@ -37,4 +54,4 @@ class PXLSRT < Thor
|
|
37
54
|
end
|
38
55
|
end
|
39
56
|
|
40
|
-
|
57
|
+
CLI.start(ARGV)
|
data/lib/pxlsrt/brute.rb
CHANGED
@@ -2,13 +2,20 @@ require 'rubygems'
|
|
2
2
|
require 'oily_png'
|
3
3
|
|
4
4
|
module Pxlsrt
|
5
|
+
##
|
6
|
+
# Brute sorting creates bands for sorting using a range to determine the bandwidths,
|
7
|
+
# as opposed to smart sorting which uses edge-finding to create bands.
|
5
8
|
class Brute
|
9
|
+
##
|
10
|
+
# Uses Pxlsrt::Brute.brute to input and output from one method.
|
6
11
|
def self.suite(inputFileName, outputFileName, trusted, o={})
|
7
12
|
kml=Pxlsrt::Brute.brute(inputFileName, trusted, o)
|
8
13
|
if Pxlsrt::Helpers.contented(kml)
|
9
14
|
kml.save(outputFileName)
|
10
15
|
end
|
11
16
|
end
|
17
|
+
##
|
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.
|
12
19
|
def self.brute(input, trusted, o={})
|
13
20
|
startTime=Time.now
|
14
21
|
defOptions={
|
@@ -36,7 +43,17 @@ module Pxlsrt
|
|
36
43
|
Pxlsrt::Helpers.verbose("Options are all good.") if options[:verbose]
|
37
44
|
if input.class==String
|
38
45
|
Pxlsrt::Helpers.verbose("Getting image from file...") if options[:verbose]
|
39
|
-
|
46
|
+
if File.file?(input)
|
47
|
+
if Pxlsrt::Colors.isPNG?(input)
|
48
|
+
input=ChunkyPNG::Image.from_file(input)
|
49
|
+
else
|
50
|
+
Pxlsrt::Helpers.error("File #{input} is not a valid PNG.") if options[:verbose]
|
51
|
+
return
|
52
|
+
end
|
53
|
+
else
|
54
|
+
Pxlsrt::Helpers.error("File #{input} doesn't exist!") if options[:verbose]
|
55
|
+
return
|
56
|
+
end
|
40
57
|
elsif input.class!=String and input.class!=ChunkyPNG::Image
|
41
58
|
Pxlsrt::Helpers.error("Input is not a filename or ChunkyPNG::Image") if options[:verbose]
|
42
59
|
return
|
data/lib/pxlsrt/colors.rb
CHANGED
@@ -1,10 +1,23 @@
|
|
1
1
|
require "oily_png"
|
2
2
|
|
3
3
|
module Pxlsrt
|
4
|
+
##
|
5
|
+
# Includes color and image operations.
|
4
6
|
class Colors
|
7
|
+
##
|
8
|
+
# Converts a ChunkyPNG pixel into an array of the reg, green, and blue values
|
5
9
|
def self.getRGB(pxl)
|
6
10
|
return [ChunkyPNG::Color.r(pxl), ChunkyPNG::Color.g(pxl), ChunkyPNG::Color.b(pxl)]
|
7
11
|
end
|
12
|
+
##
|
13
|
+
# Check if file is a PNG image. ChunkyPNG only works with PNG images. Eventually, I might use conversion tools to add support, but not right now.
|
14
|
+
def self.isPNG?(path)
|
15
|
+
return File.read(path).bytes==[137, 80, 78, 71, 10]
|
16
|
+
end
|
17
|
+
##
|
18
|
+
# ChunkyPNG's rotation was a little slow and doubled runtime.
|
19
|
+
# This "rotates" an array, based on the width and height.
|
20
|
+
# It uses math and it's really cool, trust me.
|
8
21
|
def self.rotateImage(what, width, height, a)
|
9
22
|
nu=[]
|
10
23
|
case a
|
@@ -23,9 +36,15 @@ module Pxlsrt
|
|
23
36
|
end
|
24
37
|
return nu
|
25
38
|
end
|
39
|
+
##
|
40
|
+
# Gets "rows" of an array based on a width
|
26
41
|
def self.imageRGBLines(image, width)
|
27
42
|
return image.each_slice(width).to_a
|
28
43
|
end
|
44
|
+
##
|
45
|
+
# Outputs random slices of an array.
|
46
|
+
# Because of the requirements of pxlsrt, it doesn't actually slice the array, bute returns a range-like array. Example:
|
47
|
+
# [[0, 5], [6, 7], [8, 10]]
|
29
48
|
def self.randomSlices(arr, minLength, maxLength)
|
30
49
|
len=arr.length-1
|
31
50
|
if len!=0
|
@@ -54,9 +73,13 @@ module Pxlsrt
|
|
54
73
|
end
|
55
74
|
return nu
|
56
75
|
end
|
76
|
+
##
|
77
|
+
# This is really lame. Adds first three values of an array together.
|
57
78
|
def self.pxldex(pxl)
|
58
79
|
return pxl[0]+pxl[1]+pxl[2]
|
59
80
|
end
|
81
|
+
##
|
82
|
+
# Converts an RGB-like array ([red, green, blue]) into an HSB-like array ([hue, saturation, brightness]).
|
60
83
|
def self.rgb2hsb(rgb)
|
61
84
|
r = rgb[0] / 255.0
|
62
85
|
g = rgb[1] / 255.0
|
@@ -87,6 +110,8 @@ module Pxlsrt
|
|
87
110
|
end
|
88
111
|
return [h,s,v]
|
89
112
|
end
|
113
|
+
##
|
114
|
+
# Averages an array of RGB-like arrays.
|
90
115
|
def self.colorAverage(ca)
|
91
116
|
if ca.length==1
|
92
117
|
return ca.first
|
@@ -96,12 +121,18 @@ module Pxlsrt
|
|
96
121
|
b=((ca.collect { |c| c[2] }).inject{ |sum, el| sum+el }).to_f / ca.size
|
97
122
|
return [r,g,b]
|
98
123
|
end
|
124
|
+
##
|
125
|
+
# Determines color distance from each other using the Pythagorean theorem.
|
99
126
|
def self.colorDistance(c1,c2)
|
100
127
|
return Math.sqrt((c1[0]-c2[0])**2+(c1[1]-c2[1])**2+(c1[2]-c2[2])**2)
|
101
128
|
end
|
129
|
+
##
|
130
|
+
# Uses a combination of color averaging and color distance to find how "unique" a color is.
|
102
131
|
def self.colorUniqueness(c, ca)
|
103
132
|
return Pxlsrt::Colors.colorDistance(c, Pxlsrt::Colors.colorAverage(ca))
|
104
133
|
end
|
134
|
+
##
|
135
|
+
# Sorts an array of colors based on a method.
|
105
136
|
def self.pixelSort(list, how, reverse)
|
106
137
|
mhm=[]
|
107
138
|
case how.downcase
|
@@ -139,6 +170,8 @@ module Pxlsrt
|
|
139
170
|
return rand(0..1)==0 ? mhm : mhm.reverse
|
140
171
|
end
|
141
172
|
end
|
173
|
+
##
|
174
|
+
# Uses math to turn an array into an array of diagonals.
|
142
175
|
def self.getDiagonals(array, width, height)
|
143
176
|
dias={}
|
144
177
|
for x in (1-height)..(width-1)
|
@@ -152,6 +185,8 @@ module Pxlsrt
|
|
152
185
|
end
|
153
186
|
return dias
|
154
187
|
end
|
188
|
+
##
|
189
|
+
# Uses math to turn an array of diagonals into a linear array.
|
155
190
|
def self.fromDiagonals(obj, width)
|
156
191
|
ell=[]
|
157
192
|
for k in obj.keys
|
@@ -173,9 +208,13 @@ module Pxlsrt
|
|
173
208
|
end
|
174
209
|
return ell
|
175
210
|
end
|
211
|
+
##
|
212
|
+
# Turns an RGB-like array into ChunkyPNG's color
|
176
213
|
def self.arrayToRGB(a)
|
177
214
|
return ChunkyPNG::Color.rgb(a[0], a[1], a[2])
|
178
215
|
end
|
216
|
+
##
|
217
|
+
# Used in determining Sobel values.
|
179
218
|
def self.sobelate(i, x,y)
|
180
219
|
return ChunkyPNG::Color.to_grayscale_bytes(i[x,y]).first
|
181
220
|
end
|
data/lib/pxlsrt/helpers.rb
CHANGED
@@ -1,14 +1,24 @@
|
|
1
1
|
module Pxlsrt
|
2
|
+
##
|
3
|
+
# Methods not having to do with image or color manipulation.
|
2
4
|
class Helpers
|
5
|
+
##
|
6
|
+
# Determines if a value has content.
|
3
7
|
def self.contented(c)
|
4
8
|
return (c.class!=NilClass and ((defined? c)!="nil") and ((/(\S)/.match("#{c}"))!=nil))
|
5
9
|
end
|
10
|
+
##
|
11
|
+
# Used to output a red string to the terminal.
|
6
12
|
def self.red(what)
|
7
13
|
return "\e[31m#{what}\e[0m"
|
8
14
|
end
|
15
|
+
##
|
16
|
+
# Used to output a cyan string to the terminal.
|
9
17
|
def self.cyan(what)
|
10
18
|
return "\e[36m#{what}\e[0m"
|
11
19
|
end
|
20
|
+
##
|
21
|
+
# Checks if supplied options follow the rules.
|
12
22
|
def self.checkOptions(options, rules)
|
13
23
|
match=true
|
14
24
|
for o in options.keys
|
@@ -39,9 +49,13 @@ module Pxlsrt
|
|
39
49
|
end
|
40
50
|
return match
|
41
51
|
end
|
52
|
+
##
|
53
|
+
# Prints an error message.
|
42
54
|
def self.error(what)
|
43
55
|
puts "#{Pxlsrt::Helpers.red("pxlsrt")} #{what}"
|
44
56
|
end
|
57
|
+
##
|
58
|
+
# Prints something.
|
45
59
|
def self.verbose(what)
|
46
60
|
puts "#{Pxlsrt::Helpers.cyan("pxlsrt")} #{what}"
|
47
61
|
end
|
data/lib/pxlsrt/smart.rb
CHANGED
@@ -1,18 +1,22 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'oily_png'
|
3
|
-
require 'json'
|
4
|
-
require 'pathname'
|
5
|
-
require 'fileutils'
|
6
|
-
require 'base64'
|
7
3
|
|
8
4
|
module Pxlsrt
|
5
|
+
##
|
6
|
+
# Smart sorting uses edge-finding algorithms to create bands to sort,
|
7
|
+
# as opposed to brute sorting which doesn't care for the content or
|
8
|
+
# edges, just a specified range to create bands.
|
9
9
|
class Smart
|
10
|
+
##
|
11
|
+
# Uses Pxlsrt::Smart.smart to input and output from pne method.
|
10
12
|
def self.suite(inputFileName, outputFileName, trusted, o={})
|
11
13
|
kml=Pxlsrt::Smart.smart(inputFileName, trusted, o)
|
12
14
|
if Pxlsrt::Helpers.contented(kml)
|
13
15
|
kml.save(outputFileName)
|
14
16
|
end
|
15
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.
|
16
20
|
def self.smart(input, trusted, o={})
|
17
21
|
startTime=Time.now
|
18
22
|
defOptions={
|
@@ -42,7 +46,17 @@ module Pxlsrt
|
|
42
46
|
Pxlsrt::Helpers.verbose("Options are all good.") if options[:verbose]
|
43
47
|
if input.class==String
|
44
48
|
Pxlsrt::Helpers.verbose("Getting image from file...") if options[:verbose]
|
45
|
-
|
49
|
+
if File.file?(input)
|
50
|
+
if Pxlsrt::Colors.isPNG?(input)
|
51
|
+
input=ChunkyPNG::Image.from_file(input)
|
52
|
+
else
|
53
|
+
Pxlsrt::Helpers.error("File #{input} is not a valid PNG.") if options[:verbose]
|
54
|
+
return
|
55
|
+
end
|
56
|
+
else
|
57
|
+
Pxlsrt::Helpers.error("File #{input} doesn't exist!") if options[:verbose]
|
58
|
+
return
|
59
|
+
end
|
46
60
|
elsif input.class!=String and input.class!=ChunkyPNG::Image
|
47
61
|
Pxlsrt::Helpers.error("Input is not a filename or ChunkyPNG::Image") if options[:verbose]
|
48
62
|
return
|
data/lib/pxlsrt/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pxlsrt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- EVA-01
|
@@ -101,7 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
101
|
version: '0'
|
102
102
|
requirements: []
|
103
103
|
rubyforge_project:
|
104
|
-
rubygems_version: 2.
|
104
|
+
rubygems_version: 2.3.0
|
105
105
|
signing_key:
|
106
106
|
specification_version: 4
|
107
107
|
summary: Pixel sort PNG files.
|