ase 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +52 -0
- data/Rakefile +1 -0
- data/ase.gemspec +26 -0
- data/examples/control.php +114 -0
- data/examples/simple.rb +20 -0
- data/lib/ase.rb +39 -0
- data/lib/ase/color.rb +53 -0
- data/lib/ase/file.rb +71 -0
- data/lib/ase/palette.rb +37 -0
- data/lib/ase/reader.rb +75 -0
- data/lib/ase/version.rb +3 -0
- data/lib/ase/writer.rb +62 -0
- data/spec/ase_spec.rb +94 -0
- data/spec/file_spec.rb +91 -0
- data/spec/files/control.ase +0 -0
- data/spec/spec_helper.rb +16 -0
- metadata +140 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a8f02ed546d29cb98fc1e48ec4327a551d544fad
|
4
|
+
data.tar.gz: 3e8545e46be2158f2040eb42dda2368402cf04dd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6aa291a962d1d474d722d184bf802327e97590307b3b0e01b97679137c5fe98f60725f2b4731ef54ed41531930b403abeccbd421a203e944f90a01d12cb2dea0
|
7
|
+
data.tar.gz: 0acd8002bd0f69550c86d7627de4bfb5921032b56419244bf01def81ca2a308a37e4c6d141bea26e922f93b6ba30afb8c574c247d4ca16a52ade887bd181803c
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Ryan LeFevre
|
2
|
+
|
3
|
+
MIT License
|
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
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# ASE.rb
|
2
|
+
|
3
|
+
A general purpose library for reading and writing Adobe Swatch Exchange files in Ruby. ASE files can be used across the entire Adobe Creative Suite (Photoshop, Illustrator, etc).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'ase'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install ase
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
**Writing**
|
22
|
+
|
23
|
+
``` ruby
|
24
|
+
doc = ASE.new
|
25
|
+
|
26
|
+
palette = ASE::Palette.new('My Colors')
|
27
|
+
palette.add 'Black', ASE::Color.new(0, 0, 0)
|
28
|
+
palette.add 'Red', ASE::Color.from_hex('#ff0000')
|
29
|
+
|
30
|
+
doc << palette
|
31
|
+
doc.to_file('path/to/file.ase')
|
32
|
+
```
|
33
|
+
|
34
|
+
**Reading**
|
35
|
+
|
36
|
+
``` ruby
|
37
|
+
doc = ASE.from_file('path/to/file.ase')
|
38
|
+
|
39
|
+
puts doc['My Colors']['Red'].to_rgb
|
40
|
+
#=> [255, 0, 0]
|
41
|
+
|
42
|
+
puts doc['My Colors'].size
|
43
|
+
#=> 2
|
44
|
+
```
|
45
|
+
|
46
|
+
## Contributing
|
47
|
+
|
48
|
+
1. Fork it
|
49
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
50
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
51
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
52
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/ase.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ase/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ase"
|
8
|
+
spec.version = ASE::VERSION
|
9
|
+
spec.authors = ["Ryan LeFevre"]
|
10
|
+
spec.email = ["meltingice8917@gmail.com"]
|
11
|
+
spec.description = %q{Reader/writer for Adobe Swatch Exchange files}
|
12
|
+
spec.summary = %q{Reader/writer for Adobe Swatch Exchange files. Can be used across the entire Adobe Creative Suite.}
|
13
|
+
spec.homepage = "http://cosmos.layervault.com/aserb.html"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "guard"
|
24
|
+
spec.add_development_dependency "guard-rspec"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
<?php
|
2
|
+
/**
|
3
|
+
* Make an Adobe Swatch Exchange file
|
4
|
+
*
|
5
|
+
* @param array
|
6
|
+
* @return string
|
7
|
+
* @see http://www.colourlovers.com/web/blog/2007/11/08/color-palettes-in-adobe-swatch-exchange-ase
|
8
|
+
* @author Chris Williams - http://www.colourlovers.com
|
9
|
+
* @version 2.0
|
10
|
+
* This script uses the Multibyte String extension: http://www.php.net/manual/en/book.mbstring.php
|
11
|
+
* MIT License
|
12
|
+
* Copyright (c) 2011 Chris Williams - http://www.colourlovers.com
|
13
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
14
|
+
* of this software and associated documentation files (the "Software"), to deal
|
15
|
+
* in the Software without restriction, including without limitation the rights
|
16
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
17
|
+
* copies of the Software, and to permit persons to whom the Software is
|
18
|
+
* furnished to do so, subject to the following conditions:
|
19
|
+
* The above copyright notice and this permission notice shall be included in
|
20
|
+
* all copies or substantial portions of the Software.
|
21
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
22
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
23
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
24
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
25
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
26
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
27
|
+
* THE SOFTWARE.
|
28
|
+
*/
|
29
|
+
function mkASE($palettes) {
|
30
|
+
$internal_encoding = mb_internal_encoding();
|
31
|
+
mb_internal_encoding("UTF-8");
|
32
|
+
|
33
|
+
ob_start();
|
34
|
+
|
35
|
+
$totalColors = $numPalettes = 0;
|
36
|
+
|
37
|
+
foreach ($palettes as $palette) {
|
38
|
+
$totalColors += count($palette["colors"]);
|
39
|
+
++$numPalettes;
|
40
|
+
}
|
41
|
+
|
42
|
+
echo "ASEF"; # File signature
|
43
|
+
echo pack("n*",1,0); # Version
|
44
|
+
echo pack("N",$totalColors + ($numPalettes * 2)); # Total number of blocks
|
45
|
+
|
46
|
+
foreach ($palettes as $palette) {
|
47
|
+
echo pack("n",0xC001); # Group start
|
48
|
+
|
49
|
+
# Length of this block - see below
|
50
|
+
|
51
|
+
$title = (mb_convert_encoding($palette["title"],"UTF-16BE","UTF-8") . pack("n",0));
|
52
|
+
$buffer = pack("n",(strlen($title) / 2)); # Length of the group title
|
53
|
+
$buffer .= $title; # Group title
|
54
|
+
|
55
|
+
echo pack("N",strlen($buffer)); # Length of this block
|
56
|
+
echo $buffer;
|
57
|
+
|
58
|
+
foreach ($palette["colors"] as $color) {
|
59
|
+
echo pack("n",1); # Color entry
|
60
|
+
|
61
|
+
# Length of this block - see below
|
62
|
+
|
63
|
+
$title = (mb_convert_encoding($color[1],"UTF-16BE","UTF-8") . pack("n",0));
|
64
|
+
$buffer = pack("n",(strlen($title) / 2)); # Length of the title
|
65
|
+
$buffer .= $title; # Title
|
66
|
+
|
67
|
+
# Colors
|
68
|
+
list ($r,$g,$b) = array_map("intval",sscanf($color[0],"%2x%2x%2x"));
|
69
|
+
$r /= 255;
|
70
|
+
$g /= 255;
|
71
|
+
$b /= 255;
|
72
|
+
|
73
|
+
$buffer .= "RGB ";
|
74
|
+
$buffer .= strrev(pack("f",$r));
|
75
|
+
$buffer .= strrev(pack("f",$g));
|
76
|
+
$buffer .= strrev(pack("f",$b));
|
77
|
+
$buffer .= pack("n",0); # Color type - 0x00 "Global"
|
78
|
+
|
79
|
+
echo pack("N",strlen($buffer)); # Length of this block
|
80
|
+
echo $buffer;
|
81
|
+
}
|
82
|
+
echo pack("n",0xC002); # Group end
|
83
|
+
|
84
|
+
echo pack("N",0); # Length of "Group end" block, which is 0
|
85
|
+
}
|
86
|
+
|
87
|
+
$return = ob_get_contents();
|
88
|
+
ob_end_clean();
|
89
|
+
|
90
|
+
mb_internal_encoding($internal_encoding);
|
91
|
+
|
92
|
+
return $return;
|
93
|
+
}
|
94
|
+
|
95
|
+
/*
|
96
|
+
Colors from the Palettes:
|
97
|
+
Vintage Modern http://www.colourlovers.com/palette/110225/Vintage_Modern
|
98
|
+
Thought Provoking http://www.colourlovers.com/palette/694737/Thought_Provoking
|
99
|
+
|
100
|
+
Licensed under Creative Commons: http://creativecommons.org/licenses/by-nc-sa/3.0/
|
101
|
+
*/
|
102
|
+
|
103
|
+
$palettes = array (
|
104
|
+
array (
|
105
|
+
"title" => "Simple",
|
106
|
+
"colors" => array (
|
107
|
+
array ("FFFFFF","White"),
|
108
|
+
array ("000000","Black"),
|
109
|
+
),
|
110
|
+
),
|
111
|
+
);
|
112
|
+
|
113
|
+
$ase = mkASE($palettes);
|
114
|
+
file_put_contents('./control.ase', $ase);
|
data/examples/simple.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require './lib/ase'
|
3
|
+
|
4
|
+
doc = ASE.new
|
5
|
+
|
6
|
+
palette = ASE::Palette.new("Simple")
|
7
|
+
palette.add 'White', ASE::Color.from_hex('#ffffff')
|
8
|
+
palette.add 'Black', ASE::Color.from_hex('#000000')
|
9
|
+
|
10
|
+
doc << palette
|
11
|
+
|
12
|
+
puts "\nTO FILE"
|
13
|
+
pp doc
|
14
|
+
|
15
|
+
doc.to_file './output.ase'
|
16
|
+
|
17
|
+
puts "\nFROM FILE"
|
18
|
+
doc2 = ASE.from_file './output.ase'
|
19
|
+
|
20
|
+
pp doc2
|
data/lib/ase.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
dir_root = File.dirname(File.absolute_path(__FILE__))
|
2
|
+
|
3
|
+
require dir_root + "/ase/version"
|
4
|
+
require dir_root + "/ase/color"
|
5
|
+
require dir_root + "/ase/file"
|
6
|
+
require dir_root + "/ase/palette"
|
7
|
+
require dir_root + "/ase/reader"
|
8
|
+
require dir_root + "/ase/writer"
|
9
|
+
|
10
|
+
|
11
|
+
class ASE
|
12
|
+
include Reader
|
13
|
+
include Writer
|
14
|
+
|
15
|
+
attr_accessor :palettes
|
16
|
+
|
17
|
+
def initialize(file=nil)
|
18
|
+
@file = file
|
19
|
+
@palettes = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_palette(palette)
|
23
|
+
raise "Can only pass an ASE::Palette" unless palette.is_a?(ASE::Palette)
|
24
|
+
@palettes[palette.name] = palette
|
25
|
+
end
|
26
|
+
alias :<< :add_palette
|
27
|
+
|
28
|
+
def [](name)
|
29
|
+
@palettes[name]
|
30
|
+
end
|
31
|
+
|
32
|
+
def method_missing(method, *args, &block)
|
33
|
+
if @palettes.has_key?(method.to_s)
|
34
|
+
return @palettes[method.to_s]
|
35
|
+
end
|
36
|
+
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
data/lib/ase/color.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# Nice little wrapper that lets us easily perform some functions on a
|
2
|
+
# given color.
|
3
|
+
class ASE
|
4
|
+
class Color
|
5
|
+
class << self
|
6
|
+
def from_rgba(*args)
|
7
|
+
args = args.first if args.length == 1
|
8
|
+
self.new *args
|
9
|
+
end
|
10
|
+
alias :from_rgb :from_rgba
|
11
|
+
|
12
|
+
def from_hex(hex)
|
13
|
+
self.new *hex.gsub('#', '').scan(/../).map { |c| c.to_i(16) }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_accessor :r, :g, :b, :a
|
18
|
+
|
19
|
+
# We always internally store the color as RGBA.
|
20
|
+
def initialize(r, g, b, a = 255)
|
21
|
+
@r = r
|
22
|
+
@g = g
|
23
|
+
@b = b
|
24
|
+
@a = a
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_rgba
|
28
|
+
[@r, @g, @b, @a]
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_rgb
|
32
|
+
[@r, @g, @b]
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_css
|
36
|
+
"rgba(#{r}, #{g}, #{b}, #{a})"
|
37
|
+
end
|
38
|
+
|
39
|
+
def [](i)
|
40
|
+
[@r, @g, @b, @a][i]
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_hex(incl_hash=true, incl_alpha=false)
|
44
|
+
hex = incl_hash ? '#' : ''
|
45
|
+
colors = [@r, @g, @b]
|
46
|
+
colors << @a if incl_alpha
|
47
|
+
|
48
|
+
colors.each { |c| hex << c.to_s(16) }
|
49
|
+
return hex
|
50
|
+
end
|
51
|
+
alias :to_s :to_hex
|
52
|
+
end
|
53
|
+
end
|
data/lib/ase/file.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
class ASE
|
2
|
+
class File < ::File
|
3
|
+
FORMATS = {
|
4
|
+
ulonglong: {
|
5
|
+
length: 8,
|
6
|
+
code: 'Q>'
|
7
|
+
},
|
8
|
+
longlong: {
|
9
|
+
length: 8,
|
10
|
+
code: 'q>'
|
11
|
+
},
|
12
|
+
double: {
|
13
|
+
length: 8,
|
14
|
+
code: 'G'
|
15
|
+
},
|
16
|
+
float: {
|
17
|
+
length: 4,
|
18
|
+
code: 'F'
|
19
|
+
},
|
20
|
+
uint: {
|
21
|
+
length: 4,
|
22
|
+
code: 'L>'
|
23
|
+
},
|
24
|
+
int: {
|
25
|
+
length: 4,
|
26
|
+
code: 'l>'
|
27
|
+
},
|
28
|
+
ushort: {
|
29
|
+
length: 2,
|
30
|
+
code: 'S>'
|
31
|
+
},
|
32
|
+
short: {
|
33
|
+
length: 2,
|
34
|
+
code: 's>'
|
35
|
+
},
|
36
|
+
ulong: {
|
37
|
+
length: 4,
|
38
|
+
code: 'L>'
|
39
|
+
},
|
40
|
+
long: {
|
41
|
+
length: 4,
|
42
|
+
code: 'l>'
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
FORMATS.each do |format, info|
|
47
|
+
define_method "read_#{format}" do
|
48
|
+
read(info[:length]).unpack(info[:code])[0]
|
49
|
+
end
|
50
|
+
|
51
|
+
define_method "write_#{format}" do |*args|
|
52
|
+
write args.pack(info[:code] + '*')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def read_string
|
57
|
+
length = read_ushort
|
58
|
+
read(length * 2).encode('UTF-8', 'UTF-16BE').delete("\00")
|
59
|
+
end
|
60
|
+
|
61
|
+
def write_string(string)
|
62
|
+
write_ushort(string.length + 1)
|
63
|
+
write string.encode('UTF-16BE')
|
64
|
+
write_null_byte
|
65
|
+
end
|
66
|
+
|
67
|
+
def write_null_byte
|
68
|
+
write [0].pack('S>')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/ase/palette.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
class ASE
|
2
|
+
class Palette
|
3
|
+
attr_accessor :name, :colors
|
4
|
+
|
5
|
+
def initialize(name)
|
6
|
+
@name = name
|
7
|
+
@colors = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def add(name, color)
|
11
|
+
@colors[name] = color
|
12
|
+
end
|
13
|
+
alias :[]= :add
|
14
|
+
alias :add_color :add
|
15
|
+
|
16
|
+
def remove(name)
|
17
|
+
@colors.delete(name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def [](i)
|
21
|
+
@colors[i]
|
22
|
+
end
|
23
|
+
|
24
|
+
def length
|
25
|
+
@colors.length
|
26
|
+
end
|
27
|
+
alias :size :length
|
28
|
+
|
29
|
+
def method_missing(method, *args, &block)
|
30
|
+
if @colors.has_key?(method.to_s)
|
31
|
+
return @colors[method.to_s]
|
32
|
+
end
|
33
|
+
|
34
|
+
super
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/ase/reader.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
class ASE
|
2
|
+
module Reader
|
3
|
+
def self.included(base)
|
4
|
+
base.send :include, InstanceMethods
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def from_file(file)
|
10
|
+
doc = ASE.new(file)
|
11
|
+
doc.read!
|
12
|
+
|
13
|
+
return doc
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module InstanceMethods
|
18
|
+
def from_file(file)
|
19
|
+
@file = file
|
20
|
+
read!
|
21
|
+
end
|
22
|
+
|
23
|
+
def read!
|
24
|
+
raise "Must specify an output file" if @file.nil?
|
25
|
+
@file = File.new(@file, 'rb')
|
26
|
+
|
27
|
+
# Signature and version, who cares?
|
28
|
+
# Okay maybe we should validate this in the future.
|
29
|
+
@file.seek 8, IO::SEEK_CUR
|
30
|
+
|
31
|
+
block_count = @file.read_ulong
|
32
|
+
|
33
|
+
read_palette until @file.eof?
|
34
|
+
|
35
|
+
@file.close
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def read_palette
|
41
|
+
block_start = @file.read_ushort
|
42
|
+
|
43
|
+
title_block_size = @file.read_ulong
|
44
|
+
title = @file.read_string
|
45
|
+
|
46
|
+
palette = Palette.new(title)
|
47
|
+
|
48
|
+
# Read the colors
|
49
|
+
while true
|
50
|
+
color_start = @file.read_ushort
|
51
|
+
break if color_start == 0xC002
|
52
|
+
|
53
|
+
color_size = @file.read_ulong
|
54
|
+
color_name = @file.read_string
|
55
|
+
color_mode = @file.read(4)
|
56
|
+
|
57
|
+
r, g, b = @file.read(12).scan(/.{1,4}/).map do |c|
|
58
|
+
(c.reverse.unpack('F')[0] * 255).to_i
|
59
|
+
end
|
60
|
+
|
61
|
+
palette.add color_name, Color.new(r, g, b)
|
62
|
+
|
63
|
+
# Null byte
|
64
|
+
@file.seek 2, IO::SEEK_CUR
|
65
|
+
end
|
66
|
+
|
67
|
+
# Group end block
|
68
|
+
@file.seek 4, IO::SEEK_CUR
|
69
|
+
|
70
|
+
add_palette palette
|
71
|
+
return true
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/ase/version.rb
ADDED
data/lib/ase/writer.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
class ASE
|
2
|
+
module Writer
|
3
|
+
def to_file(file)
|
4
|
+
@file = file
|
5
|
+
write!
|
6
|
+
end
|
7
|
+
|
8
|
+
def write!
|
9
|
+
raise "Must specify an output file" if @file.nil?
|
10
|
+
@file = File.new(@file, 'wb')
|
11
|
+
|
12
|
+
palette_count = @palettes.length
|
13
|
+
color_count = @palettes.inject(0) { |sum, p| p.size }
|
14
|
+
|
15
|
+
# Signature
|
16
|
+
@file.write "ASEF"
|
17
|
+
|
18
|
+
# Version
|
19
|
+
@file.write_ushort 1, 0
|
20
|
+
|
21
|
+
# Number of blocks
|
22
|
+
@file.write_ulong(color_count + (palette_count * 2))
|
23
|
+
|
24
|
+
@palettes.each do |palette_name, palette|
|
25
|
+
# Block start
|
26
|
+
@file.write_ushort 0xC001
|
27
|
+
|
28
|
+
# Block length (title is UTF-16 encoded)
|
29
|
+
@file.write_ulong 4 + (palette_name.length * 2)
|
30
|
+
|
31
|
+
# Palette name
|
32
|
+
@file.write_string palette_name
|
33
|
+
|
34
|
+
palette.colors.each do |name, color|
|
35
|
+
# Color start
|
36
|
+
@file.write_ushort 1
|
37
|
+
|
38
|
+
# Block length
|
39
|
+
@file.write_ulong 22 + (name.length * 2)
|
40
|
+
|
41
|
+
# Color name
|
42
|
+
@file.write_string name
|
43
|
+
|
44
|
+
# Color mode
|
45
|
+
@file.write 'RGB '
|
46
|
+
|
47
|
+
# Colors
|
48
|
+
rgb = color.to_rgb.map { |c| c / 255 }
|
49
|
+
rgb.each { |c| @file.write [c].pack('F').reverse }
|
50
|
+
|
51
|
+
# End of colors
|
52
|
+
@file.write_null_byte
|
53
|
+
end
|
54
|
+
|
55
|
+
@file.write_ushort 0xC002 # Group end
|
56
|
+
@file.write_ulong 0 # Group end block
|
57
|
+
end
|
58
|
+
|
59
|
+
@file.close
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/spec/ase_spec.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ASE do
|
4
|
+
before(:each) do
|
5
|
+
@doc = ASE.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it "is initialized with defaults" do
|
9
|
+
expect(@doc.palettes).to eq({})
|
10
|
+
expect(@doc.palettes.length).to be 0
|
11
|
+
end
|
12
|
+
|
13
|
+
it "can add palettes" do
|
14
|
+
@doc.add_palette ASE::Palette.new('Test')
|
15
|
+
@doc << ASE::Palette.new('Also Test')
|
16
|
+
end
|
17
|
+
|
18
|
+
describe ASE::Palette do
|
19
|
+
it "must have a name" do
|
20
|
+
expect {
|
21
|
+
ASE::Palette.new
|
22
|
+
}.to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
it "is initialized with proper defaults" do
|
26
|
+
palette = ASE::Palette.new('Test')
|
27
|
+
|
28
|
+
expect(palette.name).to eq('Test')
|
29
|
+
expect(palette.colors).to eq({})
|
30
|
+
end
|
31
|
+
|
32
|
+
it "can add and remove colors" do
|
33
|
+
palette = ASE::Palette.new('Test')
|
34
|
+
color = ASE::Color.new(255, 255, 255)
|
35
|
+
|
36
|
+
palette.add 'White', color
|
37
|
+
expect(palette.colors).to eq({
|
38
|
+
'White' => color
|
39
|
+
})
|
40
|
+
|
41
|
+
palette.remove 'White'
|
42
|
+
expect(palette.colors).to eq({})
|
43
|
+
end
|
44
|
+
|
45
|
+
it '#length returns the number of colors' do
|
46
|
+
palette = ASE::Palette.new('Test')
|
47
|
+
palette.add 'White', ASE::Color.new(255, 255, 255)
|
48
|
+
palette.add 'Black', ASE::Color.new(0, 0, 0)
|
49
|
+
|
50
|
+
expect(palette.length).to be 2
|
51
|
+
expect(palette.size).to be 2
|
52
|
+
end
|
53
|
+
|
54
|
+
it '#[] lets you access a specific color' do
|
55
|
+
palette = ASE::Palette.new('Test')
|
56
|
+
color = ASE::Color.new(255, 255, 255)
|
57
|
+
|
58
|
+
palette.add 'White', color
|
59
|
+
expect(palette['White']).to be color
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe ASE::Color do
|
64
|
+
it 'must be initialized with all RGB channels' do
|
65
|
+
expect {
|
66
|
+
ASE::Color.new
|
67
|
+
}.to raise_error
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'sets a proper default for the alpha channel' do
|
71
|
+
color = ASE::Color.new(0, 0, 0)
|
72
|
+
expect(color.a).to be 255
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'can be created with an RGB array' do
|
76
|
+
color1 = ASE::Color.from_rgba [0, 0, 0]
|
77
|
+
color2 = ASE::Color.from_rgb [0, 0, 0]
|
78
|
+
|
79
|
+
expect(color1.to_rgba).to eq([0, 0, 0, 255])
|
80
|
+
expect(color2.to_rgba).to eq([0, 0, 0, 255])
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'can be created from a hex value' do
|
84
|
+
color1 = ASE::Color.from_hex('#000000')
|
85
|
+
color2 = ASE::Color.from_hex('000000')
|
86
|
+
color3 = ASE::Color.from_hex('#00000000')
|
87
|
+
|
88
|
+
rgba = [0, 0, 0, 255]
|
89
|
+
expect(color1.to_rgba).to eq(rgba)
|
90
|
+
expect(color2.to_rgba).to eq(rgba)
|
91
|
+
expect(color3.to_rgba).to eq([0, 0, 0, 0])
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/spec/file_spec.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
describe 'Files' do
|
5
|
+
describe 'Reading' do
|
6
|
+
it 'throws an error if file is not set' do
|
7
|
+
doc = ASE.new
|
8
|
+
|
9
|
+
expect {
|
10
|
+
doc.read!
|
11
|
+
}.to raise_error
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'can read via factory or instantiation' do
|
15
|
+
doc1 = ASE.from_file('spec/files/control.ase')
|
16
|
+
expect(doc1.palettes.length).to be 1
|
17
|
+
|
18
|
+
doc2 = ASE.new('spec/files/control.ase')
|
19
|
+
doc2.read!
|
20
|
+
expect(doc2.palettes.length).to be 1
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'properly reads the palette name' do
|
24
|
+
doc = ASE.from_file('spec/files/control.ase')
|
25
|
+
expect(doc.palettes).to have_key('Simple')
|
26
|
+
expect(doc['Simple']).to eq(doc.palettes['Simple'])
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'reads the correct number of colors' do
|
30
|
+
doc = ASE.from_file('spec/files/control.ase')
|
31
|
+
expect(doc['Simple'].size).to be 2
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'correctly reads the color names' do
|
35
|
+
doc = ASE.from_file('spec/files/control.ase')
|
36
|
+
expect(doc['Simple'].colors).to have_key('White')
|
37
|
+
expect(doc['Simple'].colors).to have_key('Black')
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'correctly reads the color values' do
|
41
|
+
doc = ASE.from_file('spec/files/control.ase')
|
42
|
+
expect(doc['Simple']['White'].to_rgb).to eq([255, 255, 255])
|
43
|
+
expect(doc['Simple']['Black'].to_rgb).to eq([0, 0, 0])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'Writing' do
|
48
|
+
before(:each) do
|
49
|
+
doc = ASE.new
|
50
|
+
|
51
|
+
palette = ASE::Palette.new('Test')
|
52
|
+
palette.add 'Red', ASE::Color.new(255, 0, 0)
|
53
|
+
palette.add 'Blue', ASE::Color.new(0, 0, 255)
|
54
|
+
|
55
|
+
doc << palette
|
56
|
+
|
57
|
+
@output = Tempfile.new('output.ase')
|
58
|
+
doc.to_file @output.path
|
59
|
+
end
|
60
|
+
|
61
|
+
after(:each) do
|
62
|
+
@output.unlink
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'writes data to the output file' do
|
66
|
+
expect(@output.size).to be > 0
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'properly writes the palette name' do
|
70
|
+
d = ASE.from_file(@output.path)
|
71
|
+
expect(d.palettes).to have_key('Test')
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'writes the correct number of colors' do
|
75
|
+
d = ASE.from_file(@output.path)
|
76
|
+
expect(d['Test'].size).to be 2
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'writes the correct color names' do
|
80
|
+
d = ASE.from_file(@output.path)
|
81
|
+
expect(d['Test'].colors).to have_key('Red')
|
82
|
+
expect(d['Test'].colors).to have_key('Blue')
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'writes the correct color values' do
|
86
|
+
d = ASE.from_file(@output.path)
|
87
|
+
expect(d['Test']['Red'].to_rgb).to eq([255, 0, 0])
|
88
|
+
expect(d['Test']['Blue'].to_rgb).to eq([0, 0, 255])
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
Binary file
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require './lib/ase'
|
2
|
+
|
3
|
+
RSpec.configure do |config|
|
4
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
5
|
+
config.run_all_when_everything_filtered = true
|
6
|
+
|
7
|
+
unless ENV['CIRCLECI']
|
8
|
+
config.filter_run :focus
|
9
|
+
end
|
10
|
+
|
11
|
+
# Run specs in random order to surface order dependencies. If you find an
|
12
|
+
# order dependency and want to debug it, you can fix the order by providing
|
13
|
+
# the seed, which is printed after each run.
|
14
|
+
# --seed 1234
|
15
|
+
config.order = 'random'
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ase
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan LeFevre
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-07-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: guard
|
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
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: guard-rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Reader/writer for Adobe Swatch Exchange files
|
84
|
+
email:
|
85
|
+
- meltingice8917@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- .gitignore
|
91
|
+
- .rspec
|
92
|
+
- Gemfile
|
93
|
+
- Guardfile
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- ase.gemspec
|
98
|
+
- examples/control.php
|
99
|
+
- examples/simple.rb
|
100
|
+
- lib/ase.rb
|
101
|
+
- lib/ase/color.rb
|
102
|
+
- lib/ase/file.rb
|
103
|
+
- lib/ase/palette.rb
|
104
|
+
- lib/ase/reader.rb
|
105
|
+
- lib/ase/version.rb
|
106
|
+
- lib/ase/writer.rb
|
107
|
+
- spec/ase_spec.rb
|
108
|
+
- spec/file_spec.rb
|
109
|
+
- spec/files/control.ase
|
110
|
+
- spec/spec_helper.rb
|
111
|
+
homepage: http://cosmos.layervault.com/aserb.html
|
112
|
+
licenses:
|
113
|
+
- MIT
|
114
|
+
metadata: {}
|
115
|
+
post_install_message:
|
116
|
+
rdoc_options: []
|
117
|
+
require_paths:
|
118
|
+
- lib
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 2.0.3
|
132
|
+
signing_key:
|
133
|
+
specification_version: 4
|
134
|
+
summary: Reader/writer for Adobe Swatch Exchange files. Can be used across the entire
|
135
|
+
Adobe Creative Suite.
|
136
|
+
test_files:
|
137
|
+
- spec/ase_spec.rb
|
138
|
+
- spec/file_spec.rb
|
139
|
+
- spec/files/control.ase
|
140
|
+
- spec/spec_helper.rb
|