psd 1.3.3 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,6 +7,7 @@ class PSD
7
7
  class Node
8
8
  include Ancestry
9
9
  include Search
10
+ include BuildPreview
10
11
 
11
12
  # Default properties that all nodes contain
12
13
  PROPERTIES = [:name, :left, :right, :top, :bottom, :height, :width]
@@ -38,7 +39,7 @@ class PSD
38
39
  end
39
40
 
40
41
  def group?
41
- is_a?(PSD::Node::Group)
42
+ is_a?(PSD::Node::Group) || is_a?(PSD::Node::Root)
42
43
  end
43
44
 
44
45
  def to_hash
@@ -58,7 +58,13 @@ class PSD::Node
58
58
  type: :layer,
59
59
  text: @layer.text,
60
60
  ref_x: @layer.reference_point.x,
61
- ref_y: @layer.reference_point.y
61
+ ref_y: @layer.reference_point.y,
62
+ mask: @layer.mask.snapshot,
63
+ image: {
64
+ width: @layer.image.width,
65
+ height: @layer.image.height,
66
+ channels: @layer.channels_info
67
+ }
62
68
  })
63
69
  end
64
70
 
@@ -38,6 +38,18 @@ class PSD
38
38
  parent.children
39
39
  end
40
40
 
41
+ def next_sibling
42
+ return nil if parent.nil?
43
+ index = siblings.index(self)
44
+ siblings[index + 1]
45
+ end
46
+
47
+ def prev_sibling
48
+ return nil if parent.nil?
49
+ index = siblings.index(self)
50
+ siblings[index - 1]
51
+ end
52
+
41
53
  # Does this node have any siblings?
42
54
  def has_siblings?
43
55
  siblings.length > 1
@@ -0,0 +1,69 @@
1
+ class PSD
2
+ class Node
3
+ module BuildPreview
4
+ include PSD::Image::Export::PNG
5
+
6
+ alias :orig_to_png :to_png
7
+ def to_png
8
+ return build_png if group?
9
+ layer.image.to_png
10
+ end
11
+
12
+ def build_png(png=nil)
13
+ png ||= create_canvas
14
+
15
+ children.reverse.each do |c|
16
+ next unless c.visible?
17
+
18
+ if c.group?
19
+ if c.blending_mode == 'passthru'
20
+ c.build_png(png)
21
+ else
22
+ compose! c, png, c.build_png, 0, 0
23
+ end
24
+ else
25
+ compose! c, png, c.image.to_png_with_mask, c.left.to_i, c.top.to_i
26
+ end
27
+ end
28
+
29
+ png
30
+ end
31
+
32
+ private
33
+
34
+ def create_canvas
35
+ width, height = document_dimensions
36
+ ChunkyPNG::Canvas.new(width.to_i, height.to_i, ChunkyPNG::Color::TRANSPARENT)
37
+ end
38
+
39
+ # Modified from ChunkyPNG::Canvas#compose! in order to support various blend modes.
40
+ def compose!(layer, base, other, offset_x = 0, offset_y = 0)
41
+ blending_mode = layer.blending_mode.gsub(/ /, '_')
42
+ PSD.logger.warn("Blend mode #{blending_mode} is not implemented") unless Compose.respond_to?(blending_mode)
43
+ PSD.logger.debug("Blending #{layer.name} with #{blending_mode} blend mode")
44
+
45
+ LayerStyles.new(layer, other).apply!
46
+ other = ClippingMask.new(layer, other).apply
47
+
48
+ for y in 0...other.height do
49
+ for x in 0...other.width do
50
+ base_x = x + offset_x
51
+ base_y = y + offset_y
52
+
53
+ next if base_x < 0 || base_y < 0 || base_x >= base.width || base_y >= base.height
54
+
55
+ color = Compose.send(
56
+ blending_mode,
57
+ other[x, y],
58
+ base[base_x, base_y],
59
+ opacity: layer.opacity,
60
+ fill_opacity: layer.fill_opacity
61
+ )
62
+
63
+ base[base_x, base_y] = color
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -23,6 +23,7 @@ class PSD
23
23
  return matches.map { |m| m.children_at_path(path, opts) }.flatten
24
24
  end
25
25
  end
26
+ alias :children_with_path :children_at_path
26
27
 
27
28
  # Given a layer comp ID, name, or :last for last document state, create a new
28
29
  # tree based on the layers/groups that belong to the comp only.
@@ -0,0 +1,27 @@
1
+ class PSD
2
+ class Resource
3
+ class Section
4
+ class Slices < Section
5
+ attr_reader :data, :version
6
+
7
+ def self.id; 1050; end
8
+ def self.name; :slices; end
9
+
10
+ def parse
11
+ @version = @file.read_int
12
+ @descriptor_version = @file.read_int
13
+ @resource.data = self
14
+
15
+ if @version == 7 || @version == 8
16
+ @data = Descriptor.new(@file).parse
17
+ end
18
+
19
+ end
20
+
21
+ def to_a
22
+ @data.nil? ? [] : @data['slices']
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,3 +1,3 @@
1
1
  class PSD
2
- VERSION = "1.3.3"
2
+ VERSION = "1.4.0"
3
3
  end
Binary file
@@ -28,7 +28,7 @@ describe 'Image Exporting' do
28
28
 
29
29
  describe "as PNG" do
30
30
  it "should produce a valid PNG object" do
31
- expect(@psd.image.to_png).to be_an_instance_of(ChunkyPNG::Image)
31
+ expect(@psd.image.to_png).to be_an_instance_of(ChunkyPNG::Canvas)
32
32
 
33
33
  expect(@psd.image.to_png.width).to eq(1)
34
34
  expect(@psd.image.to_png.height).to eq(1)
@@ -58,7 +58,7 @@ describe 'Image Exporting' do
58
58
  @psd.parse!
59
59
 
60
60
  png = @psd.tree.children.first.image.to_png
61
- expect(png).to be_an_instance_of(ChunkyPNG::Image)
61
+ expect(png).to be_an_instance_of(ChunkyPNG::Canvas)
62
62
  expect(png.width).to eq(1)
63
63
  expect(png.height).to eq(1)
64
64
  expect(
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Slices' do
4
+
5
+ describe "Handle file with slice properly" do
6
+
7
+
8
+ it "should successfully parse a the PSD file of version 7 or above and has slices" do
9
+ psd = PSD.new('spec/files/slices.psd')
10
+ psd.parse!
11
+
12
+ # File should parse
13
+ expect(psd).to be_parsed
14
+
15
+ # Slices should not be nil
16
+ expect(psd.resources[:slices]).to_not be_nil
17
+
18
+ # slices version should be above 6
19
+ expect(psd.resources[:slices].data.version).to be > 6
20
+
21
+ # Bounds of each slice should not be nil
22
+ psd.resources[:slices].data.to_a.each do |slice|
23
+ expect(slice).to_not be_nil
24
+ expect(slice['bounds']).to_not be_nil
25
+ end
26
+ end
27
+
28
+
29
+ it "should successfully parse a the PSD file of version 6 and has slices" do
30
+ psd = PSD.new('spec/files/pixel.psd')
31
+ psd.parse!
32
+
33
+ # File should parse
34
+ expect(psd).to be_parsed
35
+
36
+ # Slices should still be not nil
37
+ expect(psd.resources[:slices]).to_not be_nil
38
+
39
+ # But slices version should be equal to 6
40
+ expect(psd.resources[:slices].data.version).to eq 6
41
+
42
+ # Slices data to be nil
43
+ expect(psd.resources[:slices].data.to_a).to eq []
44
+ end
45
+ end
46
+
47
+ describe "Handle file without slices properly" do
48
+ #TODO: All files have atleast one autogenerated slice. Dunno how to handle this case yet!
49
+ #it "should successfully parse a PSD file which does not have slices" do
50
+ #end
51
+ end
52
+ 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.3.3
4
+ version: 1.4.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-10-23 00:00:00.000000000 Z
12
+ date: 2013-11-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -144,7 +144,9 @@ files:
144
144
  - lib/psd.rb
145
145
  - lib/psd/blend_mode.rb
146
146
  - lib/psd/channel_image.rb
147
+ - lib/psd/clipping_mask.rb
147
148
  - lib/psd/color.rb
149
+ - lib/psd/compose.rb
148
150
  - lib/psd/descriptor.rb
149
151
  - lib/psd/file.rb
150
152
  - lib/psd/header.rb
@@ -170,6 +172,8 @@ files:
170
172
  - lib/psd/layer/path_components.rb
171
173
  - lib/psd/layer/position_and_channels.rb
172
174
  - lib/psd/layer_info.rb
175
+ - lib/psd/layer_info/blend_clipping_elements.rb
176
+ - lib/psd/layer_info/blend_interior_elements.rb
173
177
  - lib/psd/layer_info/fill_opacity.rb
174
178
  - lib/psd/layer_info/layer_group.rb
175
179
  - lib/psd/layer_info/layer_id.rb
@@ -183,7 +187,11 @@ files:
183
187
  - lib/psd/layer_info/typetool.rb
184
188
  - lib/psd/layer_info/unicode_name.rb
185
189
  - lib/psd/layer_info/vector_mask.rb
190
+ - lib/psd/layer_info/vector_mask_2.rb
191
+ - lib/psd/layer_info/vector_stroke.rb
192
+ - lib/psd/layer_info/vector_stroke_content.rb
186
193
  - lib/psd/layer_mask.rb
194
+ - lib/psd/layer_styles.rb
187
195
  - lib/psd/logger.rb
188
196
  - lib/psd/mask.rb
189
197
  - lib/psd/node.rb
@@ -192,6 +200,7 @@ files:
192
200
  - lib/psd/node_layer.rb
193
201
  - lib/psd/node_root.rb
194
202
  - lib/psd/nodes/ancestry.rb
203
+ - lib/psd/nodes/build_preview.rb
195
204
  - lib/psd/nodes/has_children.rb
196
205
  - lib/psd/nodes/lock_to_origin.rb
197
206
  - lib/psd/nodes/parse_layers.rb
@@ -201,6 +210,7 @@ files:
201
210
  - lib/psd/resource_section.rb
202
211
  - lib/psd/resources.rb
203
212
  - lib/psd/resources/layer_comps.rb
213
+ - lib/psd/resources/slices.rb
204
214
  - lib/psd/section.rb
205
215
  - lib/psd/util.rb
206
216
  - lib/psd/version.rb
@@ -210,12 +220,14 @@ files:
210
220
  - spec/files/path.psd
211
221
  - spec/files/pixel.psd
212
222
  - spec/files/simplest.psd
223
+ - spec/files/slices.psd
213
224
  - spec/files/text.psd
214
225
  - spec/hierarchy_spec.rb
215
226
  - spec/identity_spec.rb
216
227
  - spec/image_spec.rb
217
228
  - spec/parsing_spec.rb
218
229
  - spec/psd_spec.rb
230
+ - spec/slices_spec.rb
219
231
  - spec/spec_helper.rb
220
232
  - spec/text_spec.rb
221
233
  homepage: http://cosmos.layervault.com/psdrb.html
@@ -248,11 +260,13 @@ test_files:
248
260
  - spec/files/path.psd
249
261
  - spec/files/pixel.psd
250
262
  - spec/files/simplest.psd
263
+ - spec/files/slices.psd
251
264
  - spec/files/text.psd
252
265
  - spec/hierarchy_spec.rb
253
266
  - spec/identity_spec.rb
254
267
  - spec/image_spec.rb
255
268
  - spec/parsing_spec.rb
256
269
  - spec/psd_spec.rb
270
+ - spec/slices_spec.rb
257
271
  - spec/spec_helper.rb
258
272
  - spec/text_spec.rb