1 module psd.layer;
2 import psd.parser;
3 import std.stdio : File;
4 
5 /**
6     Photoshop blending modes
7 */
8 enum BlendingMode : string {
9     PassThrough = "pass",
10     Normal = "norm",
11     Dissolve = "diss",
12     Darken = "dark",
13     Multiply = "mul ",
14     ColorBurn = "idiv",
15     LinearBurn = "lbrn",
16     DarkerColor = "dkCl",
17     Lighten = "lite",
18     Screen = "scrn",
19     ColorDodge = "div ",
20     LinearDodge = "lddg",
21     LighterColor = "lgCl",
22     Overlay = "over",
23     SoftLight = "sLit",
24     HardLight = "hLit",
25     VividLight = "vLit",
26     LinearLight = "lLit",
27     PinLight = "pLit",
28     HardMix = "hMix",
29     Difference = "diff",
30     Exclusion = "smud",
31     Subtract = "fsub",
32     Divide = "fdiv",
33     Hue = "hue ",
34     Saturation = "sat ",
35     Color = "colr",
36     Luminosity = "lum "
37 }
38 
39 /**
40     A struct representing a layer mask as stored in the layers of the Layer Mask section.
41 */
42 struct LayerMask
43 {
44 	/**
45         Top coordinate of the rectangle that encloses the mask.
46     */
47     int top;
48 
49 	/**
50         Left coordinate of the rectangle that encloses the mask.
51     */
52     int left;
53 
54 	/**
55         Bottom coordinate of the rectangle that encloses the mask.
56     */
57     int bottom;
58 
59 	/**
60         Right coordinate of the rectangle that encloses the mask.
61     */
62     int right;
63 
64 
65 	/**
66         The offset from the start of the file where the channel's data is stored.
67     */
68     ulong fileOffset;
69 
70 
71 	/**
72         Planar data, having a size of (right-left)*(bottom-top)*bytesPerPixel.
73     */
74     ubyte[] data;
75 
76 
77 	/**
78         The mask's feather value.
79     */
80     double feather;
81 
82 	/**
83         The mask's density value.
84     */
85     ubyte density;
86 
87 	/**
88         The mask's default color regions outside the enclosing rectangle.
89     */
90     ubyte defaultColor;
91 };
92 
93 /**
94     A struct representing a vector mask as stored in the layers of the Layer Mask section.
95 */
96 struct VectorMask
97 {
98 	/**
99         Top coordinate of the rectangle that encloses the mask.
100     */
101     int top;
102 
103 	/**
104         Left coordinate of the rectangle that encloses the mask.
105     */
106     int left;
107 
108 	/**
109         Bottom coordinate of the rectangle that encloses the mask.
110     */
111     int bottom;
112 
113 	/**
114         Right coordinate of the rectangle that encloses the mask.
115     */
116     int right;
117 
118 
119 	/**
120         The offset from the start of the file where the channel's data is stored.
121     */
122     ulong fileOffset;
123 
124 
125 	/**
126         Planar data, having a size of (right-left)*(bottom-top)*bytesPerPixel.
127     */
128     ubyte[] data;
129 
130 
131 	/**
132         The mask's feather value.
133     */
134     double feather;
135 
136 	/**
137         The mask's density value.
138     */
139     ubyte density;
140 
141 	/**
142         The mask's default color regions outside the enclosing rectangle.
143     */
144     ubyte defaultColor;
145 };
146 
147 /**
148     Information about Masks
149 */
150 struct MaskData
151 {
152     /**
153         Top X coordinate of mask
154     */
155     int top;
156 
157     /**
158         Left X coordinate of mask
159     */
160     int left;
161 
162     /**
163         Bottom Y coordinate of mask
164     */
165     int bottom;
166 
167     /**
168         Right X coordinate of mask
169     */
170     int right;
171     
172     /**
173         Default color of mask
174     */
175     ubyte defaultColor;
176     
177     /**
178         If the mask is a vector mask or not
179     */
180     bool isVectorMask;
181 };
182 
183 /**
184     Type of channel.
185 */
186 enum ChannelType
187 {
188     INVALID = 32767,					///< Internal value. Used to denote that a channel no longer holds valid data.
189 
190     R = 0,								///< Type denoting the R channel, not necessarily the first in a RGB Color Mode document.
191     G = 1,								///< Type denoting the G channel, not necessarily the second in a RGB Color Mode document.
192     B = 2,								///< Type denoting the B channel, not necessarily the third in a RGB Color Mode document.
193 
194     TRANSPARENCY_MASK = -1,				///< The layer's channel data is a transparency mask.
195     LAYER_OR_VECTOR_MASK = -2,			///< The layer's channel data is either a layer or vector mask.
196     LAYER_MASK = -3						///< The layer's channel data is a layer mask.
197 }
198 
199 /**
200     Information about color channels
201 */
202 struct ChannelInfo {
203     /**
204         Type of channel
205     */
206     short type;
207 
208     /**
209         Offset into the file of the color channel
210     */
211     uint fileOffset;
212 
213     /**
214         Length of data in color channel
215     */
216     uint dataLength;
217     
218     /**
219         The data of the channel
220     */
221     ubyte[] data;
222 
223     /**
224         Gets whether the channel is a mask
225     */
226     bool isMask() {
227         return type < 0;
228     }
229 }
230 
231 /**
232     The different types of layer
233 */
234 enum LayerType {
235     /**
236         Any other type of layer
237     */
238     Any = 0,
239 
240     /**
241         An open folder
242     */
243     OpenFolder = 1,
244 
245     /**
246         A closed folder
247     */
248     ClosedFolder = 2,
249 
250     /**
251         A bounding section divider
252     
253         Hidden in the UI
254     */
255     SectionDivider = 3
256 }
257 
258 /**
259     Flags for a layer
260 */
261 enum LayerFlags : ubyte {
262     TransProtect    = 0b00000001,
263     Visible         = 0b00000010,
264     Obsolete        = 0b00000100,
265     ModernDoc       = 0b00001000,
266     PixelIrrel      = 0b00010000,
267 
268     /**
269         Special mask used for getting whether a layer is a group layer
270         flags & GroupMask = 24, for a layer group.
271     */
272     GroupMask       = 0b00011000
273 }
274 
275 /**
276     A layer
277 */
278 struct Layer {
279 package(psd):
280     File filePtr;
281 
282 public:
283 
284     /**
285         Parent of layer
286     */
287     //Layer* parent;
288 
289     /**
290         Name of layer
291     */
292     string name;
293 
294     /**
295         Bounding box for layer
296     */
297     union {
298         struct {
299 
300             /**
301                 Top X coordinate of layer
302             */
303             int top;
304 
305             /**
306                 Left X coordinate of layer
307             */
308             int left;
309 
310             /**
311                 Bottom Y coordinate of layer
312             */
313             int bottom;
314 
315             /**
316                 Right X coordinate of layer
317             */
318             int right;
319         }
320 
321         /**
322             Bounds as array
323         */
324         int[4] bounds;
325     }
326 
327     /**
328         Blending mode
329     */
330     BlendingMode blendModeKey;
331 
332     /**
333         Channels in layer
334     */
335     ChannelInfo[] channels;
336     
337     /**
338         The layer's user mask, if any.
339     */
340 	LayerMask[] layerMask;
341     
342     /**
343         The layer's vector mask, if any.
344     */
345 	VectorMask[] vectorMask;
346 
347     /**
348         Opacity of the layer
349     */
350     ubyte opacity;
351 
352     /**
353         Whether clipping is base or non-base
354     */
355     bool clipping;
356 
357     /**
358         Flags for the layer
359     */
360     LayerFlags flags;
361 
362     /**
363         The data of the layer
364     */
365     ubyte[] data;
366 
367     /**
368         The type of layer
369     */
370     LayerType type;
371 
372     /**
373         Whether the layer is visible or not
374     */
375     bool isVisible;
376 
377     /**
378         Gets the center coordinates of the layer
379     */
380     uint[2] center() {
381         return [
382             left+(width/2),
383             top+(height/2),
384         ];
385     }
386 
387     /**
388         Gets the size of this layer
389     */
390     uint[2] size() {
391         return [
392             width,
393             height
394         ];
395     }
396 
397     /**
398         Width
399     */
400     uint width() {
401         return right-left;
402     }
403 
404     /**
405         Height
406     */
407     uint height() {
408         return bottom-top;
409     }
410 
411     /**
412         Returns true if the layer is a group
413     */
414     bool isLayerGroup() {
415         return type == LayerType.OpenFolder || type == LayerType.ClosedFolder;
416     }
417 
418     /**
419         Is the layer useful?
420     */
421     bool isLayerUseful() {
422         return !isLayerGroup() && (width != 0 && height != 0);
423     }
424 
425     /**
426         Length of data
427     */
428     size_t dataLengthUncompressed() {
429         return this.area()*channels.length;
430     }
431 
432     /**
433         Gets total data count
434     */
435     size_t totalDataCount() {
436         uint length;
437         foreach(channel; channels) length += channel.dataLength;
438         return length;
439     }
440 
441     /**
442         Area of the layer
443     */
444     size_t area() {
445         return width * height;
446     }
447 
448     /**
449         Extracts the layer image
450     */
451     void extractLayerImage() {
452         extractLayer(this);
453     }
454 }
455 
456 /**
457     A layer mask section
458 */
459 struct LayerMaskSection {
460 
461     /**
462         The layers in the section
463     */
464     Layer[] layers;
465 
466     /**
467         The amount of layers in the section
468     */
469     uint layerCount = 0;
470 
471     /**
472         The colorspace of the overlay (unused)
473     */
474     ushort overlayColorSpace = 0;
475     
476     /**
477         The global opacity level (0 = transparent, 100 = opaque)
478     */
479     ushort opacity = 0;
480     
481     /**
482         The global layer kind
483     */
484     ubyte kind = 128u;
485 
486     /**
487         Whether the layer data contains a transparency mask
488     */
489     bool hasTransparencyMask = false;
490 }