"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.writeColor = exports.writePsd = exports.writeSection = exports.writeUnicodeStringWithPadding = exports.writeUnicodeString = exports.writePascalString = exports.writeSignature = exports.writeZeros = exports.writeBytes = exports.writeFixedPointPath32 = exports.writeFixedPoint32 = exports.writeFloat64 = exports.writeFloat32 = exports.writeUint32 = exports.writeInt32 = exports.writeUint16 = exports.writeInt16 = exports.writeUint8 = exports.getWriterBufferNoCopy = exports.getWriterBuffer = exports.createWriter = void 0; var helpers_1 = require("./helpers"); var additionalInfo_1 = require("./additionalInfo"); var imageResources_1 = require("./imageResources"); function createWriter(size) { if (size === void 0) { size = 4096; } var buffer = new ArrayBuffer(size); var view = new DataView(buffer); var offset = 0; return { buffer: buffer, view: view, offset: offset }; } exports.createWriter = createWriter; function getWriterBuffer(writer) { return writer.buffer.slice(0, writer.offset); } exports.getWriterBuffer = getWriterBuffer; function getWriterBufferNoCopy(writer) { return new Uint8Array(writer.buffer, 0, writer.offset); } exports.getWriterBufferNoCopy = getWriterBufferNoCopy; function writeUint8(writer, value) { var offset = addSize(writer, 1); writer.view.setUint8(offset, value); } exports.writeUint8 = writeUint8; function writeInt16(writer, value) { var offset = addSize(writer, 2); writer.view.setInt16(offset, value, false); } exports.writeInt16 = writeInt16; function writeUint16(writer, value) { var offset = addSize(writer, 2); writer.view.setUint16(offset, value, false); } exports.writeUint16 = writeUint16; function writeInt32(writer, value) { var offset = addSize(writer, 4); writer.view.setInt32(offset, value, false); } exports.writeInt32 = writeInt32; function writeUint32(writer, value) { var offset = addSize(writer, 4); writer.view.setUint32(offset, value, false); } exports.writeUint32 = writeUint32; function writeFloat32(writer, value) { var offset = addSize(writer, 4); writer.view.setFloat32(offset, value, false); } exports.writeFloat32 = writeFloat32; function writeFloat64(writer, value) { var offset = addSize(writer, 8); writer.view.setFloat64(offset, value, false); } exports.writeFloat64 = writeFloat64; // 32-bit fixed-point number 16.16 function writeFixedPoint32(writer, value) { writeInt32(writer, value * (1 << 16)); } exports.writeFixedPoint32 = writeFixedPoint32; // 32-bit fixed-point number 8.24 function writeFixedPointPath32(writer, value) { writeInt32(writer, value * (1 << 24)); } exports.writeFixedPointPath32 = writeFixedPointPath32; function writeBytes(writer, buffer) { if (buffer) { ensureSize(writer, writer.offset + buffer.length); var bytes = new Uint8Array(writer.buffer); bytes.set(buffer, writer.offset); writer.offset += buffer.length; } } exports.writeBytes = writeBytes; function writeZeros(writer, count) { for (var i = 0; i < count; i++) { writeUint8(writer, 0); } } exports.writeZeros = writeZeros; function writeSignature(writer, signature) { if (signature.length !== 4) throw new Error("Invalid signature: '".concat(signature, "'")); for (var i = 0; i < 4; i++) { writeUint8(writer, signature.charCodeAt(i)); } } exports.writeSignature = writeSignature; function writePascalString(writer, text, padTo) { var length = text.length; writeUint8(writer, length); for (var i = 0; i < length; i++) { var code = text.charCodeAt(i); writeUint8(writer, code < 128 ? code : '?'.charCodeAt(0)); } while (++length % padTo) { writeUint8(writer, 0); } } exports.writePascalString = writePascalString; function writeUnicodeString(writer, text) { writeUint32(writer, text.length); for (var i = 0; i < text.length; i++) { writeUint16(writer, text.charCodeAt(i)); } } exports.writeUnicodeString = writeUnicodeString; function writeUnicodeStringWithPadding(writer, text) { writeUint32(writer, text.length + 1); for (var i = 0; i < text.length; i++) { writeUint16(writer, text.charCodeAt(i)); } writeUint16(writer, 0); } exports.writeUnicodeStringWithPadding = writeUnicodeStringWithPadding; function getLargestLayerSize(layers) { if (layers === void 0) { layers = []; } var max = 0; for (var _i = 0, layers_1 = layers; _i < layers_1.length; _i++) { var layer = layers_1[_i]; if (layer.canvas || layer.imageData) { var _a = getLayerDimentions(layer), width = _a.width, height = _a.height; max = Math.max(max, 2 * height + 2 * width * height); } if (layer.children) { max = Math.max(max, getLargestLayerSize(layer.children)); } } return max; } function writeSection(writer, round, func, writeTotalLength, large) { if (writeTotalLength === void 0) { writeTotalLength = false; } if (large === void 0) { large = false; } if (large) writeUint32(writer, 0); var offset = writer.offset; writeUint32(writer, 0); func(); var length = writer.offset - offset - 4; var len = length; while ((len % round) !== 0) { writeUint8(writer, 0); len++; } if (writeTotalLength) { length = len; } writer.view.setUint32(offset, length, false); } exports.writeSection = writeSection; function writePsd(writer, psd, options) { if (options === void 0) { options = {}; } if (!(+psd.width > 0 && +psd.height > 0)) throw new Error('Invalid document size'); if ((psd.width > 30000 || psd.height > 30000) && !options.psb) throw new Error('Document size is too large (max is 30000x30000, use PSB format instead)'); var imageResources = psd.imageResources || {}; var opt = __assign(__assign({}, options), { layerIds: new Set(), layerToId: new Map() }); if (opt.generateThumbnail) { imageResources = __assign(__assign({}, imageResources), { thumbnail: createThumbnail(psd) }); } var imageData = psd.imageData; if (!imageData && psd.canvas) { imageData = psd.canvas.getContext('2d').getImageData(0, 0, psd.canvas.width, psd.canvas.height); } if (imageData && (psd.width !== imageData.width || psd.height !== imageData.height)) throw new Error('Document canvas must have the same size as document'); var globalAlpha = !!imageData && (0, helpers_1.hasAlpha)(imageData); var maxBufferSize = Math.max(getLargestLayerSize(psd.children), 4 * 2 * psd.width * psd.height + 2 * psd.height); var tempBuffer = new Uint8Array(maxBufferSize); // header writeSignature(writer, '8BPS'); writeUint16(writer, options.psb ? 2 : 1); // version writeZeros(writer, 6); writeUint16(writer, globalAlpha ? 4 : 3); // channels writeUint32(writer, psd.height); writeUint32(writer, psd.width); writeUint16(writer, 8); // bits per channel writeUint16(writer, 3 /* ColorMode.RGB */); // we only support saving RGB right now // color mode data writeSection(writer, 1, function () { // TODO: implement }); // image resources writeSection(writer, 1, function () { var _loop_1 = function (handler) { var has = handler.has(imageResources); var count = has === false ? 0 : (has === true ? 1 : has); var _loop_2 = function (i) { writeSignature(writer, '8BIM'); writeUint16(writer, handler.key); writePascalString(writer, '', 2); writeSection(writer, 2, function () { return handler.write(writer, imageResources, i); }); }; for (var i = 0; i < count; i++) { _loop_2(i); } }; for (var _i = 0, resourceHandlers_1 = imageResources_1.resourceHandlers; _i < resourceHandlers_1.length; _i++) { var handler = resourceHandlers_1[_i]; _loop_1(handler); } }); // layer and mask info writeSection(writer, 2, function () { writeLayerInfo(tempBuffer, writer, psd, globalAlpha, opt); writeGlobalLayerMaskInfo(writer, psd.globalLayerMaskInfo); writeAdditionalLayerInfo(writer, psd, psd, opt); }, undefined, !!opt.psb); // image data var channels = globalAlpha ? [0, 1, 2, 3] : [0, 1, 2]; var width = imageData ? imageData.width : psd.width; var height = imageData ? imageData.height : psd.height; var data = { data: new Uint8Array(width * height * 4), width: width, height: height }; writeUint16(writer, 1 /* Compression.RleCompressed */); // Photoshop doesn't support zip compression of composite image data if (helpers_1.RAW_IMAGE_DATA && psd.imageDataRaw) { console.log('writing raw image data'); writeBytes(writer, psd.imageDataRaw); } else { if (imageData) data.data.set(new Uint8Array(imageData.data.buffer, imageData.data.byteOffset, imageData.data.byteLength)); // add weird white matte if (globalAlpha) { var size = data.width * data.height * 4; var p = data.data; for (var i = 0; i < size; i += 4) { var pa = p[i + 3]; if (pa != 0 && pa != 255) { var a = pa / 255; var ra = 255 * (1 - a); p[i + 0] = p[i + 0] * a + ra; p[i + 1] = p[i + 1] * a + ra; p[i + 2] = p[i + 2] * a + ra; } } } writeBytes(writer, (0, helpers_1.writeDataRLE)(tempBuffer, data, channels, !!options.psb)); } } exports.writePsd = writePsd; function writeLayerInfo(tempBuffer, writer, psd, globalAlpha, options) { writeSection(writer, 4, function () { var _a; var layers = []; addChildren(layers, psd.children); if (!layers.length) layers.push({}); writeInt16(writer, globalAlpha ? -layers.length : layers.length); var layersData = layers.map(function (l, i) { return getChannels(tempBuffer, l, i === 0, options); }); var _loop_3 = function (layerData) { var layer = layerData.layer, top_1 = layerData.top, left = layerData.left, bottom = layerData.bottom, right = layerData.right, channels = layerData.channels; writeInt32(writer, top_1); writeInt32(writer, left); writeInt32(writer, bottom); writeInt32(writer, right); writeUint16(writer, channels.length); for (var _e = 0, channels_1 = channels; _e < channels_1.length; _e++) { var c = channels_1[_e]; writeInt16(writer, c.channelId); if (options.psb) writeUint32(writer, 0); writeUint32(writer, c.length); } writeSignature(writer, '8BIM'); writeSignature(writer, helpers_1.fromBlendMode[layer.blendMode] || 'norm'); writeUint8(writer, Math.round((0, helpers_1.clamp)((_a = layer.opacity) !== null && _a !== void 0 ? _a : 1, 0, 1) * 255)); writeUint8(writer, layer.clipping ? 1 : 0); var flags = 0x08; // 1 for Photoshop 5.0 and later, tells if bit 4 has useful information if (layer.transparencyProtected) flags |= 0x01; if (layer.hidden) flags |= 0x02; if (layer.vectorMask || (layer.sectionDivider && layer.sectionDivider.type !== 0 /* SectionDividerType.Other */)) { flags |= 0x10; // pixel data irrelevant to appearance of document } if (layer.effects && (0, additionalInfo_1.hasMultiEffects)(layer.effects)) { // TODO: this is not correct flags |= 0x20; // just guessing this one, might be completely incorrect } // if ('_2' in layer) flags |= 0x20; // TEMP!!! writeUint8(writer, flags); writeUint8(writer, 0); // filler writeSection(writer, 1, function () { writeLayerMaskData(writer, layer, layerData); writeLayerBlendingRanges(writer, psd); writePascalString(writer, layer.name || '', 4); writeAdditionalLayerInfo(writer, layer, psd, options); }); }; // layer records for (var _i = 0, layersData_1 = layersData; _i < layersData_1.length; _i++) { var layerData = layersData_1[_i]; _loop_3(layerData); } // layer channel image data for (var _b = 0, layersData_2 = layersData; _b < layersData_2.length; _b++) { var layerData = layersData_2[_b]; for (var _c = 0, _d = layerData.channels; _c < _d.length; _c++) { var channel = _d[_c]; writeUint16(writer, channel.compression); if (channel.buffer) { writeBytes(writer, channel.buffer); } } } }, true, options.psb); } function writeLayerMaskData(writer, _a, layerData) { var mask = _a.mask; writeSection(writer, 1, function () { if (!mask) return; var m = layerData.mask || {}; writeInt32(writer, m.top); writeInt32(writer, m.left); writeInt32(writer, m.bottom); writeInt32(writer, m.right); writeUint8(writer, mask.defaultColor); var params = 0; if (mask.userMaskDensity !== undefined) params |= 1 /* MaskParams.UserMaskDensity */; if (mask.userMaskFeather !== undefined) params |= 2 /* MaskParams.UserMaskFeather */; if (mask.vectorMaskDensity !== undefined) params |= 4 /* MaskParams.VectorMaskDensity */; if (mask.vectorMaskFeather !== undefined) params |= 8 /* MaskParams.VectorMaskFeather */; var flags = 0; if (mask.disabled) flags |= 2 /* LayerMaskFlags.LayerMaskDisabled */; if (mask.positionRelativeToLayer) flags |= 1 /* LayerMaskFlags.PositionRelativeToLayer */; if (mask.fromVectorData) flags |= 8 /* LayerMaskFlags.LayerMaskFromRenderingOtherData */; if (params) flags |= 16 /* LayerMaskFlags.MaskHasParametersAppliedToIt */; writeUint8(writer, flags); if (params) { writeUint8(writer, params); if (mask.userMaskDensity !== undefined) writeUint8(writer, Math.round(mask.userMaskDensity * 0xff)); if (mask.userMaskFeather !== undefined) writeFloat64(writer, mask.userMaskFeather); if (mask.vectorMaskDensity !== undefined) writeUint8(writer, Math.round(mask.vectorMaskDensity * 0xff)); if (mask.vectorMaskFeather !== undefined) writeFloat64(writer, mask.vectorMaskFeather); } // TODO: handle rest of the fields writeZeros(writer, 2); }); } function writeLayerBlendingRanges(writer, psd) { writeSection(writer, 1, function () { writeUint32(writer, 65535); writeUint32(writer, 65535); var channels = psd.channels || 0; // TODO: use always 4 instead ? // channels = 4; // TESTING for (var i = 0; i < channels; i++) { writeUint32(writer, 65535); writeUint32(writer, 65535); } }); } function writeGlobalLayerMaskInfo(writer, info) { writeSection(writer, 1, function () { if (info) { writeUint16(writer, info.overlayColorSpace); writeUint16(writer, info.colorSpace1); writeUint16(writer, info.colorSpace2); writeUint16(writer, info.colorSpace3); writeUint16(writer, info.colorSpace4); writeUint16(writer, info.opacity * 0xff); writeUint8(writer, info.kind); writeZeros(writer, 3); } }); } function writeAdditionalLayerInfo(writer, target, psd, options) { var _loop_4 = function (handler) { var key = handler.key; if (key === 'Txt2' && options.invalidateTextLayers) return "continue"; if (key === 'vmsk' && options.psb) key = 'vsms'; if (handler.has(target)) { var large = options.psb && helpers_1.largeAdditionalInfoKeys.indexOf(key) !== -1; writeSignature(writer, large ? '8B64' : '8BIM'); writeSignature(writer, key); var fourBytes = key === 'Txt2' || key === 'luni' || key === 'vmsk' || key === 'artb' || key === 'artd' || key === 'vogk' || key === 'SoLd' || key === 'lnk2' || key === 'vscg' || key === 'vsms' || key === 'GdFl' || key === 'lmfx' || key === 'lrFX' || key === 'cinf' || key === 'PlLd' || key === 'Anno'; writeSection(writer, fourBytes ? 4 : 2, function () { handler.write(writer, target, psd, options); }, key !== 'Txt2' && key !== 'cinf' && key !== 'extn', large); } }; for (var _i = 0, infoHandlers_1 = additionalInfo_1.infoHandlers; _i < infoHandlers_1.length; _i++) { var handler = infoHandlers_1[_i]; _loop_4(handler); } } function addChildren(layers, children) { if (!children) return; for (var _i = 0, children_1 = children; _i < children_1.length; _i++) { var c = children_1[_i]; if (c.children && c.canvas) throw new Error("Invalid layer, cannot have both 'canvas' and 'children' properties"); if (c.children && c.imageData) throw new Error("Invalid layer, cannot have both 'imageData' and 'children' properties"); if (c.children) { layers.push({ name: '', sectionDivider: { type: 3 /* SectionDividerType.BoundingSectionDivider */, }, // TESTING // nameSource: 'lset', // id: [4, 0, 0, 8, 11, 0, 0, 0, 0, 14][layers.length] || 0, // layerColor: 'none', // timestamp: [1611346817.349021, 0, 0, 1611346817.349175, 1611346817.3491833, 0, 0, 0, 0, 1611346817.349832][layers.length] || 0, // protected: {}, // referencePoint: { x: 0, y: 0 }, }); addChildren(layers, c.children); layers.push(__assign({ sectionDivider: { type: c.opened === false ? 2 /* SectionDividerType.ClosedFolder */ : 1 /* SectionDividerType.OpenFolder */, key: helpers_1.fromBlendMode[c.blendMode] || 'pass', subType: 0, } }, c)); } else { layers.push(__assign({}, c)); } } } function resizeBuffer(writer, size) { var newLength = writer.buffer.byteLength; do { newLength *= 2; } while (size > newLength); var newBuffer = new ArrayBuffer(newLength); var newBytes = new Uint8Array(newBuffer); var oldBytes = new Uint8Array(writer.buffer); newBytes.set(oldBytes); writer.buffer = newBuffer; writer.view = new DataView(writer.buffer); } function ensureSize(writer, size) { if (size > writer.buffer.byteLength) { resizeBuffer(writer, size); } } function addSize(writer, size) { var offset = writer.offset; ensureSize(writer, writer.offset += size); return offset; } function createThumbnail(psd) { var canvas = (0, helpers_1.createCanvas)(10, 10); var scale = 1; if (psd.width > psd.height) { canvas.width = 160; canvas.height = Math.floor(psd.height * (canvas.width / psd.width)); scale = canvas.width / psd.width; } else { canvas.height = 160; canvas.width = Math.floor(psd.width * (canvas.height / psd.height)); scale = canvas.height / psd.height; } var context = canvas.getContext('2d'); context.scale(scale, scale); if (psd.imageData) { var temp = (0, helpers_1.createCanvas)(psd.imageData.width, psd.imageData.height); temp.getContext('2d').putImageData(psd.imageData, 0, 0); context.drawImage(temp, 0, 0); } else if (psd.canvas) { context.drawImage(psd.canvas, 0, 0); } return canvas; } function getChannels(tempBuffer, layer, background, options) { var layerData = getLayerChannels(tempBuffer, layer, background, options); var mask = layer.mask; if (mask) { var top_2 = mask.top | 0; var left = mask.left | 0; var right = mask.right | 0; var bottom = mask.bottom | 0; var _a = getLayerDimentions(mask), width = _a.width, height = _a.height; var imageData = mask.imageData; if (!imageData && mask.canvas && width && height) { imageData = mask.canvas.getContext('2d').getImageData(0, 0, width, height); } if (width && height && imageData) { right = left + width; bottom = top_2 + height; if (imageData.width !== width || imageData.height !== height) { throw new Error('Invalid imageData dimentions'); } var buffer = void 0; var compression = void 0; if (helpers_1.RAW_IMAGE_DATA && layer.maskDataRaw) { // console.log('written raw layer image data'); buffer = layer.maskDataRaw; compression = 1 /* Compression.RleCompressed */; } else if (options.compress) { buffer = (0, helpers_1.writeDataZipWithoutPrediction)(imageData, [0]); compression = 2 /* Compression.ZipWithoutPrediction */; } else { buffer = (0, helpers_1.writeDataRLE)(tempBuffer, imageData, [0], !!options.psb); compression = 1 /* Compression.RleCompressed */; } layerData.mask = { top: top_2, left: left, right: right, bottom: bottom }; layerData.channels.push({ channelId: -2 /* ChannelID.UserMask */, compression: compression, buffer: buffer, length: 2 + buffer.length }); } else { layerData.mask = { top: 0, left: 0, right: 0, bottom: 0 }; layerData.channels.push({ channelId: -2 /* ChannelID.UserMask */, compression: 0 /* Compression.RawData */, buffer: new Uint8Array(0), length: 0 }); } } return layerData; } function getLayerDimentions(_a) { var canvas = _a.canvas, imageData = _a.imageData; return imageData || canvas || { width: 0, height: 0 }; } function cropImageData(data, left, top, width, height) { var croppedData = (0, helpers_1.createImageData)(width, height); var srcData = data.data; var dstData = croppedData.data; for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var src = ((x + left) + (y + top) * width) * 4; var dst = (x + y * width) * 4; dstData[dst] = srcData[src]; dstData[dst + 1] = srcData[src + 1]; dstData[dst + 2] = srcData[src + 2]; dstData[dst + 3] = srcData[src + 3]; } } return croppedData; } function getLayerChannels(tempBuffer, layer, background, options) { var _a; var top = layer.top | 0; var left = layer.left | 0; var right = layer.right | 0; var bottom = layer.bottom | 0; var channels = [ { channelId: -1 /* ChannelID.Transparency */, compression: 0 /* Compression.RawData */, buffer: undefined, length: 2 }, { channelId: 0 /* ChannelID.Color0 */, compression: 0 /* Compression.RawData */, buffer: undefined, length: 2 }, { channelId: 1 /* ChannelID.Color1 */, compression: 0 /* Compression.RawData */, buffer: undefined, length: 2 }, { channelId: 2 /* ChannelID.Color2 */, compression: 0 /* Compression.RawData */, buffer: undefined, length: 2 }, ]; var _b = getLayerDimentions(layer), width = _b.width, height = _b.height; if (!(layer.canvas || layer.imageData) || !width || !height) { right = left; bottom = top; return { layer: layer, top: top, left: left, right: right, bottom: bottom, channels: channels }; } right = left + width; bottom = top + height; var data = layer.imageData || layer.canvas.getContext('2d').getImageData(0, 0, width, height); if (options.trimImageData) { var trimmed = trimData(data); if (trimmed.left !== 0 || trimmed.top !== 0 || trimmed.right !== data.width || trimmed.bottom !== data.height) { left += trimmed.left; top += trimmed.top; right -= (data.width - trimmed.right); bottom -= (data.height - trimmed.bottom); width = right - left; height = bottom - top; if (!width || !height) { return { layer: layer, top: top, left: left, right: right, bottom: bottom, channels: channels }; } if (layer.imageData) { data = cropImageData(data, trimmed.left, trimmed.top, width, height); } else { data = layer.canvas.getContext('2d').getImageData(trimmed.left, trimmed.top, width, height); } } } var channelIds = [ 0 /* ChannelID.Color0 */, 1 /* ChannelID.Color1 */, 2 /* ChannelID.Color2 */, ]; if (!background || options.noBackground || layer.mask || (0, helpers_1.hasAlpha)(data) || (helpers_1.RAW_IMAGE_DATA && ((_a = layer.imageDataRaw) === null || _a === void 0 ? void 0 : _a['-1']))) { channelIds.unshift(-1 /* ChannelID.Transparency */); } channels = channelIds.map(function (channelId) { var offset = (0, helpers_1.offsetForChannel)(channelId, false); // TODO: psd.colorMode === ColorMode.CMYK); var buffer; var compression; if (helpers_1.RAW_IMAGE_DATA && layer.imageDataRaw) { // console.log('written raw layer image data'); buffer = layer.imageDataRaw[channelId]; compression = 1 /* Compression.RleCompressed */; } else if (options.compress) { buffer = (0, helpers_1.writeDataZipWithoutPrediction)(data, [offset]); compression = 2 /* Compression.ZipWithoutPrediction */; } else { buffer = (0, helpers_1.writeDataRLE)(tempBuffer, data, [offset], !!options.psb); compression = 1 /* Compression.RleCompressed */; } return { channelId: channelId, compression: compression, buffer: buffer, length: 2 + buffer.length }; }); return { layer: layer, top: top, left: left, right: right, bottom: bottom, channels: channels }; } function isRowEmpty(_a, y, left, right) { var data = _a.data, width = _a.width; var start = ((y * width + left) * 4 + 3) | 0; var end = (start + (right - left) * 4) | 0; for (var i = start; i < end; i = (i + 4) | 0) { if (data[i] !== 0) { return false; } } return true; } function isColEmpty(_a, x, top, bottom) { var data = _a.data, width = _a.width; var stride = (width * 4) | 0; var start = (top * stride + x * 4 + 3) | 0; for (var y = top, i = start; y < bottom; y++, i = (i + stride) | 0) { if (data[i] !== 0) { return false; } } return true; } function trimData(data) { var top = 0; var left = 0; var right = data.width; var bottom = data.height; while (top < bottom && isRowEmpty(data, top, left, right)) top++; while (bottom > top && isRowEmpty(data, bottom - 1, left, right)) bottom--; while (left < right && isColEmpty(data, left, top, bottom)) left++; while (right > left && isColEmpty(data, right - 1, top, bottom)) right--; return { top: top, left: left, right: right, bottom: bottom }; } function writeColor(writer, color) { if (!color) { writeUint16(writer, 0 /* ColorSpace.RGB */); writeZeros(writer, 8); } else if ('r' in color) { writeUint16(writer, 0 /* ColorSpace.RGB */); writeUint16(writer, Math.round(color.r * 257)); writeUint16(writer, Math.round(color.g * 257)); writeUint16(writer, Math.round(color.b * 257)); writeUint16(writer, 0); } else if ('fr' in color) { writeUint16(writer, 0 /* ColorSpace.RGB */); writeUint16(writer, Math.round(color.fr * 255 * 257)); writeUint16(writer, Math.round(color.fg * 255 * 257)); writeUint16(writer, Math.round(color.fb * 255 * 257)); writeUint16(writer, 0); } else if ('l' in color) { writeUint16(writer, 7 /* ColorSpace.Lab */); writeInt16(writer, Math.round(color.l * 10000)); writeInt16(writer, Math.round(color.a < 0 ? (color.a * 12800) : (color.a * 12700))); writeInt16(writer, Math.round(color.b < 0 ? (color.b * 12800) : (color.b * 12700))); writeUint16(writer, 0); } else if ('h' in color) { writeUint16(writer, 1 /* ColorSpace.HSB */); writeUint16(writer, Math.round(color.h * 0xffff)); writeUint16(writer, Math.round(color.s * 0xffff)); writeUint16(writer, Math.round(color.b * 0xffff)); writeUint16(writer, 0); } else if ('c' in color) { writeUint16(writer, 2 /* ColorSpace.CMYK */); writeUint16(writer, Math.round(color.c * 257)); writeUint16(writer, Math.round(color.m * 257)); writeUint16(writer, Math.round(color.y * 257)); writeUint16(writer, Math.round(color.k * 257)); } else { writeUint16(writer, 8 /* ColorSpace.Grayscale */); writeUint16(writer, Math.round(color.k * 10000 / 255)); writeZeros(writer, 6); } } exports.writeColor = writeColor; //# sourceMappingURL=psdWriter.js.map