ynakajima/png2psd

View on GitHub
lib/psd/layer.js

Summary

Maintainability
A
1 hr
Test Coverage
'use strict';
var jDataView = require('jdataview');

/**
 * PSD Layer records
 * http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_13084
 */
function Layer() {
  this.top = 0;
  this.left = 0;
  this.width = 0;
  this.height = 0;
  this.blendmode = 'norm';
  this.opacity = 1;
  this.name = '';
  this.hasAlpha = true;
  this.channels = [];
}

/**
 * draw image
 * @param image {ImageData} image data
 */
Layer.prototype.drawImage = function(image) {
  this.width = image.width;
  this.height = image.height;
  this.hasAlpha = image.hasAlpha;
  this.channels = image.channels;
};

/**
 * return layer record binary data
 * @return {jDataView} layer record binary data
 */
Layer.prototype.toBinary = function() {
  var that = this;

  // Layer record
  var numChannel = this.channels.length;
  var layerRecordSize = 34 + 4 + 4 + 4 + (6 * numChannel);
  var layerRecord = new jDataView(layerRecordSize);

  // rectangle
  layerRecord.writeUint32(this.top); // top
  layerRecord.writeUint32(this.left); // left
  layerRecord.writeUint32(this.top + this.height); // bottom
  layerRecord.writeUint32(this.left + this.width); // right

  // number of channels in the layer 
  layerRecord.writeUint16(numChannel);
  
  // channnel infomation
  this.channels.forEach(function(channel, index) {
    // id
    var id = (that.hasAlpha && index === numChannel - 1) ? -1 : index;
    layerRecord.writeInt16(id); 

    // length
    var channelByteLength = channel.toBinary().byteLength;
    layerRecord.writeUint32(channelByteLength); 
  });

  // blend mode signature
  layerRecord.writeString('8BIM');

  // blend mode key
  layerRecord.writeString(this.blendmode);

  // opacity
  layerRecord.writeUint8(Math.round(this.opacity * 255));

  // clipping
  layerRecord.writeUint8(0); // base

  // flags
  layerRecord.writeUint8(parseInt('00001000', 2));

  // filler (zero)
  layerRecord.writeUint8(0);

  // length of the extra data field 
  layerRecord.writeUint32(4 + 4 + 4);

  // layer mask data
  layerRecord.writeUint32(0);

  // layer blending ranges data
  layerRecord.writeUint32(0); // length

  // Layer name: Pascal string, padded to a multiple of 4 bytes.
  layerRecord.writeUint8(3);
  layerRecord.writeUint8('P'.charCodeAt(0));
  layerRecord.writeUint8('N'.charCodeAt(0));
  layerRecord.writeUint8('G'.charCodeAt(0));

  return layerRecord;
};

/**
 * return channel Image binary data
 * @return {jDataView} channel Image binary data
 */
Layer.prototype.getChannelImageBinary = function() {
  var that = this;
  var channelImageData = Buffer.concat(that.channels.map(function(channel) {
    return channel.toBinary().buffer;
  }));

  return new jDataView(channelImageData);
};

module.exports = Layer;