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     uint blendModeKey;
332 
333     /**
334         Channels in layer
335     */
336     ChannelInfo[] channels;
337     
338     /**
339         The layer's user mask, if any.
340     */
341 	LayerMask[] layerMask;
342     
343     /**
344         The layer's vector mask, if any.
345     */
346 	VectorMask[] vectorMask;
347 
348     /**
349         Opacity of the layer
350     */
351     ubyte opacity;
352 
353     /**
354         Whether clipping is base or non-base
355     */
356     bool clipping;
357 
358     /**
359         Flags for the layer
360     */
361     LayerFlags flags;
362 
363     /**
364         The data of the layer
365     */
366     ubyte[] data;
367 
368     /**
369         The type of layer
370     */
371     LayerType type;
372 
373     /**
374         Whether the layer is visible or not
375     */
376     bool isVisible;
377 
378     /**
379         Gets the center coordinates of the layer
380     */
381     uint[2] center() {
382         return [
383             left+(width/2),
384             top+(height/2),
385         ];
386     }
387 
388     /**
389         Gets the size of this layer
390     */
391     uint[2] size() {
392         return [
393             width,
394             height
395         ];
396     }
397 
398     /**
399         Width
400     */
401     uint width() {
402         return right-left;
403     }
404 
405     /**
406         Height
407     */
408     uint height() {
409         return bottom-top;
410     }
411 
412     /**
413         Returns true if the layer is a group
414     */
415     bool isLayerGroup() {
416         return type == LayerType.OpenFolder || type == LayerType.ClosedFolder;
417     }
418 
419     /**
420         Is the layer useful?
421     */
422     bool isLayerUseful() {
423         return !isLayerGroup() && (width != 0 && height != 0);
424     }
425 
426     /**
427         Length of data
428     */
429     size_t dataLengthUncompressed() {
430         return this.area()*channels.length;
431     }
432 
433     /**
434         Gets total data count
435     */
436     size_t totalDataCount() {
437         uint length;
438         foreach(channel; channels) length += channel.dataLength;
439         return length;
440     }
441 
442     /**
443         Area of the layer
444     */
445     size_t area() {
446         return width * height;
447     }
448 
449     /**
450         Extracts the layer image
451     */
452     void extractLayerImage() {
453         extractLayer(this);
454     }
455 }
456 
457 /**
458     A layer mask section
459 */
460 struct LayerMaskSection {
461 
462     /**
463         The layers in the section
464     */
465     Layer[] layers;
466 
467     /**
468         The amount of layers in the section
469     */
470     uint layerCount = 0;
471 
472     /**
473         The colorspace of the overlay (unused)
474     */
475     ushort overlayColorSpace = 0;
476     
477     /**
478         The global opacity level (0 = transparent, 100 = opaque)
479     */
480     ushort opacity = 0;
481     
482     /**
483         The global layer kind
484     */
485     ubyte kind = 128u;
486 
487     /**
488         Whether the layer data contains a transparency mask
489     */
490     bool hasTransparencyMask = false;
491 }