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