pxlsrt 1.0.0 → 1.0.1
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 +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.
|