psd 1.3.3 → 1.4.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.
@@ -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