UNPKG

@randy.tarampi/pseudoimage

Version:

ʕつ◕ᴥ◕ʔつ 📷 → Your application's pseudolocales' image folders

209 lines (185 loc) 8.77 kB
const fs = require("fs"); const path = require("path"); const lwip = require("@randy.tarampi/lwip"); const mkdirp = require("mkdirp"); class Pseudoimage { /** * Instantiates a Pseudoimage * @constructor * @param {string} sourceDirectory - The directory to create pseudoimages for * @param {string} destinationDirectory - The destination to place the pseudoimages in * @param {function} transformationFunction - some image transformation function that takes an image, destination, success and failure callbacks */ constructor(sourceDirectory, destinationDirectory, transformationFunction) { this.sourceDirectory = sourceDirectory ? path.normalize(sourceDirectory) : null; this.destinationDirectory = destinationDirectory ? path.normalize(destinationDirectory) : null; this.transformationFunction = transformationFunction || defaultImageTransformation; } /** * A convenience constructor that creates retinized images to help test for unprescribed image sizes * @constructor * @param {string} sourceDirectory - The directory to create pseudoimages for * @param {string} destinationDirectory - The destination to place the pseudoimages in */ static retina(sourceDirectory, destinationDirectory) { return new Pseudoimage(sourceDirectory, destinationDirectory, retinizedImageTransformation); } /** * A convenience constructor that creates half-sized images to help test for unprescribed image sizes * @constructor * @param {string} sourceDirectory - The directory to create pseudoimages for * @param {string} destinationDirectory - The destination to place the pseudoimages in */ static half(sourceDirectory, destinationDirectory) { return new Pseudoimage(sourceDirectory, destinationDirectory, halfImageTransformation); } /** * Create an image that are the same size of some source image (a pseudoimage) and place that at some destination * @param {string} sourcePath - The source image for the pseudolocalization * @param {string} destinationPath - The destination for the pseudoimage * @param {function} transformationFunction - some image transformation function that takes an image, destination, success and failure callbacks * @return {Promise} - a promise that resolves if we create a pseudoimage at destinationPath and is rejected otherwise */ generatePseudoImage(sourcePath, destinationPath, transformationFunction) { sourcePath = path.normalize(sourcePath); destinationPath = path.normalize(destinationPath); transformationFunction = transformationFunction || this.transformationFunction; const destinationDirectory = path.dirname(destinationPath); return Promise.all([ new Promise((resolve, reject) => { fs.lstat(sourcePath, (error, lstat) => { if (error) { return reject(error); } if (!lstat.isFile()) { return reject(new Error(`${sourcePath} must be a file`)); } return resolve(lstat); }); }), mkdirpDestinationDirectoryIfRequired(destinationDirectory) ]).then(() => { return new Promise((resolve, reject) => { lwip.open(sourcePath, (error, image) => { if (error) { return reject(error); } transformationFunction(image, destinationPath, resolve, reject); }); }); }); } /** * Create pseudoimages for each image in the sourceImagePath, recursively * @param {string} sourceDirectory - The directory to create pseudoimages for * @param {string} destinationDirectory - The destination to place the pseudoimages in * @param {function} transformationFunction - some image transformation function that takes an image, destination, success and failure callbacks * @return {Promise} - a promise that resolves if we create all pseudoimages and is rejected otherwise */ generatePseudoImages(sourceDirectory, destinationDirectory, transformationFunction) { sourceDirectory = sourceDirectory ? path.normalize(sourceDirectory) : this.sourceDirectory; destinationDirectory = destinationDirectory ? path.normalize(destinationDirectory) : this.destinationDirectory; return new Promise((resolve, reject) => { fs.readdir(sourceDirectory, (error, files) => { if (error) { return reject(error); } return resolve(files); }); }) .then(files => Promise.all(files.map(file => { const source = path.join(sourceDirectory, file); const destination = path.join(destinationDirectory, file); return Promise.all([ new Promise((resolve, reject) => { fs.lstat(source, (error, sourceLstat) => { if (error) { return reject(error); } return resolve(sourceLstat); }); }), mkdirpDestinationDirectoryIfRequired(destinationDirectory) ]).then(([sourceLstat]) => { if (sourceLstat.isDirectory()) { return this.generatePseudoImages(source, destination, transformationFunction); } else if (sourceLstat.isFile()) { return this.generatePseudoImage(source, destination, transformationFunction); } else { throw new Error(`Source ${source} is neither a file nor directory (${sourceLstat.mode})`); } }); }))); } } /** * Applies a gaussian blur on an image with σ = 2 and then flips the image on the vertical and horizontal. * @param {Image} image - the image we're working on * @param {string} destinationPath - The path for the pseudoimage * @param {function} successCallback - called on success, with no return value * @param {function} errorCallback - called on failure, returns an error */ function defaultImageTransformation(image, destinationPath, successCallback, errorCallback) { image.batch() .blur(2) .flip("xy") .writeFile(destinationPath, (error) => { if (error) { return errorCallback(error); } successCallback(); }); } /** * Enlarges the image by 2x, applies a gaussian blur on an image with σ = 2 and then flips the image on the vertical and horizontal. * @param {Image} image - the image we're working on * @param {string} destinationPath - The path for the pseudoimage * @param {function} successCallback - called on success, with no return value * @param {function} errorCallback - called on failure, returns an error */ function retinizedImageTransformation(image, destinationPath, successCallback, errorCallback) { image.batch() .scale(2) .blur(2) .flip("xy") .writeFile(destinationPath, (error) => { if (error) { return errorCallback(error); } successCallback(); }); } /** * Reduces the image by 2x, applies a gaussian blur on an image with σ = 2 and then flips the image on the vertical and horizontal. * @param {Image} image - the image we're working on * @param {string} destinationPath - The path for the pseudoimage * @param {function} successCallback - called on success, with no return value * @param {function} errorCallback - called on failure, returns an error */ function halfImageTransformation(image, destinationPath, successCallback, errorCallback) { image.batch() .scale(0.5) .blur(2) .flip("xy") .writeFile(destinationPath, (error) => { if (error) { return errorCallback(error); } successCallback(); }); } module.exports = Pseudoimage; const mkdirpDestinationDirectoryIfRequired = destinationDirectory => new Promise((resolve, reject) => { fs.lstat(destinationDirectory, error => { if (error) { if (error.code === "ENOENT") { return mkdirp(destinationDirectory) .then(resolve) .catch(reject); } else { return reject(error); } } return resolve(); }); });