├── .gitignore ├── .npmignore ├── LICENSE.md ├── README.md ├── decode.js ├── encode.js ├── index.js ├── package.json ├── sample.ase ├── sample.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | bundle.js 2 | npm-debug.log 3 | .DS_Store 4 | node_modules 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | bundle.js 2 | npm-debug.log 3 | .DS_Store 4 | node_modules 5 | test 6 | fixtures 7 | test.js 8 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## The MIT License (MIT) ## 2 | 3 | Copyright (c) 2014 Hugh Kennedy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # adobe-swatch-exchange [![experimental](http://hughsk.github.io/stability-badges/dist/experimental.svg)](http://github.com/hughsk/stability-badges) # 2 | 3 | Encode/decode color palettes in Adobe's `.ase` format. 4 | 5 | ## Usage ## 6 | 7 | [![adobe-swatch-exchange](https://nodei.co/npm/adobe-swatch-exchange.png?mini=true)](https://nodei.co/npm/adobe-swatch-exchange) 8 | 9 | ### ase.decode(buffer) ### 10 | 11 | Returns a JSON object representing the contents of the `.ase` file, for example: 12 | 13 | ``` json 14 | { 15 | "version": "1.0", 16 | "groups": [], 17 | "colors": [{ 18 | "name": "RGB Red", 19 | "model": "RGB", 20 | "color": [1, 0, 0], 21 | "type": "global" 22 | }, { 23 | "name": "RGB Yellow", 24 | "model": "RGB", 25 | "color": [1, 1, 0], 26 | "type": "global" 27 | }] 28 | } 29 | ``` 30 | 31 | ## License ## 32 | 33 | MIT. See [LICENSE.md](http://github.com/hughsk/adobe-swatch-exchange/blob/master/LICENSE.md) for details. 34 | -------------------------------------------------------------------------------- /decode.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert') 2 | 3 | module.exports = decode 4 | 5 | var errors = { 6 | header: 'Not a valid .ASE file' 7 | , unexpected: 'Unexpected state. This is a bug!' 8 | } 9 | 10 | var COLOR_START = 0x0001 11 | var GROUP_START = 0xc001 12 | var GROUP_END = 0xc002 13 | 14 | var MODE_COLOR = 1 15 | var MODE_GROUP = 2 16 | 17 | var STATE_GET_MODE = 1 18 | var STATE_GET_LENGTH = 2 19 | var STATE_GET_NAME = 3 20 | var STATE_GET_MODEL = 4 21 | var STATE_GET_COLOR = 5 22 | var STATE_GET_TYPE = 6 23 | 24 | var colorSizes = { 25 | CMYK: 4 26 | , RGB: 3 27 | , LAB: 3 28 | , GRAY: 1 29 | } 30 | 31 | var colorTypes = { 32 | 0: 'global' 33 | , 1: 'spot' 34 | , 2: 'normal' 35 | } 36 | 37 | function decode(buffer) { 38 | if (typeof buffer === 'string') { 39 | buffer = Buffer(buffer) 40 | } 41 | 42 | var output = {} 43 | var groups = output.groups = [] 44 | var colors = output.colors = [] 45 | 46 | assert(getChar8(0) === 'A', errors.header) 47 | assert(getChar8(1) === 'S', errors.header) 48 | assert(getChar8(2) === 'E', errors.header) 49 | assert(getChar8(3) === 'F', errors.header) 50 | 51 | output.version = [ 52 | buffer.readUInt16BE(4) 53 | , buffer.readUInt16BE(6) 54 | ].join('.') 55 | 56 | var blocks = buffer.readUInt32BE(8) 57 | var state = STATE_GET_MODE 58 | var mode = MODE_COLOR 59 | var position = 12 60 | var blockLength 61 | var block 62 | var group 63 | var color 64 | 65 | x: while (position < buffer.length) { 66 | switch (state) { 67 | case STATE_GET_MODE: readBlockMode(); continue x 68 | case STATE_GET_LENGTH: readBlockLength(); continue x 69 | case STATE_GET_NAME: readBlockName(); continue x 70 | case STATE_GET_MODEL: readBlockModel(); continue x 71 | case STATE_GET_COLOR: readBlockColor(); continue x 72 | case STATE_GET_TYPE: readBlockType(); continue x 73 | } 74 | 75 | throw new Error(errors.unexpected) 76 | } 77 | 78 | return output 79 | 80 | function readBlockMode() { 81 | switch (buffer.readUInt16BE(position)) { 82 | case COLOR_START: colors.push(block = color = {}); break 83 | case GROUP_START: groups.push(block = group = { colors: [] }); break 84 | case GROUP_END: group = null; break 85 | 86 | default: 87 | throw new Error('Unexpected block type at byte #' + position) 88 | } 89 | 90 | if (group && block === color) { 91 | group.colors.push(color) 92 | } 93 | 94 | position += 2 95 | state = STATE_GET_LENGTH 96 | } 97 | 98 | function readBlockLength() { 99 | blockLength = buffer.readUInt32BE(position) 100 | position += 4 101 | state = STATE_GET_NAME 102 | } 103 | 104 | function readBlockName() { 105 | var length = buffer.readUInt16BE(position) 106 | var name = '' 107 | 108 | while (--length) { 109 | name += getChar16(position += 2) 110 | } 111 | 112 | position += 4 113 | block.name = name 114 | 115 | state = mode === MODE_GROUP 116 | ? STATE_GET_MODE 117 | : STATE_GET_MODEL 118 | } 119 | 120 | function readBlockModel() { 121 | block.model = ( 122 | getChar8(position++) + 123 | getChar8(position++) + 124 | getChar8(position++) + 125 | getChar8(position++) 126 | ).trim() 127 | 128 | state = STATE_GET_COLOR 129 | } 130 | 131 | function readBlockColor() { 132 | var model = block.model.toUpperCase() 133 | var count = colorSizes[model] 134 | var channels = [] 135 | 136 | while (count--) { 137 | channels.push(buffer.readFloatBE(position)) 138 | position += 4 139 | } 140 | 141 | block.color = channels 142 | 143 | state = STATE_GET_TYPE 144 | } 145 | 146 | function readBlockType() { 147 | block.type = colorTypes[buffer.readUInt16BE(position)] 148 | position += 2 149 | state = STATE_GET_MODE 150 | } 151 | 152 | function getChar8(index) { 153 | return String.fromCharCode(buffer.readUInt8(index)) 154 | } 155 | 156 | function getChar16(index) { 157 | return String.fromCharCode(buffer.readUInt16BE(index)) 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /encode.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | throw new Error([ 3 | "ase.encode isn't implemented yet." 4 | , "Please bug me or send through a pull request!" 5 | ].join('\n')) 6 | } 7 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | encode: require('./encode') 3 | , decode: require('./decode') 4 | } 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "adobe-swatch-exchange", 3 | "description": "Encode/decode color palettes in Adobe's .ase format", 4 | "version": "0.0.0", 5 | "main": "index.js", 6 | "dependencies": {}, 7 | "devDependencies": { 8 | "tape": "^2.12.3", 9 | "faucet": "^0.0.1" 10 | }, 11 | "scripts": { 12 | "test": "node test | faucet" 13 | }, 14 | "author": "Hugh Kennedy (http://hughsk.io/)", 15 | "license": "MIT", 16 | "homepage": "http://hughsk.github.io/adobe-swatch-exchange", 17 | "repository": { 18 | "type": "git", 19 | "url": "git://github.com/hughsk/adobe-swatch-exchange" 20 | }, 21 | "bugs": { 22 | "url": "https://github.com/hughsk/adobe-swatch-exchange/issues" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /sample.ase: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/adobe-swatch-exchange/992b521d354a2210c6550fbb20150b4588508a96/sample.ase -------------------------------------------------------------------------------- /sample.json: -------------------------------------------------------------------------------- 1 | {"groups":[],"colors":[{"name":"RGB Red","model":"RGB","color":[1,0,0],"type":"global"},{"name":"RGB Yellow","model":"RGB","color":[1,1,0],"type":"global"},{"name":"RGB Green","model":"RGB","color":[0,1,0],"type":"global"},{"name":"RGB Cyan","model":"RGB","color":[0,1,1],"type":"global"},{"name":"RGB Blue","model":"RGB","color":[0,0,1],"type":"global"},{"name":"RGB Magenta","model":"RGB","color":[1,0,1],"type":"global"},{"name":"White","model":"Gray","color":[1],"type":"global"},{"name":"10% Gray","model":"Gray","color":[0.8999999761581421],"type":"global"},{"name":"15% Gray","model":"Gray","color":[0.8499999642372131],"type":"global"},{"name":"20% Gray","model":"Gray","color":[0.7999999523162842],"type":"global"},{"name":"25% Gray","model":"Gray","color":[0.75],"type":"global"},{"name":"30% Gray","model":"Gray","color":[0.699999988079071],"type":"global"},{"name":"35% Gray","model":"Gray","color":[0.6499999761581421],"type":"global"},{"name":"40% Gray","model":"Gray","color":[0.5999999642372131],"type":"global"},{"name":"45% Gray","model":"Gray","color":[0.550000011920929],"type":"global"},{"name":"50% Gray","model":"Gray","color":[0.5],"type":"global"},{"name":"CMYK Red","model":"CMYK","color":[0,1,1,0],"type":"global"},{"name":"CMYK Yellow","model":"CMYK","color":[0,0,1,0],"type":"global"},{"name":"CMYK Green","model":"CMYK","color":[1,0,1,0],"type":"global"},{"name":"CMYK Cyan","model":"CMYK","color":[1,0,0,0],"type":"global"},{"name":"CMYK Blue","model":"CMYK","color":[1,1,0,0],"type":"global"},{"name":"CMYK Magenta","model":"CMYK","color":[0,1,0,0],"type":"global"},{"name":"55% Gray","model":"Gray","color":[0.44999998807907104],"type":"global"},{"name":"60% Gray","model":"Gray","color":[0.3999999761581421],"type":"global"},{"name":"65% Gray","model":"Gray","color":[0.3499999940395355],"type":"global"},{"name":"70% Gray","model":"Gray","color":[0.29999998211860657],"type":"global"},{"name":"75% Gray","model":"Gray","color":[0.25],"type":"global"},{"name":"80% Gray","model":"Gray","color":[0.19999998807907104],"type":"global"},{"name":"85% Gray","model":"Gray","color":[0.14999999105930328],"type":"global"},{"name":"90% Gray","model":"Gray","color":[0.09999999403953552],"type":"global"},{"name":"95% Gray","model":"Gray","color":[0.04999999701976776],"type":"global"},{"name":"Black","model":"Gray","color":[0],"type":"global"},{"name":"Pastel Red","model":"CMYK","color":[0,0.5,0.5,0],"type":"global"},{"name":"Pastel Red Orange","model":"CMYK","color":[0,0.3800048828125,0.5,0],"type":"global"},{"name":"Pastel Yellow Orange","model":"CMYK","color":[0,0.250091552734375,0.5,0],"type":"global"},{"name":"Pastel Yellow","model":"CMYK","color":[0,0,0.5,0],"type":"global"},{"name":"Pastel Pea Green","model":"CMYK","color":[0.250091552734375,0,0.5,0],"type":"global"},{"name":"Pastel Yellow Green","model":"CMYK","color":[0.3800048828125,0,0.5,0],"type":"global"},{"name":"Pastel Green","model":"CMYK","color":[0.5,0,0.5,0],"type":"global"},{"name":"Pastel Green Cyan","model":"CMYK","color":[0.5,0,0.250091552734375,0],"type":"global"},{"name":"Pastel Cyan","model":"CMYK","color":[0.5,0,0,0],"type":"global"},{"name":"Pastel Cyan Blue","model":"CMYK","color":[0.5,0.250091552734375,0,0],"type":"global"},{"name":"Pastel Blue","model":"CMYK","color":[0.5,0.3800048828125,0,0],"type":"global"},{"name":"Pastel Blue Violet","model":"CMYK","color":[0.5,0.5,0,0],"type":"global"},{"name":"Pastel Violet","model":"CMYK","color":[0.3800048828125,0.5,0,0],"type":"global"},{"name":"Pastel Violet Magenta","model":"CMYK","color":[0.250091552734375,0.5,0,0],"type":"global"},{"name":"Pastel Magenta","model":"CMYK","color":[0,0.5,0,0],"type":"global"},{"name":"Pastel Magenta Red","model":"CMYK","color":[0,0.5,0.250091552734375,0],"type":"global"},{"name":"Light Red","model":"CMYK","color":[0,0.720001220703125,0.720001220703125,0],"type":"global"},{"name":"Light Red Orange","model":"CMYK","color":[0,0.54010009765625,0.720001220703125,0],"type":"global"},{"name":"Light Yellow Orange","model":"CMYK","color":[0,0.360107421875,0.720001220703125,0],"type":"global"},{"name":"Light Yellow","model":"CMYK","color":[0,0,0.720001220703125,0],"type":"global"},{"name":"Light Pea Green","model":"CMYK","color":[0.360107421875,0,0.720001220703125,0],"type":"global"},{"name":"Light Yellow Green","model":"CMYK","color":[0.54010009765625,0,0.720001220703125,0],"type":"global"},{"name":"Light Green","model":"CMYK","color":[0.720001220703125,0,0.720001220703125,0],"type":"global"},{"name":"Light Green Cyan","model":"CMYK","color":[0.720001220703125,0,0.360107421875,0],"type":"global"},{"name":"Light Cyan","model":"CMYK","color":[0.720001220703125,0,0,0],"type":"global"},{"name":"Light Cyan Blue","model":"CMYK","color":[0.720001220703125,0.360107421875,0,0],"type":"global"},{"name":"Light Blue","model":"CMYK","color":[0.720001220703125,0.54010009765625,0,0],"type":"global"},{"name":"Light Blue Violet","model":"CMYK","color":[0.720001220703125,0.720001220703125,0,0],"type":"global"},{"name":"Light Violet","model":"CMYK","color":[0.54010009765625,0.720001220703125,0,0],"type":"global"},{"name":"Light Violet Magenta","model":"CMYK","color":[0.360107421875,0.720001220703125,0,0],"type":"global"},{"name":"Light Magenta","model":"CMYK","color":[0,0.720001220703125,0,0],"type":"global"},{"name":"Light Magenta Red","model":"CMYK","color":[0,0.720001220703125,0.360107421875,0],"type":"global"},{"name":"Pure Red","model":"CMYK","color":[0,1,1,0],"type":"global"},{"name":"Pure Red Orange","model":"CMYK","color":[0,0.75,1,0],"type":"global"},{"name":"Pure Yellow Orange","model":"CMYK","color":[0,0.5,1,0],"type":"global"},{"name":"Pure Yellow","model":"CMYK","color":[0,0,1,0],"type":"global"},{"name":"Pure Pea Green","model":"CMYK","color":[0.5,0,1,0],"type":"global"},{"name":"Pure Yellow Green","model":"CMYK","color":[0.75,0,1,0],"type":"global"},{"name":"Pure Green","model":"CMYK","color":[1,0,1,0],"type":"global"},{"name":"Pure Green Cyan","model":"CMYK","color":[1,0,0.5,0],"type":"global"},{"name":"Pure Cyan","model":"CMYK","color":[1,0,0,0],"type":"global"},{"name":"Pure Cyan Blue","model":"CMYK","color":[1,0.5,0,0],"type":"global"},{"name":"Pure Blue","model":"CMYK","color":[1,0.75,0,0],"type":"global"},{"name":"Pure Blue Violet","model":"CMYK","color":[1,1,0,0],"type":"global"},{"name":"Pure Violet","model":"CMYK","color":[0.75,1,0,0],"type":"global"},{"name":"Pure Violet Magenta","model":"CMYK","color":[0.5,1,0,0],"type":"global"},{"name":"Pure Magenta","model":"CMYK","color":[0,1,0,0],"type":"global"},{"name":"Pure Magenta Red","model":"CMYK","color":[0,1,0.5,0],"type":"global"},{"name":"Dark Red","model":"CMYK","color":[0,1,1,0.399993896484375],"type":"global"},{"name":"Dark Red Orange","model":"CMYK","color":[0,0.75,1,0.399993896484375],"type":"global"},{"name":"Dark Yellow Orange","model":"CMYK","color":[0,0.5,1,0.399993896484375],"type":"global"},{"name":"Dark Yellow","model":"CMYK","color":[0,0,1,0.399993896484375],"type":"global"},{"name":"Dark Pea Green","model":"CMYK","color":[0.5,0,1,0.399993896484375],"type":"global"},{"name":"Dark Yellow Green","model":"CMYK","color":[0.75,0,1,0.399993896484375],"type":"global"},{"name":"Dark Green","model":"CMYK","color":[1,0,1,0.399993896484375],"type":"global"},{"name":"Dark Green Cyan","model":"CMYK","color":[1,0,0.5,0.399993896484375],"type":"global"},{"name":"Dark Cyan","model":"CMYK","color":[1,0,0,0.399993896484375],"type":"global"},{"name":"Dark Cyan Blue","model":"CMYK","color":[1,0.5,0,0.399993896484375],"type":"global"},{"name":"Dark Blue","model":"CMYK","color":[1,0.75,0,0.399993896484375],"type":"global"},{"name":"Dark Blue Violet","model":"CMYK","color":[1,1,0,0.399993896484375],"type":"global"},{"name":"Dark Violet","model":"CMYK","color":[0.75,1,0,0.399993896484375],"type":"global"},{"name":"Dark Violet Magenta","model":"CMYK","color":[0.5,1,0,0.399993896484375],"type":"global"},{"name":"Dark Magenta","model":"CMYK","color":[0,1,0,0.399993896484375],"type":"global"},{"name":"Dark Magenta Red","model":"CMYK","color":[0,1,0.5,0.399993896484375],"type":"global"},{"name":"Darker Red","model":"CMYK","color":[0,1,1,0.600006103515625],"type":"global"},{"name":"Darker Red Orange","model":"CMYK","color":[0,0.75,1,0.600006103515625],"type":"global"},{"name":"Darker Yellow Orange","model":"CMYK","color":[0,0.5,1,0.600006103515625],"type":"global"},{"name":"Darker Yellow","model":"CMYK","color":[0,0,1,0.600006103515625],"type":"global"},{"name":"Darker Pea Green","model":"CMYK","color":[0.5,0,1,0.600006103515625],"type":"global"},{"name":"Darker Yellow Green","model":"CMYK","color":[0.75,0,1,0.600006103515625],"type":"global"},{"name":"Darker Green","model":"CMYK","color":[1,0,1,0.600006103515625],"type":"global"},{"name":"Darker Green Cyan","model":"CMYK","color":[1,0,0.5,0.600006103515625],"type":"global"},{"name":"Darker Cyan","model":"CMYK","color":[1,0,0,0.600006103515625],"type":"global"},{"name":"Darker Cyan Blue","model":"CMYK","color":[1,0.5,0,0.600006103515625],"type":"global"},{"name":"Darker Blue","model":"CMYK","color":[1,0.75,0,0.600006103515625],"type":"global"},{"name":"Darker Blue Violet","model":"CMYK","color":[1,1,0,0.600006103515625],"type":"global"},{"name":"Darker Violet","model":"CMYK","color":[0.75,1,0,0.600006103515625],"type":"global"},{"name":"Darker Violet Magenta","model":"CMYK","color":[0.5,1,0,0.600006103515625],"type":"global"},{"name":"Darker Magenta","model":"CMYK","color":[0,1,0,0.600006103515625],"type":"global"},{"name":"Darker Magenta Red","model":"CMYK","color":[0,1,0.5,0.600006103515625],"type":"global"},{"name":"Pale Cool Brown","model":"CMYK","color":[0,0.1199951171875,0.250091552734375,0.250091552734375],"type":"global"},{"name":"Light Cool Brown","model":"CMYK","color":[0.18829345703125,0.27850341796875,0.3765869140625,0.313690185546875],"type":"global"},{"name":"Medium Cool Brown","model":"CMYK","color":[0.3765869140625,0.435302734375,0.502105712890625,0.3765869140625],"type":"global"},{"name":"Dark Cool Brown","model":"CMYK","color":[0.564788818359375,0.596099853515625,0.62750244140625,0.435302734375],"type":"global"},{"name":"Darker Cool Brown","model":"CMYK","color":[0.75,0.75,0.75,0.5],"type":"global"},{"name":"Pale Warm Brown","model":"CMYK","color":[0,0.250091552734375,0.5,0.250091552734375],"type":"global"},{"name":"Light Warm Brown","model":"CMYK","color":[0.10211181640625,0.36480712890625,0.623504638671875,0.313690185546875],"type":"global"},{"name":"Medium Warm Brown","model":"CMYK","color":[0.20001220703125,0.4744873046875,0.749114990234375,0.3765869140625],"type":"global"},{"name":"Dark Warm Brown","model":"CMYK","color":[0.302093505859375,0.588287353515625,0.87451171875,0.435302734375],"type":"global"},{"name":"Darker Warm Brown","model":"CMYK","color":[0.399993896484375,0.70001220703125,1,0.5],"type":"global"}],"version":"1.0"} 2 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | var ase = require('./') 3 | var fs = require('fs') 4 | 5 | test('decode', function(t) { 6 | var buffer = fs.readFileSync('./sample.ase') 7 | var output = require('./sample.json') 8 | 9 | t.deepEqual( 10 | simplify(ase.decode(buffer)) 11 | , simplify(output) 12 | ) 13 | 14 | t.end() 15 | }) 16 | 17 | function simplify(data) { 18 | data.colors.forEach(function(c) { 19 | c.color = c.color.map(function(n) { 20 | return Math.round(n * 1000) / 1000 21 | }) 22 | }) 23 | 24 | return data 25 | } 26 | --------------------------------------------------------------------------------