quilt 0.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.
data/ChangeLog ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 / 2008-04-12
2
+
3
+ * initial release
4
+
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 swdyh
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,59 @@
1
+
2
+ = quilt
3
+
4
+
5
+ == Description
6
+ a library for generating identicon.
7
+
8
+
9
+ Identicon: http://en.wikipedia.org/wiki/Identicon
10
+
11
+ == Installation
12
+ Required RMagick or ruby-gd.
13
+
14
+ === Archive Installation
15
+
16
+ rake install
17
+
18
+ === Gem Installation
19
+
20
+ gem install quilt
21
+
22
+
23
+ == Features/Problems
24
+ * Output file type is PNG only.
25
+
26
+ == Synopsis
27
+
28
+ # input: any string
29
+ # output: 15 * 15 png (default)
30
+ identicon = Quilt::Identicon.new 'sample'
31
+ identicon.write 'sample15_15.png'
32
+
33
+ # input: identicon code(32 bit integer)
34
+ # output: 15 * 15 png (default)
35
+ identicon = Quilt::Identicon.new 1, :type => :code
36
+ identicon.write 'sample15_15_code.png'
37
+
38
+ # input: ip address
39
+ identicon = Quilt::Identicon.new '100.100.100.100', :type => :ip
40
+ identicon.write 'sample15_15_ip.png'
41
+
42
+ # output: 150 * 150 png
43
+ identicon = Quilt::Identicon.new 'sample', :scale => 10
44
+ identicon.write 'sample150_150.png'
45
+
46
+ # output: blob
47
+ identicon = Quilt::Identicon.new 'sample'
48
+ print identicon.to_blob
49
+
50
+ # change image library to Rmagick to GD
51
+ Quilt::Identicon.image_lib = Quilt::ImageGD
52
+ identicon = Quilt::Identicon.new 'sample'
53
+ identicon.write 'sample15_15_gd.png'
54
+
55
+ == Copyright
56
+
57
+ Author:: swdyh <youhei@gmail.com>
58
+ Copyright:: Copyright (c) 2008 swdyh
59
+ License:: The MIT License
data/Rakefile ADDED
@@ -0,0 +1,131 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'rake/contrib/sshpublisher'
10
+ require 'fileutils'
11
+ include FileUtils
12
+
13
+ NAME = "quilt"
14
+ AUTHOR = "swdyh"
15
+ EMAIL = "youhei@gmail.com"
16
+ DESCRIPTION = "a library for generating identicon."
17
+ RUBYFORGE_PROJECT = "quilt"
18
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
19
+ BIN_FILES = %w( )
20
+ VERS = "0.0.1"
21
+
22
+ REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
23
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config']
24
+ RDOC_OPTS = [
25
+ '--title', "#{NAME} documentation",
26
+ "--charset", "utf-8",
27
+ "--opname", "index.html",
28
+ "--line-numbers",
29
+ "--main", "README",
30
+ "--inline-source",
31
+ ]
32
+
33
+ task :default => [:test]
34
+ task :package => [:clean]
35
+
36
+ Rake::TestTask.new("test") do |t|
37
+ t.libs << "test"
38
+ t.pattern = "test/**/*_test.rb"
39
+ t.verbose = true
40
+ end
41
+
42
+ spec = Gem::Specification.new do |s|
43
+ s.name = NAME
44
+ s.version = VERS
45
+ s.platform = Gem::Platform::RUBY
46
+ s.has_rdoc = true
47
+ s.extra_rdoc_files = ["README", "ChangeLog", "MIT-LICENSE"]
48
+ s.rdoc_options += RDOC_OPTS + ['--exclude', '^(examples|extras)/']
49
+ s.summary = DESCRIPTION
50
+ s.description = DESCRIPTION
51
+ s.author = AUTHOR
52
+ s.email = EMAIL
53
+ s.homepage = HOMEPATH
54
+ s.executables = BIN_FILES
55
+ s.rubyforge_project = RUBYFORGE_PROJECT
56
+ s.bindir = "bin"
57
+ s.require_path = "lib"
58
+ # s.autorequire = ""
59
+ s.test_files = Dir["test/test_*.rb"]
60
+
61
+ #s.add_dependency('activesupport', '>=1.3.1')
62
+ #s.required_ruby_version = '>= 1.8.2'
63
+
64
+ s.files = %w(README ChangeLog Rakefile) +
65
+ Dir.glob("{bin,doc,test,lib,templates,generator,extras,website,script}/**/*") +
66
+ Dir.glob("ext/**/*.{h,c,rb}") +
67
+ Dir.glob("examples/**/*.rb") +
68
+ Dir.glob("tools/*.rb")
69
+
70
+ s.extensions = FileList["ext/**/extconf.rb"].to_a
71
+ end
72
+
73
+ Rake::GemPackageTask.new(spec) do |p|
74
+ p.need_tar = true
75
+ p.gem_spec = spec
76
+ end
77
+
78
+ task :install do
79
+ name = "#{NAME}-#{VERS}.gem"
80
+ sh %{rake package}
81
+ sh %{sudo gem install pkg/#{name}}
82
+ end
83
+
84
+ task :uninstall => [:clean] do
85
+ sh %{sudo gem uninstall #{NAME}}
86
+ end
87
+
88
+
89
+ Rake::RDocTask.new do |rdoc|
90
+ rdoc.rdoc_dir = 'html'
91
+ rdoc.options += RDOC_OPTS
92
+ rdoc.template = "resh"
93
+ #rdoc.template = "#{ENV['template']}.rb" if ENV['template']
94
+ if ENV['DOC_FILES']
95
+ rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
96
+ else
97
+ rdoc.rdoc_files.include('README', 'ChangeLog')
98
+ rdoc.rdoc_files.include('lib/**/*.rb')
99
+ rdoc.rdoc_files.include('ext/**/*.c')
100
+ end
101
+ end
102
+
103
+ desc "Publish to RubyForge"
104
+ task :rubyforge => [:rdoc, :package] do
105
+ require 'rubyforge'
106
+ Rake::RubyForgePublisher.new(RUBYFORGE_PROJECT, 'swdyh').upload
107
+ end
108
+
109
+ desc 'Package and upload the release to rubyforge.'
110
+ task :release => [:clean, :package] do |t|
111
+ v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z"
112
+ abort "Versions don't match #{v} vs #{VERS}" unless v == VERS
113
+ pkg = "pkg/#{NAME}-#{VERS}"
114
+
115
+ rf = RubyForge.new
116
+ puts "Logging in"
117
+ rf.login
118
+
119
+ c = rf.userconfig
120
+ # c["release_notes"] = description if description
121
+ # c["release_changes"] = changes if changes
122
+ c["preformatted"] = true
123
+
124
+ files = [
125
+ "#{pkg}.tgz",
126
+ "#{pkg}.gem"
127
+ ].compact
128
+
129
+ puts "Releasing #{NAME} v. #{VERS}"
130
+ rf.add_release RUBYFORGE_PROJECT, NAME, VERS, *files
131
+ end
data/lib/quilt.rb ADDED
@@ -0,0 +1,243 @@
1
+ require 'rubygems'
2
+ require 'digest/sha1'
3
+
4
+ module Quilt
5
+ class ImageRmagick
6
+ def initialize width, height
7
+ require 'RMagick'
8
+ @image = Magick::Image.new width, height
9
+ @image.format = 'png'
10
+ end
11
+
12
+ def color r, g, b
13
+ sprintf('#%02x%02x%02x', r, g, b)
14
+ end
15
+
16
+ def transparent color
17
+ @image.transparent color
18
+ end
19
+
20
+ def fill_rect x, y, _x, _y, color
21
+ dr = Magick::Draw.new
22
+ dr.fill color
23
+ dr.rectangle x, y, _x, _y
24
+ dr.draw @image
25
+ end
26
+
27
+ def polygon points, color
28
+ unless points.empty?
29
+ dr = Magick::Draw.new
30
+ dr.fill color
31
+ dr.polygon *(points.flatten)
32
+ dr.draw @image
33
+ end
34
+ end
35
+
36
+ def write path
37
+ # @image.write path
38
+ open(path, 'w') {|f| f.puts @image.to_blob }
39
+ end
40
+
41
+ def to_blob
42
+ @image.to_blob
43
+ end
44
+ end
45
+
46
+ class ImageGD
47
+ def initialize width, height
48
+ require 'GD'
49
+ @image = GD::Image.new width, height
50
+ end
51
+
52
+ def color r, g, b
53
+ @image.colorAllocate r, g, b
54
+ end
55
+
56
+ def transparent color
57
+ @image.transparent color
58
+ end
59
+
60
+ def fill_rect x, y, _x, _y, color
61
+ @image.filledRectangle x, y, _x, _y, color
62
+ end
63
+
64
+ def polygon points, color
65
+ poly = GD::Polygon.new
66
+ points.each do |i|
67
+ poly.addPt i[0], i[1]
68
+ end
69
+ @image.filledPolygon poly, color
70
+ end
71
+
72
+ def write path
73
+ File.open(path, 'w') do |f|
74
+ @image.png f
75
+ end
76
+ end
77
+
78
+ def to_blob
79
+ @image.pngStr
80
+ end
81
+ end
82
+
83
+ class Identicon
84
+ PATCHES = [
85
+ [0, 4, 24, 20, 0],
86
+ [0, 4, 20, 0],
87
+ [2, 24, 20, 2],
88
+ [0, 2, 22, 20, 0],
89
+ [2, 14, 22, 10, 2],
90
+ [0, 14, 24, 22, 0],
91
+ [2, 24, 22, 13, 11, 22, 20, 2],
92
+ [0, 14, 22, 0],
93
+ [6, 8, 18, 16, 6],
94
+ [4, 20, 10, 12, 2, 4],
95
+ [0, 2, 12, 10, 0],
96
+ [10, 14, 22, 10],
97
+ [20, 12, 24, 20],
98
+ [10, 2, 12, 10],
99
+ [0, 2, 10, 0],
100
+ [],
101
+ ]
102
+ CENTER_PATCHES = [0, 4, 8, 15]
103
+ PATCH_SIZE = 5
104
+ @@image_lib = ImageRmagick
105
+ @@salt = ''
106
+ attr_reader :code
107
+
108
+ def initialize str = '', opt = {}
109
+ case opt[:type]
110
+ when :code
111
+ @code = str.to_i
112
+ when :ip
113
+ @code = Identicon.ip2code str
114
+ else
115
+ @code = Identicon.calc_code str.to_s
116
+ end
117
+ @decode = decode @code
118
+ @scale = opt[:scale] || 1
119
+ @patch_width = (PATCH_SIZE - 1) * @scale + 1
120
+ @image = @@image_lib.new @patch_width * 3, @patch_width * 3
121
+ @back_color = @image.color 255, 255, 255
122
+ @fore_color = @image.color @decode[:red], @decode[:green], @decode[:blue]
123
+ @image.transparent @back_color
124
+ render
125
+ end
126
+
127
+ def decode code
128
+ {
129
+ :center_type => (code & 0x3),
130
+ :center_invert => (((code >> 2) & 0x01) != 0),
131
+ :corner_type => ((code >> 3) & 0x0f),
132
+ :corner_invert => (((code >> 7) & 0x01) != 0),
133
+ :corner_turn => ((code >> 8) & 0x03),
134
+ :side_type => ((code >> 10) & 0x0f),
135
+ :side_invert => (((code >> 14) & 0x01) != 0),
136
+ :side_turn => ((code >> 15) & 0x03),
137
+ :red => (((code >> 16) & 0x01f) << 3),
138
+ :green => (((code >> 21) & 0x01f) << 3),
139
+ :blue => (((code >> 27) & 0x01f) << 3),
140
+ }
141
+ end
142
+
143
+ def render
144
+ center = [[1, 1]]
145
+ side = [[1, 0], [2, 1], [1, 2], [0, 1]]
146
+ corner = [[0, 0], [2, 0], [2, 2], [0, 2]]
147
+
148
+ draw_patches(center, CENTER_PATCHES[@decode[:center_type]],
149
+ 0, @decode[:center_invert])
150
+ draw_patches(side, @decode[:side_type],
151
+ @decode[:side_turn], @decode[:side_invert])
152
+ draw_patches(corner, @decode[:corner_type],
153
+ @decode[:corner_turn], @decode[:corner_invert])
154
+ end
155
+
156
+ def draw_patches list, patch, turn, invert
157
+ list.each do |i|
158
+ draw(:x => i[0], :y => i[1], :patch => patch,
159
+ :turn => turn, :invert => invert)
160
+ turn += 1
161
+ end
162
+ end
163
+
164
+ def draw opt = {}
165
+ x = opt[:x] * @patch_width
166
+ y = opt[:y] * @patch_width
167
+ patch = opt[:patch] % PATCHES.size
168
+ turn = opt[:turn] % 4
169
+
170
+ if opt[:invert]
171
+ fore, back = @back_color, @fore_color
172
+ else
173
+ fore, back = @fore_color, @back_color
174
+ end
175
+ @image.fill_rect(x, y, x + @patch_width, y + @patch_width, back)
176
+
177
+ points = []
178
+ PATCHES[patch].each do |pt|
179
+ dx = pt % PATCH_SIZE
180
+ dy = pt / PATCH_SIZE
181
+ px = dx.to_f / (PATCH_SIZE - 1) * @patch_width
182
+ py = dy.to_f / (PATCH_SIZE - 1) * @patch_width
183
+
184
+ case turn
185
+ when 1
186
+ px, py = @patch_width - py, px
187
+ when 2
188
+ px, py = @patch_width - px, @patch_width - py
189
+ when 3
190
+ px, py = py, @patch_width - px
191
+ end
192
+ points << [x + px, y + py]
193
+ end
194
+ @image.polygon points, fore
195
+ end
196
+
197
+ def write path = "#{@code}.png"
198
+ @image.write path
199
+ end
200
+
201
+ def to_blob
202
+ @image.to_blob
203
+ end
204
+
205
+ def self.calc_code str
206
+ extract_code Identicon.digest(str)
207
+ end
208
+
209
+ def self.ip2code ip
210
+ code_ip = extract_code(ip.split('.'))
211
+ extract_code Identicon.digest(code_ip.to_s)
212
+ end
213
+
214
+ def self.digest str
215
+ Digest::SHA1.digest(str + @@salt)
216
+ end
217
+
218
+ def self.extract_code list
219
+ tmp = [list[0].to_i << 24, list[1].to_i << 16,
220
+ list[2].to_i << 8, list[3].to_i]
221
+ tmp.inject(0) do |r, i|
222
+ r | ((i[31] == 1) ? -(i & 0x7fffffff) : i)
223
+ end
224
+ end
225
+
226
+ def self.image_lib= image_lib
227
+ @@image_lib = image_lib
228
+ end
229
+
230
+ def self.image_lib
231
+ @@image_lib
232
+ end
233
+
234
+ def self.salt= salt
235
+ @@salt = salt
236
+ end
237
+
238
+ def self.salt
239
+ @@salt
240
+ end
241
+ end
242
+ end
243
+
@@ -0,0 +1,73 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+ require 'test/unit'
3
+ require 'digest/md5'
4
+ require 'fileutils'
5
+
6
+ class QultTest < Test::Unit::TestCase
7
+ def setup
8
+ @tmp_dir = File.join 'test', 'tmp'
9
+ unless File.exist? @tmp_dir
10
+ Dir.mkdir @tmp_dir
11
+ end
12
+ end
13
+
14
+ def teardown
15
+ if File.exist? @tmp_dir
16
+ FileUtils.rm_r @tmp_dir
17
+ end
18
+ end
19
+
20
+ def test_identicon
21
+ identicon = Quilt::Identicon.new
22
+ assert_instance_of Quilt::Identicon, identicon
23
+ path = File.join 'test', 'tmp', 'test'
24
+ identicon.write path
25
+ assert File.exist?(path)
26
+ File.unlink path
27
+ end
28
+
29
+ def test_to_blob
30
+ identicon = Quilt::Identicon.new
31
+ path_b = File.join 'test', 'tmp', 'test_to_blob.png'
32
+ path_w = File.join 'test', 'tmp', 'test_write.png'
33
+
34
+ open(path_b, 'w') {|f| f.write identicon.to_blob }
35
+ identicon.write path_w
36
+
37
+ digest = Proc.new {|path| Digest::MD5.hexdigest(IO.read(path)) }
38
+ assert_equal digest.call(path_w), digest.call(path_w)
39
+
40
+ File.unlink path_b, path_w
41
+ end
42
+
43
+ def test_digest
44
+ digest = Quilt::Identicon.digest('foo')
45
+ assert_not_nil digest
46
+ Quilt::Identicon.salt = 'foo'
47
+ assert_not_equal digest, Quilt::Identicon.digest('foo')
48
+ end
49
+
50
+ def test_image_lib
51
+ image_other = Class.new do
52
+ def initialize a, b; end
53
+ def method_missing *arg; end
54
+ def write path; open(path, 'w') {|f| f.puts 'other' }; end
55
+ end
56
+
57
+ libs = [Quilt::ImageGD, Quilt::ImageRmagick, image_other]
58
+ libs.each do |lib|
59
+ Quilt::Identicon.image_lib = lib
60
+ assert_equal lib, Quilt::Identicon.image_lib
61
+ identicon = Quilt::Identicon.new
62
+ assert_equal lib, identicon.instance_variable_get(:@image).class
63
+ end
64
+ end
65
+
66
+ def test_salt
67
+ salts = ['foo', 'bar', 'baz']
68
+ salts.each do |salt|
69
+ Quilt::Identicon.salt = salt
70
+ assert_equal salt, Quilt::Identicon.salt
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,3 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/quilt'
3
+
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: quilt
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - swdyh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-04-13 00:00:00 +09:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: a library for generating identicon.
17
+ email: youhei@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ - ChangeLog
25
+ - MIT-LICENSE
26
+ files:
27
+ - README
28
+ - ChangeLog
29
+ - Rakefile
30
+ - test/quilt_test.rb
31
+ - test/test_helper.rb
32
+ - lib/quilt.rb
33
+ - MIT-LICENSE
34
+ has_rdoc: true
35
+ homepage: http://quilt.rubyforge.org
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --title
39
+ - quilt documentation
40
+ - --charset
41
+ - utf-8
42
+ - --opname
43
+ - index.html
44
+ - --line-numbers
45
+ - --main
46
+ - README
47
+ - --inline-source
48
+ - --exclude
49
+ - ^(examples|extras)/
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ requirements: []
65
+
66
+ rubyforge_project: quilt
67
+ rubygems_version: 1.0.1
68
+ signing_key:
69
+ specification_version: 2
70
+ summary: a library for generating identicon.
71
+ test_files:
72
+ - test/test_helper.rb