diff --git a/README.md b/README.md index 02f14fa..146ed95 100644 --- a/README.md +++ b/README.md @@ -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 ### @@ -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 ### @@ -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 ### @@ -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 diff --git a/bin/pxlsrt b/bin/pxlsrt index 6825e7e..200ea1f 100644 --- a/bin/pxlsrt +++ b/bin/pxlsrt @@ -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" diff --git a/lib/pxlsrt/brute.rb b/lib/pxlsrt/brute.rb index 6999752..34d0cb5 100644 --- a/lib/pxlsrt/brute.rb +++ b/lib/pxlsrt/brute.rb @@ -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]}], @@ -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] @@ -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 diff --git a/lib/pxlsrt/colors.rb b/lib/pxlsrt/colors.rb index 1fada01..6086690 100644 --- a/lib/pxlsrt/colors.rb +++ b/lib/pxlsrt/colors.rb @@ -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. @@ -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. @@ -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" @@ -152,6 +179,8 @@ 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]) } @@ -159,6 +188,8 @@ def self.pixelSort(list, how, reverse) 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 @@ -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. diff --git a/lib/pxlsrt/smart.rb b/lib/pxlsrt/smart.rb index e45302a..505b099 100644 --- a/lib/pxlsrt/smart.rb +++ b/lib/pxlsrt/smart.rb @@ -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]}], @@ -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] @@ -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 diff --git a/lib/pxlsrt/version.rb b/lib/pxlsrt/version.rb index 2e4b147..c555de2 100644 --- a/lib/pxlsrt/version.rb +++ b/lib/pxlsrt/version.rb @@ -1,5 +1,5 @@ ## # The main module, your best friend. module Pxlsrt - VERSION = "1.2.0" + VERSION = "1.3.0" end