ico 0.1.0
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.
- checksums.yaml +7 -0
- data/.autotest +25 -0
- data/.gitignore +54 -0
- data/.hoeignore +11 -0
- data/Gemfile +21 -0
- data/History.txt +6 -0
- data/LICENSE +22 -0
- data/Manifest.txt +17 -0
- data/README.md +107 -0
- data/Rakefile +67 -0
- data/lib/core_ext/array/extract_options.rb +31 -0
- data/lib/ico.rb +109 -0
- data/lib/ico/icon_dir.rb +17 -0
- data/lib/ico/icon_dir_entry.rb +40 -0
- data/lib/ico/icon_image.rb +23 -0
- data/lib/ico/utils.rb +145 -0
- data/lib/ico/version.rb +3 -0
- data/lib/tasks/ico.rake +48 -0
- metadata +236 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c064583f3bb03c8b2c7a4694c398cf335900de69
|
4
|
+
data.tar.gz: 3650715d02a41fe6ffc78af9dca2d40fedff8160
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: db45233ea75ef0015f5e6adc091ed1747bdb1cfeb13fc947246772dae4e38e67354221f3cd70a858dd4c5efe7881f9ca620459e515538a19601105f162c27f36
|
7
|
+
data.tar.gz: 0512d897448380af03c439e6ad59717478cf3a860acaf2ea478edd9ddb7aa9ba71a8ebceb4ba0b93c34842bc6ec170129bd2aaa03fd62f53aada4697c83678e1
|
data/.autotest
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require "autotest/restart"
|
4
|
+
|
5
|
+
# Autotest.add_hook :initialize do |at|
|
6
|
+
# at.testlib = "minitest/unit"
|
7
|
+
#
|
8
|
+
# at.extra_files << "../some/external/dependency.rb"
|
9
|
+
#
|
10
|
+
# at.libs << ":../some/external"
|
11
|
+
#
|
12
|
+
# at.add_exception "vendor"
|
13
|
+
#
|
14
|
+
# at.add_mapping(/dependency.rb/) do |f, _|
|
15
|
+
# at.files_matching(/test_.*rb$/)
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# %w(TestA TestB).each do |klass|
|
19
|
+
# at.extra_class_map[klass] = "test/test_misc.rb"
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
|
23
|
+
# Autotest.add_hook :run_command do |at|
|
24
|
+
# system "rake build"
|
25
|
+
# end
|
data/.gitignore
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
## Specific to RubyMotion:
|
17
|
+
.dat*
|
18
|
+
.repl_history
|
19
|
+
build/
|
20
|
+
*.bridgesupport
|
21
|
+
build-iPhoneOS/
|
22
|
+
build-iPhoneSimulator/
|
23
|
+
|
24
|
+
## Specific to RubyMotion (use of CocoaPods):
|
25
|
+
#
|
26
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
27
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
28
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
29
|
+
#
|
30
|
+
# vendor/Pods/
|
31
|
+
|
32
|
+
## Documentation cache and generated files:
|
33
|
+
/.yardoc/
|
34
|
+
/_yardoc/
|
35
|
+
/doc/
|
36
|
+
/rdoc/
|
37
|
+
|
38
|
+
## Environment normalization:
|
39
|
+
/.bundle/
|
40
|
+
/vendor/bundle
|
41
|
+
/lib/bundler/man/
|
42
|
+
|
43
|
+
# for a library or gem, you might want to ignore these files since the code is
|
44
|
+
# intended to run in multiple environments; otherwise, check them in:
|
45
|
+
# Gemfile.lock
|
46
|
+
# .ruby-version
|
47
|
+
# .ruby-gemset
|
48
|
+
|
49
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
50
|
+
.rvmrc
|
51
|
+
|
52
|
+
.DS_Store
|
53
|
+
*.swp
|
54
|
+
*.swo
|
data/.hoeignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
# DO NOT EDIT THIS FILE. Instead, edit Rakefile, and run `rake bundler:gemfile`.
|
4
|
+
|
5
|
+
source "https://rubygems.org/"
|
6
|
+
|
7
|
+
gem "chunky_png", "1.3.8"
|
8
|
+
gem "bit-struct", "0.15.0"
|
9
|
+
gem "bmp-ruby", "0.1.1"
|
10
|
+
|
11
|
+
gem "minitest", "~>5.10", :group => [:development, :test]
|
12
|
+
gem "hoe-yard", ">=0.1.3", :group => [:development, :test]
|
13
|
+
gem "hoe-ignore", "~>1.0", :group => [:development, :test]
|
14
|
+
gem "hoe-bundler", "~>1.2", :group => [:development, :test]
|
15
|
+
gem "hoe-gemspec", "~>1.0", :group => [:development, :test]
|
16
|
+
gem "hoe-git", "~>1.6", :group => [:development, :test]
|
17
|
+
gem "yard", "~>0.8", :group => [:development, :test]
|
18
|
+
gem "redcarpet", "~>3.3", :group => [:development, :test]
|
19
|
+
gem "hoe", "~>3.16", :group => [:development, :test]
|
20
|
+
|
21
|
+
# vim: syntax=ruby
|
data/History.txt
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2017 Bordee Inc.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
'Software'), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest.txt
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
.autotest
|
2
|
+
.gitignore
|
3
|
+
.hoeignore
|
4
|
+
Gemfile
|
5
|
+
History.txt
|
6
|
+
LICENSE
|
7
|
+
Manifest.txt
|
8
|
+
README.md
|
9
|
+
Rakefile
|
10
|
+
lib/core_ext/array/extract_options.rb
|
11
|
+
lib/ico.rb
|
12
|
+
lib/ico/icon_dir.rb
|
13
|
+
lib/ico/icon_dir_entry.rb
|
14
|
+
lib/ico/icon_image.rb
|
15
|
+
lib/ico/utils.rb
|
16
|
+
lib/ico/version.rb
|
17
|
+
lib/tasks/ico.rake
|
data/README.md
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# ico
|
2
|
+
|
3
|
+
ICO file format in Ruby
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
```
|
8
|
+
require 'ico'
|
9
|
+
|
10
|
+
# (soon)
|
11
|
+
```
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Command Line
|
16
|
+
|
17
|
+
```
|
18
|
+
gem install ico
|
19
|
+
```
|
20
|
+
|
21
|
+
Gemfile
|
22
|
+
|
23
|
+
```
|
24
|
+
gem "ico", "~>0.1"
|
25
|
+
```
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
(soon)
|
30
|
+
|
31
|
+
For more info, see: https://en.wikipedia.org/wiki/ICO_(file_format)
|
32
|
+
|
33
|
+
### Requirements
|
34
|
+
|
35
|
+
* [Bit-Struct](https://github.com/vjoel/bit-struct)
|
36
|
+
* [BMP](https://github.com/bordeeinc/bmp-ruby)
|
37
|
+
|
38
|
+
### Dev Requirements
|
39
|
+
|
40
|
+
* [hoe](https://github.com/seattlerb/hoe) gem manager
|
41
|
+
* [hoe-bundler] may need `gem install hoe-bundler` installation before using `rake bundler:gemfile`
|
42
|
+
* [YARD](http://yardoc.org) docs
|
43
|
+
* [redcarpet](https://github.com/vmg/redcarpet) for yardoc
|
44
|
+
|
45
|
+
[hoe-bundler]: https://github.com/flavorjones/hoe-bundler
|
46
|
+
|
47
|
+
### Testing
|
48
|
+
|
49
|
+
Tests written with [minitest]
|
50
|
+
|
51
|
+
```
|
52
|
+
rake test
|
53
|
+
```
|
54
|
+
|
55
|
+
[minitest]: https://github.com/seattlerb/minitest
|
56
|
+
|
57
|
+
### Contributing
|
58
|
+
|
59
|
+
Send tested code.
|
60
|
+
Thank you, [contributors]!
|
61
|
+
|
62
|
+
[contributors]: https://github.com/bordeeinc/ico/graphs/contributors
|
63
|
+
|
64
|
+
### To Do
|
65
|
+
|
66
|
+
* (soon)
|
67
|
+
|
68
|
+
## License
|
69
|
+
|
70
|
+
MIT License
|
71
|
+
|
72
|
+
Copyright (c) 2017 Bordee Inc.
|
73
|
+
|
74
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
75
|
+
a copy of this software and associated documentation files (the
|
76
|
+
'Software'), to deal in the Software without restriction, including
|
77
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
78
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
79
|
+
permit persons to whom the Software is furnished to do so, subject to
|
80
|
+
the following conditions:
|
81
|
+
|
82
|
+
The above copyright notice and this permission notice shall be
|
83
|
+
included in all copies or substantial portions of the Software.
|
84
|
+
|
85
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
88
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
89
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
90
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
91
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
92
|
+
|
93
|
+
## About
|
94
|
+
|
95
|
+

|
96
|
+
|
97
|
+
ICO is maintained and funded by Bordee Inc.
|
98
|
+
The names and logos for Bordee are trademarks of [Bordee Inc.][bordeeinc]
|
99
|
+
|
100
|
+
[bordeeinc]: http://bordee.com
|
101
|
+
|
102
|
+
We love open source software!
|
103
|
+
See [our other projects][bordee-github]
|
104
|
+
and [check out Seattle.rb!][community]
|
105
|
+
|
106
|
+
[bordee-github]: https://github.com/bordeeinc
|
107
|
+
[community]: https://seattlerb.org
|
data/Rakefile
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "hoe"
|
5
|
+
require './lib/ico/version.rb'
|
6
|
+
|
7
|
+
Hoe.plugin :gemspec
|
8
|
+
Hoe.plugin :minitest
|
9
|
+
Hoe.plugin :yard
|
10
|
+
Hoe.plugin :bundler
|
11
|
+
Hoe.plugin :git
|
12
|
+
Hoe.plugin :ignore
|
13
|
+
|
14
|
+
Hoe.spec "ico" do
|
15
|
+
developer("So Awesome Man", "callme@1800aweso.me")
|
16
|
+
|
17
|
+
license "MIT" # this matches the license in the README
|
18
|
+
|
19
|
+
self.email = 'support@bordee.com'
|
20
|
+
|
21
|
+
self.name = 'ico'
|
22
|
+
self.version = ICO::VERSION
|
23
|
+
self.summary = 'ICO file format in Ruby'
|
24
|
+
self.description = self.summary
|
25
|
+
self.urls = ['https://github.com/bordeeinc/ico']
|
26
|
+
self.testlib = :minitest
|
27
|
+
self.readme_file = 'README.md'
|
28
|
+
self.history_file = 'History.txt'
|
29
|
+
|
30
|
+
# third-party
|
31
|
+
self.yard_title = self.name
|
32
|
+
self.yard_markup = 'markdown'
|
33
|
+
|
34
|
+
self.extra_deps += [
|
35
|
+
['chunky_png', '1.3.8'],
|
36
|
+
['bit-struct', '0.15.0'],
|
37
|
+
['bmp-ruby', '0.1.1']
|
38
|
+
]
|
39
|
+
|
40
|
+
self.extra_dev_deps += [
|
41
|
+
["hoe-yard", "~> 0.1"],
|
42
|
+
["hoe-ignore", "~> 1.0"],
|
43
|
+
["hoe-bundler", "~> 1.2"],
|
44
|
+
["hoe-gemspec", "~> 1.0"],
|
45
|
+
["hoe-git", "~> 1.6"],
|
46
|
+
["minitest", "~> 5.9"],
|
47
|
+
["yard", "~> 0.8"],
|
48
|
+
["redcarpet", "~> 3.3"] # yard/markdown
|
49
|
+
]
|
50
|
+
|
51
|
+
self.clean_globs += [
|
52
|
+
'.yardoc',
|
53
|
+
'vendor',
|
54
|
+
'Gemfile.lock',
|
55
|
+
'.bundle',
|
56
|
+
]
|
57
|
+
|
58
|
+
self.spec_extras = {
|
59
|
+
:required_ruby_version => '>= 1.9.2'
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
# require rake tasks
|
64
|
+
current_dir = File.expand_path(File.dirname(__FILE__))
|
65
|
+
Dir.glob(File.join(current_dir, 'lib/tasks/*.rake')).each {|r| import r}
|
66
|
+
|
67
|
+
# vim: syntax=ruby
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# @note copied from the main Rails repo instead of adding via active_support
|
2
|
+
# @see https://github.com/rails/rails/blob/794a70f94485fb64ed1c49ba8532895306e2001c/activesupport/lib/active_support/core_ext/array/extract_options.rb
|
3
|
+
class Hash
|
4
|
+
# By default, only instances of Hash itself are extractable.
|
5
|
+
# Subclasses of Hash may implement this method and return
|
6
|
+
# true to declare themselves as extractable. If a Hash
|
7
|
+
# is extractable, Array#extract_options! pops it from
|
8
|
+
# the Array when it is the last element of the Array.
|
9
|
+
def extractable_options?
|
10
|
+
instance_of?(Hash)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Array
|
15
|
+
# Extracts options from a set of arguments. Removes and returns the last
|
16
|
+
# element in the array if it's a hash, otherwise returns a blank hash.
|
17
|
+
#
|
18
|
+
# def options(*args)
|
19
|
+
# args.extract_options!
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# options(1, 2) # => {}
|
23
|
+
# options(1, 2, a: :b) # => {:a=>:b}
|
24
|
+
def extract_options!
|
25
|
+
if last.is_a?(Hash) && last.extractable_options?
|
26
|
+
pop
|
27
|
+
else
|
28
|
+
{}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/ico.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'bmp'
|
2
|
+
|
3
|
+
require 'core_ext/array/extract_options.rb' unless Array.method_defined?(:extract_options!)
|
4
|
+
require 'bit-struct' unless Object.const_defined?(:BitStruct)
|
5
|
+
require 'chunky_png' unless Object.const_defined?(:ChunkyPNG)
|
6
|
+
|
7
|
+
require 'ico/version'
|
8
|
+
require 'ico/utils'
|
9
|
+
require 'ico/icon_dir'
|
10
|
+
require 'ico/icon_dir_entry'
|
11
|
+
require 'ico/icon_image'
|
12
|
+
|
13
|
+
#
|
14
|
+
# @see https://en.wikipedia.org/wiki/ICO_(file_format)
|
15
|
+
#
|
16
|
+
module ICO
|
17
|
+
|
18
|
+
# make all methods class-methods
|
19
|
+
extend self
|
20
|
+
|
21
|
+
# create ICO object
|
22
|
+
#
|
23
|
+
# @param filename_array [String, Array<String>] filename, or array of filenames
|
24
|
+
# @return [BitStruct]
|
25
|
+
#
|
26
|
+
def new(filename_array)
|
27
|
+
raise ArgumentError unless (filename_array.is_a?(Array) || filename_array.is_a?(String))
|
28
|
+
|
29
|
+
# ensure non-nested array
|
30
|
+
fn_array = [filename_array].flatten
|
31
|
+
|
32
|
+
# ensure .png extensions
|
33
|
+
raise "more than PNG format files in #{filename_array.inspect}" if ICO::Utils.contains_other_than_ext?(fn_array, :png)
|
34
|
+
|
35
|
+
icon_dir = ICO::IconDir.new
|
36
|
+
icon_dir.image_count = fn_array.length
|
37
|
+
offset = ICO::IconDir::LENGTH_IN_BYTES + (fn_array.length * ICO::IconDirEntry::LENGTH_IN_BYTES)
|
38
|
+
entries = fn_array.inject({}) {|h,fn| h[fn] = ICO::IconDirEntry.new; h}
|
39
|
+
images = fn_array.inject({}) {|h,fn| h[fn] = ICO::IconImage.new; h}
|
40
|
+
images_hash = ICO::Utils.sizes_hash(fn_array, true, true)
|
41
|
+
|
42
|
+
images_hash.each do |size,fn|
|
43
|
+
img = ChunkyPNG::Image.from_file(fn)
|
44
|
+
img_hash = BMP::Utils.parse_image(img)
|
45
|
+
|
46
|
+
entry = entries[fn]
|
47
|
+
image = images[fn]
|
48
|
+
|
49
|
+
entry.width = img_hash[:image_width]
|
50
|
+
entry.height = img_hash[:image_height]
|
51
|
+
entry.bytes_in_res = img_hash[:file_size]
|
52
|
+
entry.image_offset = offset
|
53
|
+
|
54
|
+
image.width = img_hash[:image_width]
|
55
|
+
image.height = (img_hash[:image_height] * 2)
|
56
|
+
image.size_image = img_hash[:image_size]
|
57
|
+
image.data = img_hash[:pixel_array]
|
58
|
+
|
59
|
+
offset += img_hash[:file_size]
|
60
|
+
end
|
61
|
+
|
62
|
+
# IconDirEntry section as binary data string
|
63
|
+
icon_dir.data = images_hash.inject('') {|str,(k,v)| str += entries.fetch(v); str}
|
64
|
+
|
65
|
+
# IconImage section as binary data string
|
66
|
+
icon_dir.data += images_hash.inject('') {|str,(k,v)| str += images.fetch(v); str}
|
67
|
+
|
68
|
+
icon_dir
|
69
|
+
end
|
70
|
+
|
71
|
+
# PNG to ICO
|
72
|
+
#
|
73
|
+
# @param input_filename [Array<String>,String] "/path/to/example.png" OR ["/path/to/example.png", ...]
|
74
|
+
# @param output_filename [String] "/path/to/example_generated.ico"
|
75
|
+
# @return [String] filename of generated ico
|
76
|
+
#
|
77
|
+
def png_to_ico(filename_array, output_filename, overwrite=false)
|
78
|
+
ico = ICO.new(filename_array)
|
79
|
+
|
80
|
+
unless overwrite
|
81
|
+
raise "File exists: #{output_filename}" if File.exist?(output_filename)
|
82
|
+
end
|
83
|
+
|
84
|
+
IO.write(output_filename, ico)
|
85
|
+
end
|
86
|
+
|
87
|
+
# PNG to ICO force overwrite output_filename
|
88
|
+
#
|
89
|
+
def png_to_ico!(filename_array, output_filename)
|
90
|
+
png_to_ico(filename_array, output_filename, true)
|
91
|
+
end
|
92
|
+
|
93
|
+
# PNG to resized PNGs to ICO
|
94
|
+
#
|
95
|
+
# @param input_filename [String] "/path/to/example.png"
|
96
|
+
# @param sizes_array [Array<Array<Integer,Integer]>>, Array<Integer>]
|
97
|
+
# rectangles use Array with XY: `[x,y]`
|
98
|
+
# squares use single Integer `N`
|
99
|
+
# mixed indices is valid
|
100
|
+
# example: `[24, [24,24], [480,270], 888] # a[0] => 24x24; a[1] => 24x24; a[2] => 480x270; a[3] => 888x888`
|
101
|
+
# @param output_filename [String] "/path/to/example.ico"
|
102
|
+
# @return [String] filename of generated ico
|
103
|
+
#
|
104
|
+
def png_resize_to_ico(input_filename, sizes_array, output_filename)
|
105
|
+
output_dir = ICO::Utils.png_to_sizes(input_filename, sizes_array)
|
106
|
+
filename_array = Dir.glob(File.join(output_dir, '**/*'))
|
107
|
+
png_to_ico(filename_array, output_filename)
|
108
|
+
end
|
109
|
+
end
|
data/lib/ico/icon_dir.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module ICO
|
2
|
+
class IconDir < BitStruct
|
3
|
+
LENGTH_IN_BYTES = 6
|
4
|
+
|
5
|
+
default_options :endian => :little
|
6
|
+
|
7
|
+
unsigned :reserved, 16, 'Reserved. Must always be 0.', :default => 0
|
8
|
+
|
9
|
+
unsigned :type, 16, 'Specifies image type: 1 for icon (.ICO) ' +
|
10
|
+
'image, 2 for cursor (.CUR) image. Other ' +
|
11
|
+
'values are invalid.', :default => 1
|
12
|
+
|
13
|
+
unsigned :image_count, 16, 'Specifies number of images in the file.', :default => 0
|
14
|
+
|
15
|
+
rest :data, 'IconDirEntry + IconImage sections as binary data strings'
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ICO
|
2
|
+
class IconDirEntry < BitStruct
|
3
|
+
LENGTH_IN_BYTES = 16
|
4
|
+
|
5
|
+
default_options :endian => :little
|
6
|
+
|
7
|
+
unsigned :width, 8, 'Specifies image width in pixels. Can be ' +
|
8
|
+
'any number between 0 and 255. Value 0 ' +
|
9
|
+
'means image width is 256 pixels.'
|
10
|
+
|
11
|
+
unsigned :height, 8, 'Specifies image height in pixels. Can be ' +
|
12
|
+
'any number between 0 and 255. Value 0 ' +
|
13
|
+
'means image width is 256 pixels.'
|
14
|
+
|
15
|
+
unsigned :color_count, 8, 'Specifies number of colors in the color ' +
|
16
|
+
'palette. Should be 0 if the image does ' +
|
17
|
+
'not use a color palette.', :default => 0
|
18
|
+
|
19
|
+
unsigned :reserved, 8, 'Reserved. Should be 0. [NOTES 2]', :default => 0
|
20
|
+
|
21
|
+
unsigned :planes, 16, 'In ICO format: Specifies color planes. ' +
|
22
|
+
"Should be 0 or 1.\n" +
|
23
|
+
'In CUR format: Specifies the horizontal ' +
|
24
|
+
'coordinates of the hotspot in number of ' +
|
25
|
+
'pixels from the left.', :default => 1
|
26
|
+
|
27
|
+
unsigned :bit_count, 16, 'In ICO format: Specifies bits per pixel. ' +
|
28
|
+
"[NOTES 4]\n" +
|
29
|
+
'In CUR format: Specifies the vertical ' +
|
30
|
+
'coordinates of the hotspot in number of ' +
|
31
|
+
'pixels from the top.', :default => 32
|
32
|
+
|
33
|
+
unsigned :bytes_in_res, 32, 'Specifies the size of the image\'s data ' +
|
34
|
+
'in bytes'
|
35
|
+
|
36
|
+
unsigned :image_offset, 32, 'Specifies the offset of BMP or PNG data ' +
|
37
|
+
'from the beginning of the ICO/CUR file'
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ICO
|
2
|
+
class IconImage < BitStruct
|
3
|
+
HEADER_SIZE_IN_BYTES = 40
|
4
|
+
|
5
|
+
default_options :endian => :little
|
6
|
+
|
7
|
+
# BITMAPINFOHEADER
|
8
|
+
unsigned :header_size, 32, nil, :default => HEADER_SIZE_IN_BYTES
|
9
|
+
unsigned :width, 32
|
10
|
+
unsigned :height, 32
|
11
|
+
unsigned :planes, 16, nil, :default => 1
|
12
|
+
unsigned :bit_count, 16, nil, :default => 32
|
13
|
+
unsigned :compression, 32, nil, :default => 0
|
14
|
+
unsigned :size_image, 32
|
15
|
+
unsigned :x_pixels_per_meter, 32, nil, :default => 5669
|
16
|
+
unsigned :y_pixels_per_meter, 32, nil, :default => 5669
|
17
|
+
unsigned :colors_used, 32, nil, :default => 0
|
18
|
+
unsigned :colors_important, 32, nil, :default => 0
|
19
|
+
|
20
|
+
# IMAGEDATA
|
21
|
+
rest :data, '32bit RGBQUAD written: BGRA'
|
22
|
+
end
|
23
|
+
end
|
data/lib/ico/utils.rb
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
module ICO
|
2
|
+
module Utils
|
3
|
+
APPEND_FILE_FORMAT = '-%<x>dx%<y>d'
|
4
|
+
|
5
|
+
extend self
|
6
|
+
|
7
|
+
|
8
|
+
# @see https://ruby-doc.org/core-2.2.3/Enumerable.html#method-i-select
|
9
|
+
# @see https://ruby-doc.org/core-2.2.3/Enumerable.html#method-i-reject
|
10
|
+
# @param filename_array [Array<String>] array of filenames with expanded paths
|
11
|
+
# @param enum [String,Symbol] accepts: `:select` or `:reject`
|
12
|
+
# @return [Array]
|
13
|
+
def filter_dir(filename_array, enum)
|
14
|
+
raise ArgumentError unless filename_array.is_a? Array
|
15
|
+
raise ArgumentError unless enum.is_a?(String) || enum.is_a?(Symbol)
|
16
|
+
raise ArgumentError unless enum.to_s =~ /reject|select/
|
17
|
+
|
18
|
+
filename_array.send(enum).each {|fn| Dir.exist?(fn)}
|
19
|
+
end
|
20
|
+
|
21
|
+
def filter_ext(filename_array, enum, extname, include_dirs=false)
|
22
|
+
raise ArgumentError unless filename_array.is_a? Array
|
23
|
+
raise ArgumentError unless enum.is_a?(String) || enum.is_a?(Symbol)
|
24
|
+
raise ArgumentError unless enum.to_s =~ /reject|select/
|
25
|
+
raise ArgumentError unless extname.is_a?(String) || extname.is_a?(Symbol)
|
26
|
+
|
27
|
+
# reject dirs for accuracy
|
28
|
+
tmp_array = filter_dir(filename_array, :reject)
|
29
|
+
|
30
|
+
# operation on array
|
31
|
+
tmp_array = tmp_array.send(enum).each {|fn| format_ext(File.extname(fn)) == format_ext(extname)}
|
32
|
+
|
33
|
+
include_dirs ? tmp_array + filter_dir(filename_array, :select) : tmp_array
|
34
|
+
end
|
35
|
+
|
36
|
+
def format_ext(extname, overwrite=false)
|
37
|
+
raise ArgumentError unless extname.is_a?(String) || extname.is_a?(Symbol)
|
38
|
+
|
39
|
+
temp_str = extname.to_s.sub(/\A\.?/, '.').downcase
|
40
|
+
|
41
|
+
extname = tmp_str if overwrite
|
42
|
+
|
43
|
+
temp_str
|
44
|
+
end
|
45
|
+
|
46
|
+
def format_ext!(extname)
|
47
|
+
format_ext(extname, true)
|
48
|
+
end
|
49
|
+
|
50
|
+
def contains_dir?(filename_array)
|
51
|
+
filename_dir(filename_array, :select).any?
|
52
|
+
end
|
53
|
+
|
54
|
+
def contains_other_than_ext?(filename_array, extname)
|
55
|
+
filter_ext(filename_array, :reject, extname, true).any?
|
56
|
+
end
|
57
|
+
|
58
|
+
# http://stackoverflow.com/questions/2450906/is-there-a-simple-way-to-get-image-dimensions-in-ruby#2450931
|
59
|
+
def get_size(image_filename)
|
60
|
+
IO.read(image_filename)[0x10..0x18].unpack('NN')
|
61
|
+
end
|
62
|
+
|
63
|
+
def sizes_hash(filename_array, sort=false, reverse=false)
|
64
|
+
raise ArgumentError unless filename_array.is_a? Array
|
65
|
+
|
66
|
+
tmp_hash = filename_array.inject({}) {|h,fn| h[get_size(fn)] = fn; h}
|
67
|
+
|
68
|
+
case
|
69
|
+
when sort && !reverse
|
70
|
+
return tmp_hash.sort.to_h
|
71
|
+
|
72
|
+
when reverse && !sort
|
73
|
+
return tmp_hash.to_a.reverse.to_h
|
74
|
+
|
75
|
+
when sort && reverse
|
76
|
+
return tmp_hash.sort.reverse.to_h
|
77
|
+
|
78
|
+
else
|
79
|
+
return tmp_hash
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
# resize PNG file and write new sizes to directory
|
85
|
+
#
|
86
|
+
# @see https://ruby-doc.org/core-2.2.0/Kernel.html#method-i-sprintf
|
87
|
+
# @param input_filename [String] input filename; required: file is PNG file format
|
88
|
+
# @param sizes_array [Array<Array<Integer,Integer]>>, Array<Integer>]
|
89
|
+
# rectangles use Array with XY: `[x,y]`
|
90
|
+
# squares use single Integer `N`
|
91
|
+
# mixed indices is valid
|
92
|
+
# example: `[24, [24,24], [480,270], 888] # a[0] => 24x24; a[1] => 24x24; a[2] => 480x270; a[3] => 888x888`
|
93
|
+
# @param output_dirname [String] (optional)
|
94
|
+
# directory name including expanded path
|
95
|
+
# default: new dir named input_filename's basename + "_sizes" in same dir as input_filename
|
96
|
+
# @param append_filenames [String] (optional,required-with-supplied-default)
|
97
|
+
# append resized filenames with Kernel#sprintf format_string
|
98
|
+
# available args: `{:x => N, :y => N}`
|
99
|
+
# default: `"-%<x>dx%<y>d"`
|
100
|
+
# @param force_overwrite [Boolean] overwrite existing resized images
|
101
|
+
# @param clear [Boolean] default: `true`
|
102
|
+
# @param force_clear [Boolean] clear output_dirname of contents before write; default: false
|
103
|
+
# @return [String] output_dirname; default: false
|
104
|
+
def png_to_sizes(input_filename, sizes_array, output_dirname=nil, append_filenames=APPEND_FILE_FORMAT, force_overwrite=false, clear=true, force_clear=false)
|
105
|
+
basename = File.basename(input_filename, '.*')
|
106
|
+
|
107
|
+
output_dirname ||= File.join(File.expand_path(File.dirname(input_filename)), "#{basename}_sizes")
|
108
|
+
|
109
|
+
# ensure dir exists
|
110
|
+
FileUtils.mkdir_p(output_dirname)
|
111
|
+
|
112
|
+
# ensure dir empty
|
113
|
+
if clear
|
114
|
+
filename_array = Dir.glob(File.join(output_dirname, '**/*'))
|
115
|
+
|
116
|
+
unless force_clear
|
117
|
+
# protect from destructive action
|
118
|
+
raise "more than ICO format files in #{output_dirname}" if contains_other_than_ext?(filename_array, :ico)
|
119
|
+
end
|
120
|
+
|
121
|
+
FileUtils.rm_rf(filename_array)
|
122
|
+
end
|
123
|
+
|
124
|
+
# import base image
|
125
|
+
img = ChunkyPNG::Image.from_file(input_filename)
|
126
|
+
|
127
|
+
# resize
|
128
|
+
sizes_array.each do |x,y|
|
129
|
+
y ||= x
|
130
|
+
img_attrs = {:x => x, :y => y}
|
131
|
+
bn = basename + Kernel.sprintf(append_filenames, img_attrs)
|
132
|
+
fn = File.join(output_dirname, "#{bn}.png")
|
133
|
+
img_out = img.resample_nearest_neighbor(x, y)
|
134
|
+
|
135
|
+
unless force_overwrite
|
136
|
+
raise "File exists: #{fn}" if File.exist?(fn)
|
137
|
+
end
|
138
|
+
|
139
|
+
IO.write(fn, img_out)
|
140
|
+
end
|
141
|
+
|
142
|
+
return output_dirname
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/lib/ico/version.rb
ADDED
data/lib/tasks/ico.rake
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
#require 'FileUtils' unless Object.const_defined?('FileUtils')
|
2
|
+
#
|
3
|
+
## in lib/tasks/ico.rake
|
4
|
+
#CURRENT_DIR = File.expand_path(File.dirname(__FILE__))
|
5
|
+
#LIB_DIR = File.join(CURRENT_DIR, '..')
|
6
|
+
#
|
7
|
+
#namespace :ico do
|
8
|
+
#
|
9
|
+
# desc 'Transpile to-ico/* and write to lib/to-ico.js (requires browserify npm)'
|
10
|
+
# task :transpile do
|
11
|
+
#
|
12
|
+
# # ensure remove
|
13
|
+
# output_filename = File.join(LIB_DIR, 'to-ico.js')
|
14
|
+
# ico_config = File.join(LIB_DIR, '?????browserify.config.ruby.js')
|
15
|
+
#
|
16
|
+
# # ensure remove
|
17
|
+
# FileUtils.rm_f output_filename
|
18
|
+
# raise "ERROR: could not delete previous file in output path: #{output_filename}" if File.exist?(output_filename)
|
19
|
+
#
|
20
|
+
# puts "cd to-ico && ?????"
|
21
|
+
# puts `????`
|
22
|
+
#
|
23
|
+
# # ensure exists
|
24
|
+
# raise "ERROR: could not find file in output path: #{output_filename}" unless File.exist?(output_filename)
|
25
|
+
#
|
26
|
+
# puts "ico:transpile => done; success!"
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
#
|
30
|
+
# desc 'Copy `lib/to-ico/browserify.config.ruby.js` to `to-ico/browserify/`'
|
31
|
+
# task :copy_config do
|
32
|
+
#
|
33
|
+
# # ensure remove
|
34
|
+
# output_filename = File.join(LIB_DIR, '../to-ico/browserify.config.ruby.js')
|
35
|
+
# ico_config = File.join(LIB_DIR, 'browserify/browserify.config.ruby.js')
|
36
|
+
#
|
37
|
+
# FileUtils.rm_f output_filename
|
38
|
+
# raise "ERROR: could not delete previous file in output path: #{output_filename}" if File.exist?(output_filename)
|
39
|
+
#
|
40
|
+
# FileUtils.cp(ico_config, output_filename)
|
41
|
+
#
|
42
|
+
# # ensure exists
|
43
|
+
# raise "ERROR: could not find file in output path: #{output_filename}" unless File.exist?(output_filename)
|
44
|
+
#
|
45
|
+
# puts "ico:copy_config => done; success!"
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
#end
|
metadata
ADDED
@@ -0,0 +1,236 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ico
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- So Awesome Man
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-04-02 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.3.8
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.3.8
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bit-struct
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.15.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.15.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bmp-ruby
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.1.1
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.1.1
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.10'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5.10'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: hoe-yard
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.1.3
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.1.3
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: hoe-ignore
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: hoe-bundler
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.2'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.2'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: hoe-gemspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: hoe-git
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1.6'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '1.6'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: yard
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.8'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0.8'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: redcarpet
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '3.3'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '3.3'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: hoe
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '3.16'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '3.16'
|
181
|
+
description: ICO file format in Ruby
|
182
|
+
email: support@bordee.com
|
183
|
+
executables: []
|
184
|
+
extensions: []
|
185
|
+
extra_rdoc_files:
|
186
|
+
- History.txt
|
187
|
+
- Manifest.txt
|
188
|
+
- README.md
|
189
|
+
files:
|
190
|
+
- ".autotest"
|
191
|
+
- ".gitignore"
|
192
|
+
- ".hoeignore"
|
193
|
+
- Gemfile
|
194
|
+
- History.txt
|
195
|
+
- LICENSE
|
196
|
+
- Manifest.txt
|
197
|
+
- README.md
|
198
|
+
- Rakefile
|
199
|
+
- lib/core_ext/array/extract_options.rb
|
200
|
+
- lib/ico.rb
|
201
|
+
- lib/ico/icon_dir.rb
|
202
|
+
- lib/ico/icon_dir_entry.rb
|
203
|
+
- lib/ico/icon_image.rb
|
204
|
+
- lib/ico/utils.rb
|
205
|
+
- lib/ico/version.rb
|
206
|
+
- lib/tasks/ico.rake
|
207
|
+
homepage: https://github.com/bordeeinc/ico
|
208
|
+
licenses:
|
209
|
+
- MIT
|
210
|
+
metadata: {}
|
211
|
+
post_install_message:
|
212
|
+
rdoc_options:
|
213
|
+
- "--title"
|
214
|
+
- ico
|
215
|
+
- "--markup"
|
216
|
+
- markdown
|
217
|
+
- "--quiet"
|
218
|
+
require_paths:
|
219
|
+
- lib
|
220
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
221
|
+
requirements:
|
222
|
+
- - ">="
|
223
|
+
- !ruby/object:Gem::Version
|
224
|
+
version: 1.9.2
|
225
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - ">="
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
230
|
+
requirements: []
|
231
|
+
rubyforge_project:
|
232
|
+
rubygems_version: 2.2.5
|
233
|
+
signing_key:
|
234
|
+
specification_version: 4
|
235
|
+
summary: ICO file format in Ruby
|
236
|
+
test_files: []
|