psd 0.3.4 → 0.3.5
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 +4 -4
- data/CONTRIBUTING.md +7 -0
- data/README.md +14 -8
- data/lib/psd.rb +7 -5
- data/lib/psd/image.rb +5 -0
- data/lib/psd/image_exports/png.rb +2 -1
- data/lib/psd/image_formats/rle.rb +3 -2
- data/lib/psd/image_modes/rgb.rb +11 -7
- data/lib/psd/layer.rb +8 -3
- data/lib/psd/layer_mask.rb +24 -1
- data/lib/psd/logger.rb +42 -0
- data/lib/psd/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ad5fbd51101b2362d57e17fe0fe5544ebc51ea8
|
4
|
+
data.tar.gz: bb899376edd469fd83536d6bf2b50b96fb044b6e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92068cabd35464e01395b673cc8a4322fd0cd5e8f9317fcc33571df8cea9d0bd59cc98e4faeeca91399634f5549c3b04b4fbf3f891d5b32a154a54843a46e98d
|
7
|
+
data.tar.gz: 26686e5b31b29de64da12dce875cc9edde976451028cd0ccd1f25c855db2851e00be26619c4a8d49e84d8ee076b05e3015acd92bb978a24b014203489890b4ea
|
data/CONTRIBUTING.md
ADDED
data/README.md
CHANGED
@@ -142,6 +142,20 @@ png = psd.image.to_png # reference to PNG data
|
|
142
142
|
psd.image.save_as_png 'path/to/output.png' # writes PNG to disk
|
143
143
|
```
|
144
144
|
|
145
|
+
**Debugging**
|
146
|
+
|
147
|
+
If you run into any problems parsing a PSD, you can enable debug logging via the `PSD_DEBUG` environment variable. For example:
|
148
|
+
|
149
|
+
``` bash
|
150
|
+
PSD_DEBUG=STDOUT bundle exec examples/parse.rb
|
151
|
+
```
|
152
|
+
|
153
|
+
You can also give a path to a file instead. If you need to enable debugging programatically:
|
154
|
+
|
155
|
+
``` ruby
|
156
|
+
PSD.debug = true
|
157
|
+
```
|
158
|
+
|
145
159
|
## To-do
|
146
160
|
|
147
161
|
There are a few features that are currently missing from PSD.rb.
|
@@ -150,11 +164,3 @@ There are a few features that are currently missing from PSD.rb.
|
|
150
164
|
* Individual layer image exporting
|
151
165
|
* More image modes + depths for image exporting
|
152
166
|
* A few layer info blocks
|
153
|
-
|
154
|
-
## Contributing
|
155
|
-
|
156
|
-
1. Fork it
|
157
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
158
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
159
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
160
|
-
5. Create new Pull Request
|
data/lib/psd.rb
CHANGED
@@ -19,13 +19,10 @@ end
|
|
19
19
|
# the header, resources, the layer mask (including layers), and the preview image. We parse
|
20
20
|
# each of these sections in order.
|
21
21
|
class PSD
|
22
|
+
include Logger
|
22
23
|
include Helpers
|
23
24
|
include NodeExporting
|
24
25
|
|
25
|
-
# Just used to track what layer info keys we didn't parse in this file for development purposes.
|
26
|
-
def self.keys; @@keys; end
|
27
|
-
@@keys = []
|
28
|
-
|
29
26
|
DEFAULTS = {
|
30
27
|
parse_image: false,
|
31
28
|
parse_layer_images: false
|
@@ -66,7 +63,10 @@ class PSD
|
|
66
63
|
|
67
64
|
# Get the Header, parsing it if needed.
|
68
65
|
def header
|
69
|
-
@header
|
66
|
+
return @header if @header
|
67
|
+
|
68
|
+
@header = Header.read(@file)
|
69
|
+
PSD.logger.debug @header.inspect
|
70
70
|
end
|
71
71
|
|
72
72
|
# Get the Resources section, parsing if needed.
|
@@ -78,6 +78,8 @@ class PSD
|
|
78
78
|
@resources = Resources.new(@file)
|
79
79
|
@resources.parse
|
80
80
|
|
81
|
+
PSD.logger.debug @resources.inspect
|
82
|
+
|
81
83
|
return @resources.data
|
82
84
|
end
|
83
85
|
|
data/lib/psd/image.rb
CHANGED
@@ -40,6 +40,8 @@ class PSD
|
|
40
40
|
@end_pos = @start_pos + @length
|
41
41
|
|
42
42
|
@pixel_data = []
|
43
|
+
|
44
|
+
PSD.logger.debug "Image: #{width}x#{height}, length = #{@length}, mode = #{@header.mode_name}, position = #{@start_pos}"
|
43
45
|
end
|
44
46
|
|
45
47
|
# Begins parsing the image by first figuring out the compression format used, and then
|
@@ -49,9 +51,12 @@ class PSD
|
|
49
51
|
|
50
52
|
# ZIP not implemented
|
51
53
|
if [2, 3].include?(@compression)
|
54
|
+
PSD.logger.debug "Warning: ZIP image compression not supported yet. Skipping."
|
52
55
|
@file.seek @end_pos and return
|
53
56
|
end
|
54
57
|
|
58
|
+
PSD.logger.debug "Compression: id = #{@compression}, name = #{COMPRESSIONS[@compression]}"
|
59
|
+
|
55
60
|
parse_image_data!
|
56
61
|
|
57
62
|
return self
|
@@ -7,6 +7,7 @@ class PSD::Image
|
|
7
7
|
# Load the image pixels into a PNG file and return a reference to the
|
8
8
|
# data.
|
9
9
|
def to_png
|
10
|
+
PSD.logger.debug "Beginning PNG export"
|
10
11
|
png = ChunkyPNG::Image.new(width, height, ChunkyPNG::Color::TRANSPARENT)
|
11
12
|
|
12
13
|
i = 0
|
@@ -29,7 +30,7 @@ class PSD::Image
|
|
29
30
|
|
30
31
|
# Saves the PNG data to disk.
|
31
32
|
def save_as_png(file)
|
32
|
-
to_png.save(file)
|
33
|
+
to_png.save(file, :fast_rgba)
|
33
34
|
end
|
34
35
|
end
|
35
36
|
end
|
@@ -25,6 +25,7 @@ class PSD::Image
|
|
25
25
|
line_index = 0
|
26
26
|
|
27
27
|
channels.times do |i|
|
28
|
+
PSD.logger.debug "Parsing RLE channel ##{i}: position = #{chan_pos}, line = #{line_index}"
|
28
29
|
chan_pos = decode_rle_channel(chan_pos, line_index)
|
29
30
|
line_index += height
|
30
31
|
end
|
@@ -34,9 +35,9 @@ class PSD::Image
|
|
34
35
|
height.times do |j|
|
35
36
|
byte_count = @byte_counts[line_index]
|
36
37
|
line_index += 1
|
37
|
-
|
38
|
+
finish = @file.tell + byte_count
|
38
39
|
|
39
|
-
while @file.tell <
|
40
|
+
while @file.tell < finish
|
40
41
|
len = @file.read(1).bytes.to_a[0]
|
41
42
|
|
42
43
|
if len < 128
|
data/lib/psd/image_modes/rgb.rb
CHANGED
@@ -4,21 +4,25 @@ class PSD::Image::Mode
|
|
4
4
|
private
|
5
5
|
|
6
6
|
def combine_rgb_channel
|
7
|
+
PSD.logger.debug "Beginning RGB processing"
|
8
|
+
|
7
9
|
(0...@num_pixels).step(pixel_step) do |i|
|
8
|
-
|
10
|
+
r = g = b = 0
|
11
|
+
a = 255
|
9
12
|
|
10
|
-
PSD::Image::CHANNEL_INFO
|
13
|
+
PSD::Image::CHANNEL_INFO.each_with_index do |chan, index|
|
14
|
+
next if channels == 3 && chan[:id] == -1
|
11
15
|
val = @channel_data[i + (@channel_length * index)]
|
12
16
|
|
13
17
|
case chan[:id]
|
14
|
-
when -1 then
|
15
|
-
when 0 then
|
16
|
-
when 1 then
|
17
|
-
when 2 then
|
18
|
+
when -1 then a = val
|
19
|
+
when 0 then r = val
|
20
|
+
when 1 then g = val
|
21
|
+
when 2 then b = val
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
21
|
-
@pixel_data.push
|
25
|
+
@pixel_data.push r, g, b, a
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
data/lib/psd/layer.rb
CHANGED
@@ -68,6 +68,8 @@ class PSD
|
|
68
68
|
parse_legacy_layer_name
|
69
69
|
parse_extra_data
|
70
70
|
|
71
|
+
PSD.logger.debug "Layer name = #{name}"
|
72
|
+
|
71
73
|
@file.seek @layer_end # Skip over any filler zeros
|
72
74
|
|
73
75
|
end_section
|
@@ -310,21 +312,24 @@ class PSD
|
|
310
312
|
LAYER_INFO.each do |name, info|
|
311
313
|
next unless info.key == key
|
312
314
|
|
315
|
+
PSD.logger.debug "Layer Info: key = #{key}, start = #{pos}, length = #{length}"
|
316
|
+
|
313
317
|
begin
|
314
318
|
i = info.new(@file, length)
|
315
319
|
i.parse
|
316
320
|
|
317
321
|
@adjustments[name] = i
|
318
322
|
info_parsed = true
|
319
|
-
rescue Exception
|
323
|
+
rescue Exception => e
|
324
|
+
PSD.logger.error "Parsing error: key = #{key}, message = #{e.message}"
|
325
|
+
PSD.logger.error e.backtrace.join("\n")
|
320
326
|
end
|
321
327
|
|
322
328
|
break
|
323
329
|
end
|
324
330
|
|
325
331
|
if !info_parsed
|
326
|
-
PSD.
|
327
|
-
# puts "SKIPPING #{key}, length = #{length}"
|
332
|
+
PSD.logger.debug "SKIPPING: key = #{key}, length = #{length}"
|
328
333
|
@file.seek pos + length
|
329
334
|
end
|
330
335
|
|
data/lib/psd/layer_mask.rb
CHANGED
@@ -64,7 +64,9 @@ class PSD
|
|
64
64
|
layers.reverse!
|
65
65
|
group_layers
|
66
66
|
|
67
|
-
|
67
|
+
parse_global_mask
|
68
|
+
|
69
|
+
# Ensure we're at the end of this section
|
68
70
|
@file.seek finish
|
69
71
|
end_section
|
70
72
|
|
@@ -102,5 +104,26 @@ class PSD
|
|
102
104
|
end
|
103
105
|
end
|
104
106
|
end
|
107
|
+
|
108
|
+
def parse_global_mask
|
109
|
+
length = @file.read_int
|
110
|
+
return if length == 0
|
111
|
+
|
112
|
+
mask_end = @file.tell + length
|
113
|
+
PSD.logger.debug "Global Mask: length = #{length}"
|
114
|
+
|
115
|
+
@global_mask = {}
|
116
|
+
@global_mask[:overlay_color_space] = @file.read_short
|
117
|
+
@global_mask[:color_components] = 4.times.map { |i| @file.read_short >> 8 }
|
118
|
+
@global_mask[:opacity] = @file.read_short
|
119
|
+
|
120
|
+
# 0 = color selected, 1 = color protected, 128 = use value per layer
|
121
|
+
@global_mask[:kind] = @file.read(1).bytes.to_a[0]
|
122
|
+
|
123
|
+
PSD.logger.debug @global_mask
|
124
|
+
|
125
|
+
# Filler zeros
|
126
|
+
@file.seek mask_end
|
127
|
+
end
|
105
128
|
end
|
106
129
|
end
|
data/lib/psd/logger.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
class PSD
|
4
|
+
module Logger
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
attr_accessor :debug
|
11
|
+
|
12
|
+
def logger
|
13
|
+
return @logger if @logger
|
14
|
+
|
15
|
+
if debug || ENV['PSD_DEBUG']
|
16
|
+
@logger = ::Logger.new(debug_output)
|
17
|
+
@logger.formatter = proc do |severity, datetime, progname, msg|
|
18
|
+
"#{severity}: #{msg}\n"
|
19
|
+
end
|
20
|
+
else
|
21
|
+
@logger = DisabledLogger.new
|
22
|
+
end
|
23
|
+
|
24
|
+
return @logger
|
25
|
+
end
|
26
|
+
|
27
|
+
def debug_output
|
28
|
+
if ENV['PSD_DEBUG']
|
29
|
+
ENV['PSD_DEBUG'] == 'STDOUT' ? STDOUT : ENV['PSD_DEBUG']
|
30
|
+
end
|
31
|
+
|
32
|
+
STDOUT
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class DisabledLogger
|
38
|
+
def method_missing(method, *args, &block)
|
39
|
+
# silence
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/psd/version.rb
CHANGED
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: 0.3.
|
4
|
+
version: 0.3.5
|
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-
|
12
|
+
date: 2013-08-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bindata
|
@@ -119,6 +119,7 @@ extra_rdoc_files: []
|
|
119
119
|
files:
|
120
120
|
- .gitignore
|
121
121
|
- .rspec
|
122
|
+
- CONTRIBUTING.md
|
122
123
|
- Gemfile
|
123
124
|
- Guardfile
|
124
125
|
- LICENSE.txt
|
@@ -154,6 +155,7 @@ files:
|
|
154
155
|
- lib/psd/layer_info/unicode_name.rb
|
155
156
|
- lib/psd/layer_info/vector_mask.rb
|
156
157
|
- lib/psd/layer_mask.rb
|
158
|
+
- lib/psd/logger.rb
|
157
159
|
- lib/psd/mask.rb
|
158
160
|
- lib/psd/node.rb
|
159
161
|
- lib/psd/node_exporting.rb
|