├── .eslintrc ├── .gitignore ├── .travis.yml ├── LICENSE ├── bench └── bench.js ├── bin └── tiletype.js ├── index.d.ts ├── index.js ├── package.json ├── readme.md └── test ├── fixtures ├── 0.gif ├── 0.jpeg ├── 0.png ├── 0.vector.pbf ├── 0.vector.pbfz ├── 0.webp ├── gif-990x1050.gif ├── jpg-640x400.jpg ├── png-640x400.png ├── tux.webp ├── tux_alpha.webp ├── unknown.txt └── webp-550x368.webp ├── test.js └── types.ts /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint-config-unstyled" 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | sudo: false 4 | 5 | node_js: 6 | - "0.10" 7 | - "4" 8 | - "6" 9 | 10 | after_success: 11 | - if [[ ${TRAVIS_NODE_VERSION} == "0.10" ]]; then npm run coverage; fi -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) MapBox 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | - Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | - Redistributions in binary form must reproduce the above copyright notice, this 10 | list of conditions and the following disclaimer in the documentation and/or 11 | other materials provided with the distribution. 12 | - Neither the name "MapBox" nor the names of its contributors may be 13 | used to endorse or promote products derived from this software without 14 | specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /bench/bench.js: -------------------------------------------------------------------------------- 1 | var Benchmark = require('benchmark'); 2 | var suite = new Benchmark.Suite(); 3 | var assert = require('assert'); 4 | var tiletype = require('..'); 5 | var fs = require('fs'); 6 | var data = fs.readFileSync(__dirname + '/../test/fixtures/0.vector.pbf'); 7 | 8 | suite.add('tiletype.type', function() { 9 | assert.equal('pbf', tiletype.type(data)); 10 | }) 11 | .on('cycle', function(event) { 12 | console.log(String(event.target)); 13 | }) 14 | .run(); 15 | -------------------------------------------------------------------------------- /bin/tiletype.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var path = require('path'); 4 | var fs = require('fs'); 5 | var tiletype = require('..').type; 6 | 7 | var args = process.argv.slice(2); 8 | var filepath = args.shift(); 9 | filepath = filepath ? path.resolve(filepath) : ''; 10 | 11 | fs.readFile(filepath, function(err, buf) { 12 | if (err) { 13 | console.error(err.toString()); 14 | process.exit(1); 15 | } 16 | if (!tiletype(buf)) { 17 | console.error('Could not determine tile type'); 18 | process.exit(3); 19 | } 20 | console.log(tiletype(buf)); 21 | }); 22 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | export interface Header { 4 | 'Content-Type'?: string 5 | 'Content-Encoding'?: string 6 | } 7 | 8 | export type extensions = 'png' | 'pbf' | 'jpg' | 'webp' 9 | 10 | /** 11 | * Given a buffer of unknown data, return either a format as an extension 12 | * string or false if the type cannot be determined. 13 | * 14 | * Potential options are: 15 | * 16 | * * png 17 | * * pbf 18 | * * jpg 19 | * * webp 20 | * 21 | * @param {Buffer} buffer input 22 | * @returns {String|boolean} identifier 23 | */ 24 | export function type(buffer: Buffer): extensions | boolean 25 | 26 | /** 27 | * Return headers - Content-Type and Content-Encoding - 28 | * for a response containing this kind of image. 29 | * 30 | * @param {Buffer} buffer input 31 | * @returns {Object} headers 32 | */ 33 | export function headers(buffer: Buffer): Header 34 | 35 | /** 36 | * Determine the width and height of an image contained in a buffer, 37 | * returned as a [x, y] array. 38 | * 39 | * @param {Buffer} buffer input 40 | * @returns {Array|boolean} dimensions 41 | */ 42 | export function dimensions(buffer: Buffer): [number, number] | boolean 43 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | module.exports.type = type; 3 | module.exports.headers = headers; 4 | module.exports.dimensions = dimensions; 5 | 6 | /** 7 | * Given a buffer of unknown data, return either a format as an extension 8 | * string or false if the type cannot be determined. 9 | * 10 | * Potential options are: 11 | * 12 | * * png 13 | * * pbf 14 | * * jpg 15 | * * webp 16 | * 17 | * @param {Buffer} buffer input 18 | * @returns {String|boolean} identifier 19 | */ 20 | function type(buffer) { 21 | if (buffer[0] === 0x89 && buffer[1] === 0x50 && buffer[2] === 0x4E && 22 | buffer[3] === 0x47 && buffer[4] === 0x0D && buffer[5] === 0x0A && 23 | buffer[6] === 0x1A && buffer[7] === 0x0A) { 24 | return 'png'; 25 | } else if (buffer[0] === 0xFF && buffer[1] === 0xD8 && 26 | buffer[buffer.length - 2] === 0xFF && buffer[buffer.length - 1] === 0xD9) { 27 | return 'jpg'; 28 | } else if (buffer[0] === 0x47 && buffer[1] === 0x49 && buffer[2] === 0x46 && 29 | buffer[3] === 0x38 && (buffer[4] === 0x39 || buffer[4] === 0x37) && 30 | buffer[5] === 0x61) { 31 | return 'gif'; 32 | } else if (buffer[0] === 0x52 && buffer[1] === 0x49 && buffer[2] === 0x46 && buffer[3] === 0x46 && 33 | buffer[8] === 0x57 && buffer[9] === 0x45 && buffer[10] === 0x42 && buffer[11] === 0x50) { 34 | return 'webp'; 35 | // deflate: recklessly assumes contents are PBF. 36 | } else if (buffer[0] === 0x78 && buffer[1] === 0x9C) { 37 | return 'pbf'; 38 | // gzip: recklessly assumes contents are PBF. 39 | } else if (buffer[0] === 0x1F && buffer[1] === 0x8B) { 40 | return 'pbf'; 41 | } 42 | return false; 43 | } 44 | 45 | /** 46 | * Return headers - Content-Type and Content-Encoding - 47 | * for a response containing this kind of image. 48 | * 49 | * @param {Buffer} buffer input 50 | * @returns {Object} headers 51 | */ 52 | function headers(buffer) { 53 | var head = {}; 54 | if (buffer[0] === 0x89 && buffer[1] === 0x50 && buffer[2] === 0x4E && 55 | buffer[3] === 0x47 && buffer[4] === 0x0D && buffer[5] === 0x0A && 56 | buffer[6] === 0x1A && buffer[7] === 0x0A) { 57 | head['Content-Type'] = 'image/png'; 58 | } else if (buffer[0] === 0xFF && buffer[1] === 0xD8 && 59 | buffer[buffer.length - 2] === 0xFF && buffer[buffer.length - 1] === 0xD9) { 60 | head['Content-Type'] = 'image/jpeg'; 61 | } else if (buffer[0] === 0x47 && buffer[1] === 0x49 && buffer[2] === 0x46 && 62 | buffer[3] === 0x38 && (buffer[4] === 0x39 || buffer[4] === 0x37) && 63 | buffer[5] === 0x61) { 64 | head['Content-Type'] = 'image/gif'; 65 | } else if (buffer[0] === 0x52 && buffer[1] === 0x49 && buffer[2] === 0x46 && buffer[3] === 0x46 && 66 | buffer[8] === 0x57 && buffer[9] === 0x45 && buffer[10] === 0x42 && buffer[11] === 0x50) { 67 | head['Content-Type'] = 'image/webp'; 68 | // deflate: recklessly assumes contents are PBF. 69 | } else if (buffer[0] === 0x78 && buffer[1] === 0x9C) { 70 | head['Content-Type'] = 'application/x-protobuf'; 71 | head['Content-Encoding'] = 'deflate'; 72 | // gzip: recklessly assumes contents are PBF. 73 | } else if (buffer[0] === 0x1F && buffer[1] === 0x8B) { 74 | head['Content-Type'] = 'application/x-protobuf'; 75 | head['Content-Encoding'] = 'gzip'; 76 | } 77 | return head; 78 | } 79 | 80 | /** 81 | * Determine the width and height of an image contained in a buffer, 82 | * returned as a [x, y] array. 83 | * 84 | * @param {Buffer} buffer input 85 | * @returns {Array|boolean} dimensions 86 | */ 87 | function dimensions(buffer) { 88 | var mp28 = Math.pow(2,8); 89 | switch (type(buffer)) { 90 | case 'png': 91 | var i = 8; 92 | while (i < buffer.length) { 93 | var length = buffer.readUInt32BE(i); 94 | var chunktype = buffer.toString('ascii', i + 4, i + 8); 95 | // Invalid chunk. 96 | if (!(length || chunktype === 'IEND')) return false; 97 | // Length + type. 98 | i += 8; 99 | if (chunktype === 'IHDR') { 100 | var w = (buffer[i+0]*Math.pow(2,32)) + (buffer[i+1]*Math.pow(2,16)) + (buffer[i+2]*Math.pow(2,8)) + buffer[i+3]; 101 | var h = (buffer[i+4]*Math.pow(2,32)) + (buffer[i+5]*Math.pow(2,16)) + (buffer[i+6]*Math.pow(2,8)) + buffer[i+7]; 102 | return [w,h]; 103 | } 104 | // Skip CRC. 105 | i += length + 4; 106 | } 107 | break; 108 | case 'jpg': 109 | var i = 2; 110 | while (i < buffer.length) { 111 | // Invalid chunk. 112 | if (buffer[i] !== 0xff) return false; 113 | var chunktype = buffer[i+1]; 114 | var length = (buffer[i+2]*mp28) + (buffer[i+3]); 115 | // Entropy-encoded begins after this chunk. Bail. 116 | if (chunktype === 0xda) { 117 | return false; 118 | } else if (chunktype === 0xc0) { 119 | var h = (buffer[i+5]*Math.pow(2,8)) + buffer[i+6]; 120 | var w = (buffer[i+7]*Math.pow(2,8)) + buffer[i+8]; 121 | return [w,h]; 122 | } 123 | i += 2 + length; 124 | } 125 | break; 126 | case 'gif': 127 | var w = (buffer[7]*Math.pow(2,8)) + buffer[6]; 128 | var h = (buffer[9]*Math.pow(2,8)) + buffer[8]; 129 | return [w,h]; 130 | break; 131 | case 'webp': 132 | var chunktype = buffer.toString('ascii', 12, 16); 133 | if (chunktype === 'VP8 ') { 134 | // Invalid chunk. 135 | if (buffer[23] !== 0x9d || buffer[24] !== 0x01 || buffer[25] !== 0x2a) return false; 136 | var w = buffer[26] | (buffer[27] << 8); 137 | var h = buffer[28] | (buffer[29] << 8); 138 | return [w,h]; 139 | } 140 | else if (chunktype === 'VP8L') { 141 | var w = 1 + (buffer[21] | (buffer[22] & 0x3F) << 8); 142 | var h = 1 + (((buffer[22] & 0xC0) >> 6) | (buffer[23] << 2) | ((buffer[24] & 0xF) << 10)); 143 | return [w,h]; 144 | } 145 | else if (chunktype === 'VP8X') { 146 | var w = 1 + (buffer[24] | buffer[25] << 8 | buffer[26] << 16); 147 | var h = 1 + (buffer[27] | buffer[28] << 8 | buffer[29] << 16); 148 | 149 | return [w,h]; 150 | } 151 | return false; 152 | break; 153 | } 154 | return false; 155 | } 156 | 157 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mapbox/tiletype", 3 | "description": "detect common map tile formats from a buffer", 4 | "version": "0.3.1", 5 | "url": "http://github.com/mapbox/tiletype", 6 | "author": { 7 | "name": "Mapbox", 8 | "url": "https://www.mapbox.com/", 9 | "email": "info@mapbox.com" 10 | }, 11 | "licenses": [ 12 | { 13 | "type": "BSD" 14 | } 15 | ], 16 | "devDependencies": { 17 | "benchmark": "1.0.x", 18 | "dox": "^0.7.0", 19 | "doxme": "^1.8.2", 20 | "istanbul": "~0.3.17", 21 | "coveralls": "~2.11.2", 22 | "tape": "2.13.x", 23 | "eslint": "~1.00.0", 24 | "eslint-config-unstyled": "^1.1.0", 25 | "@types/node": "^6.0.52", 26 | "typescript": "^2.1.4" 27 | }, 28 | "main": "./index.js", 29 | "scripts": { 30 | "test": "eslint index.js && node test/test.js", 31 | "doc": "dox -r < index.js | doxme --readme > README.md", 32 | "coverage": "istanbul cover tape test/*test.js && coveralls < ./coverage/lcov.info", 33 | "types": "tsc test/types.ts" 34 | }, 35 | "bin": { 36 | "tiletype": "bin/tiletype.js" 37 | }, 38 | "types": "index.d.ts", 39 | "repository": { 40 | "type": "git", 41 | "url": "git@github.com:mapbox/tiletype.git" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # tiletype 2 | 3 | [![build status](https://secure.travis-ci.com/mapbox/tiletype.png)](http://travis-ci.com/mapbox/tiletype) 4 | [![Coverage Status](https://coveralls.io/repos/mapbox/tiletype/badge.svg?branch=coverage&service=github)](https://coveralls.io/github/mapbox/tiletype?branch=coverage) 5 | 6 | detect common map tile formats from a buffer 7 | 8 | 9 | ### `type(buffer)` 10 | 11 | Given a buffer of unknown data, return either a format as an extension 12 | string or false if the type cannot be determined. 13 | 14 | Potential options are: 15 | 16 | * png 17 | * pbf 18 | * jpg 19 | * webp 20 | 21 | 22 | ### Parameters 23 | 24 | | parameter | type | description | 25 | | --------- | ------ | ----------- | 26 | | `buffer` | Buffer | input | 27 | 28 | 29 | 30 | **Returns** `String,boolean`, identifier 31 | 32 | 33 | ### `headers(buffer)` 34 | 35 | Return headers - Content-Type and Content-Encoding - 36 | for a response containing this kind of image. 37 | 38 | 39 | ### Parameters 40 | 41 | | parameter | type | description | 42 | | --------- | ------ | ----------- | 43 | | `buffer` | Buffer | input | 44 | 45 | 46 | 47 | **Returns** `Object`, headers 48 | 49 | 50 | ### `dimensions(buffer, dimensions)` 51 | 52 | Determine the width and height of an image contained in a buffer, 53 | returned as a [x, y] array. 54 | 55 | 56 | ### Parameters 57 | 58 | | parameter | type | description | 59 | | ------------ | -------------- | ----------- | 60 | | `buffer` | Buffer | input | 61 | | `dimensions` | Array\,boolean | | 62 | 63 | 64 | ## Installation 65 | 66 | Requires [nodejs](http://nodejs.org/). 67 | 68 | ```sh 69 | $ npm install @mapbox/tiletype 70 | ``` 71 | 72 | ## Tests 73 | 74 | ```sh 75 | $ npm test 76 | ``` 77 | 78 | 79 | -------------------------------------------------------------------------------- /test/fixtures/0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapbox/tiletype/0632405c008302c15dfdefb104789baac1c10d30/test/fixtures/0.gif -------------------------------------------------------------------------------- /test/fixtures/0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapbox/tiletype/0632405c008302c15dfdefb104789baac1c10d30/test/fixtures/0.jpeg -------------------------------------------------------------------------------- /test/fixtures/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapbox/tiletype/0632405c008302c15dfdefb104789baac1c10d30/test/fixtures/0.png -------------------------------------------------------------------------------- /test/fixtures/0.vector.pbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapbox/tiletype/0632405c008302c15dfdefb104789baac1c10d30/test/fixtures/0.vector.pbf -------------------------------------------------------------------------------- /test/fixtures/0.vector.pbfz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapbox/tiletype/0632405c008302c15dfdefb104789baac1c10d30/test/fixtures/0.vector.pbfz -------------------------------------------------------------------------------- /test/fixtures/0.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapbox/tiletype/0632405c008302c15dfdefb104789baac1c10d30/test/fixtures/0.webp -------------------------------------------------------------------------------- /test/fixtures/gif-990x1050.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapbox/tiletype/0632405c008302c15dfdefb104789baac1c10d30/test/fixtures/gif-990x1050.gif -------------------------------------------------------------------------------- /test/fixtures/jpg-640x400.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapbox/tiletype/0632405c008302c15dfdefb104789baac1c10d30/test/fixtures/jpg-640x400.jpg -------------------------------------------------------------------------------- /test/fixtures/png-640x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapbox/tiletype/0632405c008302c15dfdefb104789baac1c10d30/test/fixtures/png-640x400.png -------------------------------------------------------------------------------- /test/fixtures/tux.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapbox/tiletype/0632405c008302c15dfdefb104789baac1c10d30/test/fixtures/tux.webp -------------------------------------------------------------------------------- /test/fixtures/tux_alpha.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapbox/tiletype/0632405c008302c15dfdefb104789baac1c10d30/test/fixtures/tux_alpha.webp -------------------------------------------------------------------------------- /test/fixtures/unknown.txt: -------------------------------------------------------------------------------- 1 | qTXN2gcIkBTRNRaObUf4BMxkaN99daF1VhvJUftOEnoelzfIiWmhY/3n3Y5XkoJk 2 | L8PITDzvCEVsiz+nyqRV0OIfd4zjyvGQCrzMR7RUfoKmt7+y6VZ/ZGE7+w4tll2U 3 | FnUwwtMv+jGENJDNS35Pbk5seozZM0zQor8byRHUa4+jFKk1bonpcJsyqxiR8sgn 4 | LSNZaEXa3zmu2BNsN/458/RiiXNA/dCLdR4YSdV1Ev9O8tvYib0AZAKrA/kXxIRO 5 | lf8Gg2QCJizQ6cOQ1Iug/HpC0IdA/IRWU/GfbB1a+iOeUzlV9mkyataWmjS35mzM 6 | g7zqZGTLansLBEoamVdjT5KFxzxPnM0qNd4KNbiJp076fjKyzsYDV6QLlsJu+R2l 7 | Ss00hIm+LUB8wxG3eXFV1c5J9ZsnyZ8VKa9ZOLOBZvpoPD8N5B5N8Dl1yEpoP73q 8 | 9JXrFbjE91vQnuuNbUFrNXKs+TKLsaXtj90o3m6GDYbd1x/tWdPu3fnzz3J6UFT/ 9 | 1Jovl8wdcrdFTT24UUSSWnXtyWjWKa+hVVxkdRzJYIl+YcpRCBARZ/EfNpidpG6Z 10 | au2lMs5mmx+rckdTS+g/79cUUn5jfcRtNxcVVK+SNr3BL04XCNoJ1hUvKH969i8m 11 | 2YhQ/ps1itXv1v67VnpW15T1ps9XltLTW2k1GDURqDHLY7O5CzHjo8KKZ07CihWm 12 | 7fAiFinrapyBxLVSv6p/uPRkMxwpugujX9ZLpDP5O9AxJkhMYJImkZJ7HgtosWlE 13 | yP+HMo5+zDKt327MpZAY/TMd48hVYV55ZP1swS11p9QWGCXT6Rsyeyz9Pj1kXQYj 14 | mvKKDjXhUFADlJw9Mu+CYt8oW+JapyVTX5VJEwQ2H9BknwDxs0Evx8peZ6DWSOvE 15 | 1aVzFb1/GdLTd4UPpx87+1UI9zncjcVYXglMEokouWdUI/DJiNXsDBAOKe0sMV72 16 | Os7GdHlVDVS6Cot17eyaO+uy+x/QpKVjz1ypuTaWHmA8kEJhiYnLV16VHK5gq7q6 17 | 7hvmhc1RDCHGprpoqJFaeUtxPjldzgBKKZLwKjU191t8IZyVLgkTKKeE9kJo38rm 18 | TUVja2US/ChYGXsUCADWlSyH3G0fxE9YxOayCNdSKomTTTOS6Wgj8xWKwJWE2LJW 19 | cNw7EcFMjWAbvLHWM3FH0MqNkKNlOuhotvD2zx/KJDIiqBvDZzPYVNCB1SHBuvUF 20 | 86tqY50dR+9N7kjoAWvIjP9ejr5ZStlfRyOjicR2ceAfYxDitgxE2uHqdHLMiQJn 21 | uIq/NKL59TtawGPPVLMl8BzEYvc28GY+oL1GXOYaP24q9e0PbZm2BA== 22 | -------------------------------------------------------------------------------- /test/fixtures/webp-550x368.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapbox/tiletype/0632405c008302c15dfdefb104789baac1c10d30/test/fixtures/webp-550x368.webp -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var tiletype = require('..'); 2 | var assert = require('assert'); 3 | var tape = require('tape'); 4 | var path = require('path'); 5 | var fs = require('fs'); 6 | var exec = require('child_process').exec; 7 | var cmd = path.resolve(__dirname, '..', 'bin', 'tiletype.js'); 8 | 9 | var files = { 10 | 'jpg': fs.readFileSync(__dirname + '/fixtures/0.jpeg'), 11 | 'png': fs.readFileSync(__dirname + '/fixtures/0.png'), 12 | 'gif': fs.readFileSync(__dirname + '/fixtures/0.gif'), 13 | 'webp': fs.readFileSync(__dirname + '/fixtures/0.webp'), 14 | 'pbf': fs.readFileSync(__dirname + '/fixtures/0.vector.pbf'), 15 | 'pbfz': fs.readFileSync(__dirname + '/fixtures/0.vector.pbfz'), 16 | 'unknown': fs.readFileSync(__dirname + '/fixtures/unknown.txt'), 17 | 'webpLossless': fs.readFileSync(__dirname + '/fixtures/tux.webp'), 18 | 'webpExtended': fs.readFileSync(__dirname + '/fixtures/tux_alpha.webp') 19 | }; 20 | 21 | tape('type', function(t) { 22 | t.equal('jpg', tiletype.type(files.jpg), 'jpg'); 23 | t.equal('png', tiletype.type(files.png), 'png'); 24 | t.equal('gif', tiletype.type(files.gif), 'gif'); 25 | t.equal('webp', tiletype.type(files.webp), 'webp'); 26 | t.equal('webp', tiletype.type(files.webpLossless), 'webpLossless'); 27 | t.equal('webp', tiletype.type(files.webpExtended), 'webpExtended'); 28 | t.equal('pbf', tiletype.type(files.pbf), 'pbf'); 29 | t.equal('pbf', tiletype.type(files.pbfz), 'pbf'); 30 | t.equal(false, tiletype.type(files.unknown)); 31 | t.end(); 32 | }); 33 | 34 | tape('headers', function(t) { 35 | t.deepEqual({'Content-Type':'image/jpeg'}, tiletype.headers(files.jpg)); 36 | t.deepEqual({'Content-Type':'image/png'}, tiletype.headers(files.png)); 37 | t.deepEqual({'Content-Type':'image/gif'}, tiletype.headers(files.gif)); 38 | t.deepEqual({'Content-Type':'image/webp'}, tiletype.headers(files.webp)); 39 | t.deepEqual({'Content-Type':'application/x-protobuf','Content-Encoding':'deflate'}, tiletype.headers(files.pbf)); 40 | t.deepEqual({'Content-Type':'application/x-protobuf','Content-Encoding':'gzip'}, tiletype.headers(files.pbfz)); 41 | t.deepEqual({}, tiletype.headers(false)); 42 | t.end(); 43 | }); 44 | 45 | tape('dimensions', function(t) { 46 | t.deepEqual([256,256], tiletype.dimensions(files.png)); 47 | t.deepEqual([640,400], tiletype.dimensions(fs.readFileSync(__dirname + '/fixtures/png-640x400.png'))); 48 | t.deepEqual([256,256], tiletype.dimensions(files.jpg)); 49 | t.deepEqual([640,400], tiletype.dimensions(fs.readFileSync(__dirname + '/fixtures/jpg-640x400.jpg'))); 50 | t.deepEqual([256,256], tiletype.dimensions(files.gif)); 51 | t.deepEqual([990,1050], tiletype.dimensions(fs.readFileSync(__dirname + '/fixtures/gif-990x1050.gif'))); 52 | t.deepEqual([256,256], tiletype.dimensions(files.webp)); 53 | t.deepEqual([550,368], tiletype.dimensions(fs.readFileSync(__dirname + '/fixtures/webp-550x368.webp'))); 54 | 55 | t.deepEqual([386,395], tiletype.dimensions(files.webpLossless)); 56 | t.deepEqual([386,395], tiletype.dimensions(files.webpExtended)); 57 | t.end(); 58 | }); 59 | 60 | tape('executable: success', function(t) { 61 | exec(cmd + ' ' + path.resolve(__dirname + '/fixtures/0.vector.pbf'), function(err, stdout, stderr) { 62 | t.ifError(err, 'detected'); 63 | t.equal(stdout, 'pbf\n', 'determined type'); 64 | t.notOk(stderr, 'no stderr'); 65 | t.end(); 66 | }); 67 | }); 68 | 69 | tape('executable: unknown', function(t) { 70 | exec(cmd + ' ' + path.resolve(__dirname + '/fixtures/unknown.txt'), function(err, stdout, stderr) { 71 | t.equal(err.code, 3, 'exit 3'); 72 | t.notOk(stdout, 'no stdout'); 73 | t.equal(stderr, 'Could not determine tile type\n', 'expected stderr'); 74 | t.end(); 75 | }); 76 | }); 77 | 78 | tape('executable: no file', function(t) { 79 | exec(cmd, function(err, stdout, stderr) { 80 | t.equal(err.code, 1, 'exit 1'); 81 | t.notOk(stdout, 'no stdout'); 82 | t.ok(stderr === 'Error: ENOENT, open \'\'\n' || 83 | stderr === 'Error: ENOENT: no such file or directory, open \'\'\n', 'expected stderr'); 84 | t.end(); 85 | }); 86 | }); 87 | -------------------------------------------------------------------------------- /test/types.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs' 2 | import * as tiletype from '../' 3 | 4 | const dimensions = tiletype.dimensions(fs.readFileSync(__dirname + '/fixtures/0.jpeg')) 5 | const header = tiletype.headers(fs.readFileSync(__dirname + '/fixtures/0.jpeg')) 6 | const type = tiletype.type(fs.readFileSync(__dirname + '/fixtures/0.jpeg')) --------------------------------------------------------------------------------