UNPKG

image-tiler

Version:

Create zoom tile pyramids from a large image

78 lines (73 loc) 3.44 kB
'use strict'; var execFileSync = require('child_process').execFileSync; var sizeOf = require('image-size'); var mkdirp = require('mkdirp-promise'); var rimraf = require('rimraf-then'); var fs = require('fs'); var path = require('path'); function tileLevel(inPath, outPath, zoom, tileSize, pattern, quality) { var dotExtension = pattern.replace(/.*(\.[^.]+)$/, '$1'); var patternedFilename = pattern.replace(/\{z\}/, '' + zoom) .replace(/\{x\}/, '%[fx:page.x/' + tileSize + ']') .replace(/\{y\}/, '%[fx:page.y/' + tileSize + ']') .replace(/\.[^.]+$/, ''); var patternedFilenameWithoutTheFilename = ''; if (pattern.indexOf(path.sep) > 0) { patternedFilenameWithoutTheFilename = pattern.replace(new RegExp(path.sep + '[^' + path.sep + ']*$'), '') .replace(/\{z\}/, '' + zoom); } return mkdirp(outPath + path.sep + patternedFilenameWithoutTheFilename) .then(() => { var args = [inPath, '-crop', tileSize + 'x' + tileSize, '-set', 'filename:tile', patternedFilename, '-quality', quality, '+repage', '+adjoin', outPath + '/%[filename:tile]' + dotExtension]; execFileSync('convert', args); }); } function imageBiggerThanTile(path, tileSize) { var size = sizeOf(path); return size.height > tileSize || size.width > tileSize; } function tileRec(inPath, outPath, zoom, tileSize, tempDir, pattern, zoomToDisplay, invertZoom, quality) { var inPathMpc = tempDir + '/temp_level_' + zoom + '.mpc'; var inPathCache = tempDir + '/temp_level_' + zoom + '.cache'; execFileSync('convert', [inPath, inPathMpc]); return tileLevel(inPathMpc, outPath, zoomToDisplay, tileSize, pattern, quality) .then(function () { if (imageBiggerThanTile(inPath, tileSize)) { var newZoom = zoom + 1; var newZoomToDisplay = zoomToDisplay + 1; if (!invertZoom) { newZoomToDisplay = zoomToDisplay - 1; } var newInPath = tempDir + '/temp_level_' + zoom + '.png'; execFileSync('convert', [inPathMpc, '-resize', '50%', '-quality', quality, newInPath]); fs.unlinkSync(inPathMpc); fs.unlinkSync(inPathCache); return tileRec(newInPath, outPath, newZoom, tileSize, tempDir, pattern, newZoomToDisplay, invertZoom, quality); } else { fs.unlinkSync(inPathMpc); fs.unlinkSync(inPathCache); } }); } module.exports.tile = function (inPath, outPath, pattern, options) { options = options || {}; var tileSize = options.tileSize || 256; var tmpDir = options.tmpDir || process.env.TMPDIR || '/tmp'; var tempDir = tmpDir + '/image-tiler_' + process.pid; var zoom = 0; var zoomToDisplay = 0; var quality = options.quality || 100; if (!options.invertZoom) { var size = sizeOf(inPath); var halvingsWidth = Math.ceil(Math.log2(Math.ceil(size.width / tileSize))); var halvingsheight = Math.ceil(Math.log2(Math.ceil(size.height / tileSize))); zoomToDisplay = Math.max(halvingsWidth, halvingsheight); } return mkdirp(tempDir) .then(() => tileRec(inPath, outPath, zoom, tileSize, tempDir, pattern, zoomToDisplay, options.invertZoom, quality)) .then(() => rimraf(tempDir)); };