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 }