Skip to content

Commit

Permalink
Transparency support. More sorting methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
czycha committed Jul 2, 2014
1 parent 389c6a6 commit ff4099d
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 18 deletions.
54 changes: 51 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ gem install pxlsrt
Brute sorting uses a user defined range for bandwidths to sort.

```
pxlsrt brute INPUT OUTPUT [--min MIN] [--max MAX] [--vertical] [--smooth] [--reverse [no | reverse | either]] [--method [sum-rgb | red | green | blue | sum-hsb | hue | saturation | brightness | uniqueness | luma | random]] [--diagonal] [--verbose]
pxlsrt brute INPUT OUTPUT [--min MIN] [--max MAX] [--vertical] [--smooth] [--reverse [no | reverse | either]] [--method [sum-rgb | red | green | blue | sum-hsb | hue | saturation | brightness | uniqueness | luma | random | magenta | cyan | yellow | alpha]] [--diagonal] [--verbose]
```

### Options and parameters ###
Expand Down Expand Up @@ -69,7 +69,7 @@ Same as above example.
Smart sorting uses edges detected within the image (determined through [Sobel operators](http://en.wikipedia.org/wiki/Sobel_operator)) along with a user-defined threshold to define bandwidths to sort.

```
pxlsrt smart INPUT OUTPUT [--threshold THRESHOLD] [--absolute] [--edge EDGE] [--vertical] [--smooth] [--reverse [no | reverse | either]] [--method [sum-rgb | red | green | blue | sum-hsb | hue | saturation | brightness | uniqueness | luma | random]] [--diagonal]
pxlsrt smart INPUT OUTPUT [--threshold THRESHOLD] [--absolute] [--edge EDGE] [--vertical] [--smooth] [--reverse [no | reverse | either]] [--method [sum-rgb | red | green | blue | sum-hsb | hue | saturation | brightness | uniqueness | luma | random | magenta | cyan | yellow | alpha]] [--diagonal]
```

### Options and parameters ###
Expand Down Expand Up @@ -152,7 +152,7 @@ Sorts by the "distance" of the pixel from the average color of band (excluding t

```
avg(colors) = sum(colors) / (length of colors)
uniqueness(red, green, blue, reds, greens, blues) = sqrt((red - avg(reds))^2 + (green - avg(greens))^2 + (blue - avg(blues))^2)
uniqueness(red, green, blue, alpha, reds, greens, blues, alphas) = sqrt((red - avg(reds))^2 + (green - avg(greens))^2 + (blue - avg(blues))^2 + (alpha - avg(alphas))^2)
```

### luma ###
Expand All @@ -167,6 +167,54 @@ luma(red, green, blue) = red * 0.2126 + green * 0.7152 + blue * 0.0722

Randomizes the pixels.

### magenta ###

Sorts by a magenta value.

```
magenta(red, green, blue) = red + blue
```

### cyan ###

Sorts by a cyan value.

```
cyan(red, green, blue) = green + blue
```

### yellow ###

Sorts by a yellow value.

```
yellow(red, green, blue) = red + green
```

### alpha ###

Sorts by the opacity (the opposite of transparency) of a pixel. The "A" in RGBA.

```
alpha(red, green, blue, alpha) = alpha
```

### sum-rgba ###

Sorts by the sum of the red, green, blue, and alpha values.

```
sum-rgba(red, green, blue, alpha) = red + green + blue + alpha
```

### sum-hsba ###

Sorts by the sum of the hue, saturation, brightness, and alpha values.

```
sum-hsba(hue, saturation, brightness, alpha) = (hue * 100 / 360) + saturation + brightness + alpha * 100 / 255
```

## To use within Ruby files

```ruby
Expand Down
2 changes: 1 addition & 1 deletion bin/pxlsrt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class CLI < Thor
class_option :vertical, :type => :boolean, :default => false, :aliases => "-v"
class_option :diagonal, :type => :boolean, :default => false, :aliases => "-d"
class_option :smooth, :type => :boolean, :default => false, :aliases => "-s"
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"]
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"]
class_option :verbose, :type => :boolean, :default => false, :aliases => "-V"

option :min, :type => :numeric, :default => Float::INFINITY, :banner => "MINIMUM BANDWIDTH"
Expand Down
6 changes: 3 additions & 3 deletions lib/pxlsrt/brute.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def self.brute(input, o={})
:vertical => [false, true],
:diagonal => [false, true],
:smooth => [false, true],
:method => ["sum-rgb", "red", "green", "blue", "sum-hsb", "hue", "saturation", "brightness", "uniqueness", "luma", "random"],
:method => ["sum-rgb", "red", "green", "blue", "sum-hsb", "hue", "saturation", "brightness", "uniqueness", "luma", "random", "cyan", "magenta", "yellow", "alpha", "sum-rgba", "sum-hsba"],
:verbose => [false, true],
:min => [Float::INFINITY, {:class => [Fixnum]}],
:max => [Float::INFINITY, {:class => [Fixnum]}],
Expand Down Expand Up @@ -76,7 +76,7 @@ def self.brute(input, o={})
Pxlsrt::Helpers.verbose("Retrieving RGB values of pixels...") if options[:verbose]
kml=[]
for xy in 0..(w*h-1)
kml.push(Pxlsrt::Colors.getRGB(png[xy % w,(xy/w).floor]))
kml.push(Pxlsrt::Colors.getRGBA(png[xy % w,(xy/w).floor]))
end
if options[:vertical]==true
Pxlsrt::Helpers.verbose("Rotating image for vertical mode...") if options[:verbose]
Expand Down Expand Up @@ -134,7 +134,7 @@ def self.brute(input, o={})
end
Pxlsrt::Helpers.verbose("Giving pixels new RGB values...") if options[:verbose]
for xy in 0..(w*h-1)
sorted[xy % w, (xy/w).floor]=Pxlsrt::Colors.arrayToRGB(toImage[xy])
sorted[xy % w, (xy/w).floor]=Pxlsrt::Colors.arrayToRGBA(toImage[xy])
end
endTime=Time.now
timeElapsed=endTime-startTime
Expand Down
45 changes: 38 additions & 7 deletions lib/pxlsrt/colors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ module Pxlsrt
# Includes color and image operations.
class Colors
##
# Converts a ChunkyPNG pixel into an array of the reg, green, and blue values
def self.getRGB(pxl)
return [ChunkyPNG::Color.r(pxl), ChunkyPNG::Color.g(pxl), ChunkyPNG::Color.b(pxl)]
# Converts a ChunkyPNG pixel into an array of the red, green, blue, and alpha values
def self.getRGBA(pxl)
return [ChunkyPNG::Color.r(pxl), ChunkyPNG::Color.g(pxl), ChunkyPNG::Color.b(pxl), ChunkyPNG::Color.a(pxl)]
end
##
# 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.
Expand Down Expand Up @@ -119,12 +119,13 @@ def self.colorAverage(ca)
r=((ca.collect { |c| c[0] }).inject{ |sum, el| sum+el }).to_f / ca.size
g=((ca.collect { |c| c[1] }).inject{ |sum, el| sum+el }).to_f / ca.size
b=((ca.collect { |c| c[2] }).inject{ |sum, el| sum+el }).to_f / ca.size
return [r,g,b]
a=((ca.collect { |c| c[3] }).inject{ |sum, el| sum+el }).to_f / ca.size
return [r,g,b,a]
end
##
# Determines color distance from each other using the Pythagorean theorem.
def self.colorDistance(c1,c2)
return Math.sqrt((c1[0]-c2[0])**2+(c1[1]-c2[1])**2+(c1[2]-c2[2])**2)
return Math.sqrt((c1[0]-c2[0])**2+(c1[1]-c2[1])**2+(c1[2]-c2[2])**2+(c1[3]-c2[3])**2)
end
##
# Uses a combination of color averaging and color distance to find how "unique" a color is.
Expand All @@ -133,17 +134,43 @@ def self.colorUniqueness(c, ca)
end
##
# Sorts an array of colors based on a method.
# Available methods:
# * sum-rgb (default)
# * sum-rgba
# * red
# * yellow
# * green
# * cyan
# * blue
# * magenta
# * hue
# * saturation
# * brightness
# * sum-hsb
# * sum-hsba
# * uniqueness
# * luma
# * random
# * alpha
def self.pixelSort(list, how, reverse)
mhm=[]
case how.downcase
when "sum-rgb"
mhm= list.sort_by { |c| Pxlsrt::Colors.pxldex(c) }
when "sum-rgba"
mhm=list.sort_by { |c| Pxlsrt::Colors.pxldex(c)+c[3] }
when "red"
mhm= list.sort_by { |c| c[0] }
when "yellow"
mhm=list.sort_by { |c| c[0]+c[1] }
when "green"
mhm= list.sort_by { |c| c[1] }
when "cyan"
mhm=list.sort_by { |c| c[1]+c[2] }
when "blue"
mhm= list.sort_by { |c| c[2] }
when "magenta"
mhm=list.sort_by { |c| c[0]+c[2] }
when "hue"
mhm= list.sort_by { |c| Pxlsrt::Colors.rgb2hsb(c)[0] }
when "saturation"
Expand All @@ -152,13 +179,17 @@ def self.pixelSort(list, how, reverse)
mhm= list.sort_by { |c| Pxlsrt::Colors.rgb2hsb(c)[2] }
when "sum-hsb"
mhm= list.sort_by { |c| k=Pxlsrt::Colors.rgb2hsb(c); k[0]*100/360+k[1]+k[2] }
when "sum-hsb"
mhm= list.sort_by { |c| k=Pxlsrt::Colors.rgb2hsb(c); k[0]*100/360+k[1]+k[2]+k[3]*100/255 }
when "uniqueness"
avg=Pxlsrt::Colors.colorAverage(list)
mhm=list.sort_by { |c| Pxlsrt::Colors.colorUniqueness(c, [avg]) }
when "luma"
mhm=list.sort_by { |c| Pxlsrt::Colors.pxldex([c[0]*0.2126, c[1]*0.7152, c[2]*0.0722]) }
when "random"
mhm=list.shuffle
when "alpha"
mhm=list.sort_by{ |c| c[3] }
else
mhm= list.sort_by { |c| Pxlsrt::Colors.pxldex(c) }
end
Expand Down Expand Up @@ -210,8 +241,8 @@ def self.fromDiagonals(obj, width)
end
##
# Turns an RGB-like array into ChunkyPNG's color
def self.arrayToRGB(a)
return ChunkyPNG::Color.rgb(a[0], a[1], a[2])
def self.arrayToRGBA(a)
return ChunkyPNG::Color.rgba(a[0], a[1], a[2], a[3])
end
##
# Used in determining Sobel values.
Expand Down
6 changes: 3 additions & 3 deletions lib/pxlsrt/smart.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def self.smart(input, o={})
:vertical => [false, true],
:diagonal => [false, true],
:smooth => [false, true],
:method => ["sum-rgb", "red", "green", "blue", "sum-hsb", "hue", "saturation", "brightness", "uniqueness", "luma", "random"],
:method => ["sum-rgb", "red", "green", "blue", "sum-hsb", "hue", "saturation", "brightness", "uniqueness", "luma", "random", "cyan", "magenta", "yellow", "alpha", "sum-rgba", "sum-hsba"],
:verbose => [false, true],
:absolute => [false, true],
:threshold => [{:class => [Float, Fixnum]}],
Expand Down Expand Up @@ -90,7 +90,7 @@ def self.smart(input, o={})
else
val = 2000000000
end
k.push({ "sobel" => val, "pixel" => [x, y], "color" => Pxlsrt::Colors.getRGB(img[x, y]) })
k.push({ "sobel" => val, "pixel" => [x, y], "color" => Pxlsrt::Colors.getRGBA(img[x, y]) })
end
if options[:vertical]==true
Pxlsrt::Helpers.verbose("Rotating image for vertical mode...") if options[:verbose]
Expand Down Expand Up @@ -213,7 +213,7 @@ def self.smart(input, o={})
end
Pxlsrt::Helpers.verbose("Giving pixels new RGB values...") if options[:verbose]
for px in 0..(w*h-1)
edge[px % w, (px/w).floor]=Pxlsrt::Colors.arrayToRGB(image[px])
edge[px % w, (px/w).floor]=Pxlsrt::Colors.arrayToRGBA(image[px])
end
endTime=Time.now
timeElapsed=endTime-startTime
Expand Down
2 changes: 1 addition & 1 deletion lib/pxlsrt/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
##
# The main module, your best friend.
module Pxlsrt
VERSION = "1.2.0"
VERSION = "1.3.0"
end

0 comments on commit ff4099d

Please sign in to comment.