Skip to content

Instantly share code, notes, and snippets.

@dunedain289
Created September 15, 2011 06:02
Show Gist options
  • Save dunedain289/1218649 to your computer and use it in GitHub Desktop.
Save dunedain289/1218649 to your computer and use it in GitHub Desktop.
Codebrawl selective color

Codebrawl Selective Color entry

All the code so far is in select.rb. I set up a few helper functions at the top of the file to get color components in floating point for the hue calculations. The hue calculation itself is ripped straight from Wikipedia HSL and HSV, implemented in pure Ruby. I also took advantage of ChunkyPNG's already-implemented grayscale conversion (after rolling my own first, then realizing my mistake).

The commands used to generate all the versions are:

./select.rb 20 65 input.png yellow.png
./select.rb 0 18 input.png red.png
./select.rb 65 90 input.png green.png
./select.rb 185 215 input.png blue.png
./select.rb 235 245 input.png violet.png

where the command line syntax is:

select.rb <lower hue limit, 0-360.0> <upper hue limit, 0-360.0> <input file> <output file>

Since I'm not a GUI expert, I haven't wrapped this up with its own color picker - I used the ColorSync Utility built-in to my MacBook to estimate Hue value ranges for the different crayons.

# A sample Gemfile
source "http://rubygems.org"
gem "chunky_png"
# gem "rails"
GEM
remote: http://rubygems.org/
specs:
chunky_png (1.2.4)
PLATFORMS
ruby
DEPENDENCIES
chunky_png
#!/usr/bin/env ruby
require 'bundler'
require 'chunky_png'
def r_f(color)
ChunkyPNG::Color.r(color) / 255.0
end
def g_f(color)
ChunkyPNG::Color.g(color) / 255.0
end
def b_f(color)
ChunkyPNG::Color.b(color) / 255.0
end
def hue(color)
return 0.0 if ChunkyPNG::Color.grayscale? color
alpha = 0.5 * (2*r_f(color) - g_f(color) - b_f(color))
beta = Math.sqrt(3)/2.0 * (g_f(color) - b_f(color))
rad = Math.atan2(beta, alpha)
rad = 2*Math::PI + rad if rad < 0
rad / (2*Math::PI) * 360.0
end
unless ARGV.length == 4
puts <<HELP
Usage:
select.rb <lower hue limit, 0-360.0> <upper hue limit, 0-360.0> <input file> <output file>
HELP
exit(0)
end
lower_limit = Float(ARGV[0])
upper_limit = Float(ARGV[1])
input_file = ARGV[2]
output_file = ARGV[3]
puts "reading from #{input_file}"
puts "writing to #{output_file}"
input = ChunkyPNG::Image.from_file(input_file)
puts "keeping pixels with #{lower_limit} <= hue <= #{upper_limit}"
(0...input.height).each do |y|
puts "row #{y}"
(0...input.width).each do |x|
h = hue input[x,y]
unless lower_limit <= h && h <= upper_limit
input[x,y] = ChunkyPNG::Color.grayscale ChunkyPNG::Color.grayscale_teint input[x,y]
end
end
end
input.save(output_file)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment