psd 1.2.2 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +22 -0
- data/lib/psd/file.rb +1 -1
- data/lib/psd/helpers.rb +4 -0
- data/lib/psd/layer.rb +1 -0
- data/lib/psd/layer_info/metadata_setting.rb +35 -0
- data/lib/psd/layer_info/typetool.rb +1 -1
- data/lib/psd/node.rb +5 -1
- data/lib/psd/node_group.rb +6 -0
- data/lib/psd/node_layer.rb +6 -6
- data/lib/psd/node_root.rb +3 -1
- data/lib/psd/nodes/search.rb +35 -0
- data/lib/psd/resources/layer_comps.rb +4 -0
- data/lib/psd/version.rb +1 -1
- data/spec/hierarchy_spec.rb +17 -0
- data/spec/parsing_spec.rb +13 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d04a7ff525ba486c5d37f11d89b6106c5ae9960a
|
4
|
+
data.tar.gz: 8993d2ce5b328983e55ee77a1ba6297afc37ad0a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5da04951ba02c95f1770574a70258736033ff3b9d8b74ede4873592c3ac102fe7972372df4e5ae8f5279d5044c7a475ac5f7de5e86611769d9db59234edf693
|
7
|
+
data.tar.gz: c2e37f8843ff642688c8ea136e28821c51ba8f964368026968301a69046eee757b7b4e48480fe91ff43bd18542d95814046fef9c07cee604aa6f25ad3466393f
|
data/README.md
CHANGED
@@ -15,6 +15,7 @@ A general purpose Photoshop file parser written in Ruby. It allows you to work w
|
|
15
15
|
* Color mode and bit-depth
|
16
16
|
* Vector mask data
|
17
17
|
* Flattened image data
|
18
|
+
* Layer comps
|
18
19
|
|
19
20
|
PSD.rb is tested against:
|
20
21
|
|
@@ -90,6 +91,27 @@ For any of the traversal methods, you can also retrieve folder or layer nodes on
|
|
90
91
|
psd.tree.descendant_layers
|
91
92
|
```
|
92
93
|
|
94
|
+
If you know the path to a group or layer within the tree, you can search by that path. Note that this always returns an Array because layer/group names do not have to be unique.
|
95
|
+
|
96
|
+
``` ruby
|
97
|
+
psd.tree.children_at_path("Version A/Matte")
|
98
|
+
```
|
99
|
+
|
100
|
+
**Layer Comps**
|
101
|
+
|
102
|
+
You can also filter nodes based on a layer comp. To generate a new tree consisting only of the layers that are enabled in a certain layer comp:
|
103
|
+
|
104
|
+
``` ruby
|
105
|
+
# Get information about all the available layer comps
|
106
|
+
puts psd.layer_comps
|
107
|
+
|
108
|
+
# Can filter by name or by ID (obtained from above)
|
109
|
+
tree = psd.tree.filter_by_comp('Version A')
|
110
|
+
puts tree.children.map(&:name)
|
111
|
+
```
|
112
|
+
|
113
|
+
This returns a new node tree and does not alter the original so you won't lose any data.
|
114
|
+
|
93
115
|
**Accessing Layer Data**
|
94
116
|
|
95
117
|
To get data such as the name or dimensions of a layer:
|
data/lib/psd/file.rb
CHANGED
data/lib/psd/helpers.rb
CHANGED
data/lib/psd/layer.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative '../layer_info'
|
2
|
+
|
3
|
+
class PSD
|
4
|
+
class MetadataSetting < LayerInfo
|
5
|
+
@key = 'shmd'
|
6
|
+
|
7
|
+
def parse
|
8
|
+
count = @file.read_int
|
9
|
+
|
10
|
+
count.times do
|
11
|
+
@file.seek 4, IO::SEEK_CUR # signature, always 8BIM
|
12
|
+
|
13
|
+
key = @file.read_string(4)
|
14
|
+
copy_on_sheet_dup = @file.read(1).bytes.to_a[0]
|
15
|
+
@file.seek 3, IO::SEEK_CUR # Padding
|
16
|
+
|
17
|
+
len = @file.read_int
|
18
|
+
data_end = @file.tell + len
|
19
|
+
|
20
|
+
PSD.logger.debug "Layer metadata: key = #{key}, length = #{len}"
|
21
|
+
|
22
|
+
parse_layer_comp_setting if key == 'cmls'
|
23
|
+
|
24
|
+
@file.seek data_end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def parse_layer_comp_setting
|
31
|
+
@file.seek 4, IO::SEEK_CUR # Version
|
32
|
+
@data[:layer_comp] = Descriptor.new(@file).parse
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/psd/node.rb
CHANGED
@@ -11,7 +11,7 @@ class PSD
|
|
11
11
|
# Default properties that all nodes contain
|
12
12
|
PROPERTIES = [:name, :left, :right, :top, :bottom, :height, :width]
|
13
13
|
|
14
|
-
attr_accessor :parent, :children
|
14
|
+
attr_accessor :parent, :children, :layer
|
15
15
|
|
16
16
|
def initialize(layers=[])
|
17
17
|
@children = []
|
@@ -29,6 +29,10 @@ class PSD
|
|
29
29
|
@layer.visible?
|
30
30
|
end
|
31
31
|
|
32
|
+
def psd
|
33
|
+
parent.psd
|
34
|
+
end
|
35
|
+
|
32
36
|
def layer?
|
33
37
|
is_a?(PSD::Node::Layer)
|
34
38
|
end
|
data/lib/psd/node_group.rb
CHANGED
@@ -55,6 +55,12 @@ class PSD::Node
|
|
55
55
|
})
|
56
56
|
end
|
57
57
|
|
58
|
+
# If the method is missing, we blindly send it to the layer.
|
59
|
+
# The layer handles the case in which the method doesn't exist.
|
60
|
+
def method_missing(method, *args, &block)
|
61
|
+
@layer.send(method, *args, &block)
|
62
|
+
end
|
63
|
+
|
58
64
|
private
|
59
65
|
|
60
66
|
def get_dimensions
|
data/lib/psd/node_layer.rb
CHANGED
@@ -25,12 +25,6 @@ class PSD::Node
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
# If the method is missing, we blindly send it to the layer.
|
29
|
-
# The layer handles the case in which the method doesn't exist.
|
30
|
-
def method_missing(method, *args, &block)
|
31
|
-
layer.send(method, *args, &block)
|
32
|
-
end
|
33
|
-
|
34
28
|
# Attempt to translate the layer.
|
35
29
|
def translate(x=0, y=0)
|
36
30
|
@layer.translate x, y
|
@@ -67,5 +61,11 @@ class PSD::Node
|
|
67
61
|
ref_y: @layer.reference_point.y
|
68
62
|
})
|
69
63
|
end
|
64
|
+
|
65
|
+
# If the method is missing, we blindly send it to the layer.
|
66
|
+
# The layer handles the case in which the method doesn't exist.
|
67
|
+
def method_missing(method, *args, &block)
|
68
|
+
@layer.send(method, *args, &block)
|
69
|
+
end
|
70
70
|
end
|
71
71
|
end
|
data/lib/psd/node_root.rb
CHANGED
@@ -6,7 +6,7 @@ class PSD::Node
|
|
6
6
|
include PSD::HasChildren
|
7
7
|
include PSD::Node::ParseLayers
|
8
8
|
|
9
|
-
|
9
|
+
attr_accessor :children
|
10
10
|
|
11
11
|
# Stores a reference to the parsed PSD and builds the
|
12
12
|
# tree hierarchy.
|
@@ -51,6 +51,8 @@ class PSD::Node
|
|
51
51
|
0
|
52
52
|
end
|
53
53
|
|
54
|
+
def psd; @psd; end
|
55
|
+
|
54
56
|
private
|
55
57
|
|
56
58
|
def build_hierarchy
|
data/lib/psd/nodes/search.rb
CHANGED
@@ -23,6 +23,41 @@ class PSD
|
|
23
23
|
return matches.map { |m| m.children_at_path(path, opts) }.flatten
|
24
24
|
end
|
25
25
|
end
|
26
|
+
|
27
|
+
# Given a layer comp ID, name, or :last for last document state, create a new
|
28
|
+
# tree based on the layers/groups that belong to the comp only.
|
29
|
+
def filter_by_comp(id)
|
30
|
+
if id.is_a?(String)
|
31
|
+
comp = psd.layer_comps.select { |c| c[:name] == id }.first
|
32
|
+
raise "Layer comp not found" if comp.nil?
|
33
|
+
|
34
|
+
id = comp[:id]
|
35
|
+
elsif id == :last
|
36
|
+
id = 0
|
37
|
+
end
|
38
|
+
|
39
|
+
root = PSD::Node::Root.new(psd)
|
40
|
+
filter_for_comp!(id, root)
|
41
|
+
|
42
|
+
return root
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def filter_for_comp!(id, node)
|
48
|
+
node.children.select! do |c|
|
49
|
+
c
|
50
|
+
.metadata
|
51
|
+
.data[:layer_comp]['layerSettings'].map { |l| !l.has_key?('enab') || l['enab'] ? l['compList'] : nil }
|
52
|
+
.flatten
|
53
|
+
.compact
|
54
|
+
.include?(id)
|
55
|
+
end
|
56
|
+
|
57
|
+
node.children.each do |c|
|
58
|
+
filter_for_comp!(id, c) if c.is_a?(PSD::Node::Group)
|
59
|
+
end
|
60
|
+
end
|
26
61
|
end
|
27
62
|
end
|
28
63
|
end
|
data/lib/psd/version.rb
CHANGED
data/spec/hierarchy_spec.rb
CHANGED
@@ -86,6 +86,23 @@ describe "Hierarchy" do
|
|
86
86
|
expect(@tree.children_at_path('NOPE')).to be_an_instance_of(Array)
|
87
87
|
expect(@tree.children_at_path('NOPE').size).to eq(0)
|
88
88
|
end
|
89
|
+
|
90
|
+
it "should throw an error if filtering by a non-existant layer comp" do
|
91
|
+
expect { @tree.filter_by_comp('WAT') }.to raise_error("Layer comp not found")
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should correctly filter and produce a new tree when filtering by layer comp" do
|
95
|
+
tree = @tree.filter_by_comp('Version A')
|
96
|
+
expect(tree).to be_an_instance_of(PSD::Node::Root)
|
97
|
+
expect(tree.children.size).to eq(1)
|
98
|
+
expect(tree.children[0].name).to eq("Version A")
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should return a new tree when filtering by layer comps" do
|
102
|
+
tree = @tree.filter_by_comp('Version A')
|
103
|
+
expect(tree).to_not eq(@tree)
|
104
|
+
expect(@tree.children.size).to eq(3)
|
105
|
+
end
|
89
106
|
end
|
90
107
|
end
|
91
108
|
end
|
data/spec/parsing_spec.rb
CHANGED
@@ -131,5 +131,18 @@ describe 'Parsing' do
|
|
131
131
|
expect(blend_mode.opacity_percentage).to eq(100)
|
132
132
|
expect(blend_mode.visible).to be_true
|
133
133
|
end
|
134
|
+
|
135
|
+
it "should parse all layer comps" do
|
136
|
+
expect(@psd.layer_comps.size).to eq(3)
|
137
|
+
expect(@psd.layer_comps.map { |c| c[:name] }).to eq([
|
138
|
+
'Version A',
|
139
|
+
'Version B',
|
140
|
+
'Version C'
|
141
|
+
])
|
142
|
+
|
143
|
+
@psd.layer_comps.each do |c|
|
144
|
+
expect(c[:id]).to be > 0
|
145
|
+
end
|
146
|
+
end
|
134
147
|
end
|
135
148
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: psd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan LeFevre
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-09-
|
12
|
+
date: 2013-09-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -165,6 +165,7 @@ files:
|
|
165
165
|
- lib/psd/layer_info/layer_name_source.rb
|
166
166
|
- lib/psd/layer_info/layer_section_divider.rb
|
167
167
|
- lib/psd/layer_info/legacy_typetool.rb
|
168
|
+
- lib/psd/layer_info/metadata_setting.rb
|
168
169
|
- lib/psd/layer_info/object_effects.rb
|
169
170
|
- lib/psd/layer_info/placed_layer.rb
|
170
171
|
- lib/psd/layer_info/reference_point.rb
|