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 }