flambient 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7d0a17dbd56e0fb11949760f71e4bb83b54a2ba1
4
+ data.tar.gz: 3bf2040f2239df137f001fc182100717441ffdad
5
+ SHA512:
6
+ metadata.gz: 93b5f7c375ccf0fe3b03ab67321ecd7badb92937a037a9a39059e61c0bf6f4b32da0ef184df57498dc05a1f8c64756cafe97bfe42e1e7912cb8e4e815541bc82
7
+ data.tar.gz: 38a08294110fd9f7b3eb5f1f818bb56e59b200e3e2bedb8c3baa61b0141047ac59a58e5841d83507a0064306ff59175ef40884ef8022399fae159784832b5e72
@@ -0,0 +1,3 @@
1
+ *.png
2
+ Gemfile.lock
3
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'flambient'
4
+
5
+ if ARGV[0].nil?
6
+ raise "No input path supplied"
7
+ end
8
+
9
+ if ARGV[1].nil?
10
+ raise "No output path supplied"
11
+ end
12
+
13
+ image = ChunkyPNG::Image.from_file(ARGV[0])
14
+ processor = Flambient::Processor.new(image, 64)
15
+
16
+ new_image = processor.process
17
+ new_image.save(ARGV[1])
@@ -0,0 +1,20 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "flambient"
5
+ s.version = "0.0.1"
6
+ s.authors = ["Tom Taylor"]
7
+ s.email = ["tom@tomtaylor.co.uk"]
8
+ s.homepage = "https://github.com/tomtaylor/flambient"
9
+ s.summary = "Triangular pixel effects on PNGs"
10
+
11
+ s.files = `git ls-files`.split($\)
12
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
13
+ s.require_paths = ["lib"]
14
+ s.executables = ["flambient"]
15
+
16
+ s.add_dependency "chunky_png", '~> 1.2.9'
17
+ s.add_dependency "oily_png", '~> 1.1.0'
18
+
19
+ s.add_development_dependency "rake"
20
+ end
@@ -0,0 +1 @@
1
+ require 'flambient/processor'
@@ -0,0 +1,128 @@
1
+ require 'chunky_png'
2
+ require 'oily_png'
3
+
4
+ module Flambient
5
+ class Processor
6
+
7
+ attr_reader :tile_size, :image
8
+
9
+ def initialize(image, tile_size = 32)
10
+ @image = image
11
+ @tile_size = tile_size
12
+ end
13
+
14
+ def process
15
+ # Round the size of the image down to the nearest tile
16
+ width = (image.width / tile_size) * tile_size
17
+ height = (image.height / tile_size) * tile_size
18
+ new_image = ChunkyPNG::Canvas.new(width, height, ChunkyPNG::Color::TRANSPARENT)
19
+
20
+ (0...width).step(tile_size) do |x|
21
+ (0...height).step(tile_size) do |y|
22
+ process_tile(new_image, x, y)
23
+ end
24
+ end
25
+
26
+ new_image
27
+ end
28
+
29
+ private
30
+
31
+ def process_tile(new_image, x, y)
32
+ top, left, bottom, right = quad_colours(x, y)
33
+
34
+ p_top_left = [x, y]
35
+ p_top_right = [x + tile_size, y]
36
+ p_bottom_left = [x, y + tile_size]
37
+ p_bottom_right = [x + tile_size, y + tile_size]
38
+
39
+ # Change the angle of the triangle depending on the closest matching
40
+ # colour.
41
+ if color_distance(top, left) > color_distance(top, right)
42
+ c1 = average_color([top, left])
43
+ c2 = average_color([bottom, right])
44
+
45
+ new_image.polygon([p_top_left, p_top_right, p_bottom_left], c1, c1)
46
+ new_image.polygon([p_top_right, p_bottom_left, p_bottom_right], c2, c2)
47
+ else
48
+ c1 = average_color([top, right])
49
+ c2 = average_color([bottom, left])
50
+
51
+ new_image.polygon([p_top_left, p_top_right, p_bottom_right], c1, c1)
52
+ new_image.polygon([p_top_left, p_bottom_left, p_bottom_right], c2, c2)
53
+ end
54
+ end
55
+
56
+ # Returns the average colours for different portions of the tile.
57
+ def quad_colours(tile_x, tile_y)
58
+ [:top, :left, :bottom, :right].map do |side|
59
+ average_color(triangle_pixels(tile_x, tile_y, side))
60
+ end
61
+ end
62
+
63
+ # This is meant to return the pixels for a triangle in a tile, but instead
64
+ # does a simple rectangle, because I couldn't be bothered to think about
65
+ # the maths.
66
+ def triangle_pixels(tile_x, tile_y, side)
67
+ quad_size = tile_size / 2
68
+
69
+ case side
70
+ when :top
71
+ p1 = [tile_x, tile_y]
72
+ p2 = [tile_x + tile_size, tile_y + quad_size]
73
+ when :left
74
+ p1 = [tile_x, tile_y]
75
+ p2 = [tile_x + quad_size, tile_y + tile_size]
76
+ when :bottom
77
+ p1 = [tile_x, tile_y + quad_size]
78
+ p2 = [tile_x + tile_size, tile_y + tile_size]
79
+ when :right
80
+ p1 = [tile_x + quad_size, tile_y]
81
+ p2 = [tile_x + tile_size, tile_y + tile_size]
82
+ end
83
+
84
+ p1 = ChunkyPNG.Point(p1)
85
+ p2 = ChunkyPNG.Point(p2)
86
+
87
+ [].tap do |pixels|
88
+ (p1.x...p2.x).each do |x|
89
+ (p1.y...p2.y).each do |y|
90
+ pixels << image.get_pixel(x, y)
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ # Calculates the average colour of an array of pixels
97
+ def average_color(pixels)
98
+ r_avg = 0; g_avg = 0; b_avg = 0
99
+ count = pixels.length
100
+
101
+ pixels.each do |pixel|
102
+ r, g, b = ChunkyPNG::Color.to_truecolor_bytes(pixel)
103
+ r_avg += r
104
+ g_avg += g
105
+ b_avg += b
106
+ end
107
+
108
+ r_avg = r_avg / count
109
+ g_avg = g_avg / count
110
+ b_avg = b_avg / count
111
+
112
+ ChunkyPNG::Color.rgb(r_avg, g_avg, b_avg)
113
+ end
114
+
115
+ # See http://en.wikipedia.org/wiki/Hue#Computing_hue_from_RGB
116
+ def color_hue(pixel)
117
+ r, g, b = ChunkyPNG::Color.to_truecolor_bytes(pixel)
118
+ return 0 if r == b and b == g
119
+ ((180 / Math::PI * Math.atan2((2 * r) - g - b, Math.sqrt(3) * (g - b))) - 90) % 360
120
+ end
121
+
122
+ # The modular distance, as the hue is circular
123
+ def color_distance(pixel, poxel)
124
+ hue_pixel, hue_poxel = color_hue(pixel), color_hue(poxel)
125
+ [(hue_pixel - hue_poxel) % 360, (hue_poxel - hue_pixel) % 360].min
126
+ end
127
+ end
128
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flambient
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tom Taylor
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: chunky_png
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.2.9
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.2.9
27
+ - !ruby/object:Gem::Dependency
28
+ name: oily_png
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.1.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email:
57
+ - tom@tomtaylor.co.uk
58
+ executables:
59
+ - flambient
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - Gemfile
65
+ - Rakefile
66
+ - bin/flambient
67
+ - flambient.gemspec
68
+ - lib/flambient.rb
69
+ - lib/flambient/processor.rb
70
+ homepage: https://github.com/tomtaylor/flambient
71
+ licenses: []
72
+ metadata: {}
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubyforge_project:
89
+ rubygems_version: 2.2.0
90
+ signing_key:
91
+ specification_version: 4
92
+ summary: Triangular pixel effects on PNGs
93
+ test_files: []