Jump To …
READMElib / psd / blend_mode.coffeelib / psd / channel_image.coffeelib / psd / color.coffeelib / psd / descriptor.coffeelib / psd / file.coffeelib / psd / header.coffeelib / psd / image.coffeelib / psd / image_export.coffeelib / psd / image_exports / png.coffeelib / psd / image_format.coffeelib / psd / image_formats / layer_raw.coffeelib / psd / image_formats / layer_rle.coffeelib / psd / image_formats / raw.coffeelib / psd / image_formats / rle.coffeelib / psd / image_mode.coffeelib / psd / image_modes / cmyk.coffeelib / psd / image_modes / greyscale.coffeelib / psd / image_modes / rgb.coffeelib / psd / init.coffeelib / psd / layer / blend_modes.coffeelib / psd / layer / blending_ranges.coffeelib / psd / layer / channel_image.coffeelib / psd / layer / helpers.coffeelib / psd / layer / info.coffeelib / psd / layer / mask.coffeelib / psd / layer / name.coffeelib / psd / layer / position_channels.coffeelib / psd / layer.coffeelib / psd / layer_info / blend_clipping_elements.coffeelib / psd / layer_info / blend_interior_elements.coffeelib / psd / layer_info / fill_opacity.coffeelib / psd / layer_info / gradient_fill.coffeelib / psd / layer_info / layer_id.coffeelib / psd / layer_info / layer_name_source.coffeelib / psd / layer_info / legacy_typetool.coffeelib / psd / layer_info / locked.coffeelib / psd / layer_info / metadata.coffeelib / psd / layer_info / nested_section_divider.coffeelib / psd / layer_info / object_effects.coffeelib / psd / layer_info / section_divider.coffeelib / psd / layer_info / solid_color.coffeelib / psd / layer_info / typetool.coffeelib / psd / layer_info / unicode_name.coffeelib / psd / layer_info / vector_mask.coffeelib / psd / layer_info / vector_origination.coffeelib / psd / layer_info / vector_stroke.coffeelib / psd / layer_info / vector_stroke_content.coffeelib / psd / layer_info.coffeelib / psd / layer_mask.coffeelib / psd / lazy_execute.coffeelib / psd / mask.coffeelib / psd / node.coffeelib / psd / nodes / ancestry.coffeelib / psd / nodes / build_preview.coffeelib / psd / nodes / group.coffeelib / psd / nodes / layer.coffeelib / psd / nodes / root.coffeelib / psd / nodes / search.coffeelib / psd / path_record.coffeelib / psd / resource.coffeelib / psd / resource_section.coffeelib / psd / resources / layer_comps.coffeelib / psd / resources.coffeelib / psd / util.coffeelib / psd.coffeeshims / init.coffeeshims / png.coffee

layer_mask.coffee

lib/psd/
_ = require 'lodash'
Util = require './util.coffee'
Layer = require './layer.coffee'

The layer mask is the overarching data structure that describes both the layers/groups in the PSD document, and the global mask. This part of the document is ordered as such:

  • Layers
  • Layer images
  • Global Mask

The file does not need to have a global mask. If there is none, then its length will be zero.

module.exports = class LayerMask
  constructor: (@file, @header) ->
    @layers = []
    @mergedAlpha = false
    @globalMask = null

  skip: -> @file.seek @file.readInt(), true

  parse: ->
    maskSize = @file.readInt()
    finish = maskSize + @file.tell()

    return if maskSize <= 0

    @parseLayers()
    @parseGlobalMask()

The layers are stored in the reverse order that we would like them. In other words, they're stored bottom to top and we want them top to bottom.

    @layers.reverse()

    @file.seek finish

  parseLayers: ->
    layerInfoSize = Util.pad2 @file.readInt()

    if layerInfoSize > 0
      layerCount = @file.readShort()

      if layerCount < 0
        layerCount = Math.abs layerCount
        @mergedAlpha = true

      for i in [0...layerCount]
        @layers.push new Layer(@file, @header).parse()

      layer.parseChannelImage() for layer in @layers

  parseGlobalMask: ->
    length = @file.readInt()
    return if length <= 0

    maskEnd = @file.tell() + length

    @globalMask = _({}).tap (mask) =>
      mask.overlayColorSpace = @file.readShort()
      mask.colorComponents = [
        @file.readShort() >> 8
        @file.readShort() >> 8
        @file.readShort() >> 8
        @file.readShort() >> 8
      ]

      mask.opacity = @file.readShort() / 16.0

0 = color selected, 1 = color protected, 128 = use value per layer

      mask.kind = @file.readByte()

    @file.seek maskEnd

generated Tue May 12 2015 11:08:14 GMT-0400 (EDT)