"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const chalk_1 = __importDefault(require("chalk")); const mime_1 = __importDefault(require("mime")); const Cache = __importStar(require("./Cache")); const Download = __importStar(require("./Download")); const Ico = __importStar(require("./Ico")); const Jimp = __importStar(require("./jimp")); const Sharp = __importStar(require("./sharp")); const supportedMimeTypes = ['image/png', 'image/jpeg', 'image/webp', 'image/gif']; let hasWarned = false; async function resizeImagesAsync(buffer, sizes) { const sharp = await getSharpAsync(); if (!sharp) { return Jimp.resizeBufferAsync(buffer, sizes); } return Sharp.resizeBufferAsync(buffer, sizes); } async function resizeAsync(imageOptions) { const sharp = await getSharpAsync(); const { width, height, backgroundColor, resizeMode } = imageOptions; if (!sharp) { const inputOptions = { input: imageOptions.src, quality: 100 }; const jimp = await Jimp.resize(inputOptions, { width, height, fit: resizeMode, background: backgroundColor, }); if (imageOptions.removeTransparency) { jimp.colorType(2); } if (imageOptions.borderRadius) { // TODO: support setting border radius with Jimp. Currently only support making the image a circle await Jimp.circleAsync(jimp); } const imgBuffer = await jimp.getBufferAsync(jimp.getMIME()); return imgBuffer; } try { let sharpBuffer = sharp(imageOptions.src) .ensureAlpha() .resize(width, height, { fit: resizeMode, background: 'transparent' }); // Skip an extra step if the background is explicitly transparent. if (backgroundColor && backgroundColor !== 'transparent') { // Add the background color to the image sharpBuffer = sharpBuffer.composite([ { // create a background color input: { create: { width, height, // allow alpha colors channels: imageOptions.removeTransparency ? 3 : 4, background: backgroundColor, }, }, // dest-over makes the first image (input) appear on top of the created image (background color) blend: 'dest-over', }, ]); } else if (imageOptions.removeTransparency) { sharpBuffer.flatten(); } if (imageOptions.borderRadius) { const mask = Buffer.from(``); sharpBuffer.composite([{ input: mask, blend: 'dest-over' }]); } return await sharpBuffer.png().toBuffer(); } catch ({ message }) { throw new Error(`It was not possible to generate splash screen '${imageOptions.src}'. ${message}`); } } async function getSharpAsync() { let sharp; if (await Sharp.isAvailableAsync()) sharp = await Sharp.findSharpInstanceAsync(); return sharp; } function getDimensionsId(imageOptions) { return imageOptions.width === imageOptions.height ? `${imageOptions.width}` : `${imageOptions.width}x${imageOptions.height}`; } async function maybeWarnAboutInstallingSharpAsync() { // Putting the warning here will prevent the warning from showing if all images were reused from the cache if (!hasWarned && !(await Sharp.isAvailableAsync())) { hasWarned = true; console.log(); console.log(chalk_1.default.bgYellow.black(`Using node to generate images. This is much slower than using native packages.`)); console.log(chalk_1.default.yellow(`\u203A Optionally you can stop the process and try again after successfully running \`npm install -g sharp-cli\`.\n`)); } } async function ensureImageOptionsAsync(imageOptions) { const icon = Object.assign(Object.assign({}, imageOptions), { src: await Download.downloadOrUseCachedImage(imageOptions.src) }); const mimeType = mime_1.default.getType(icon.src); if (!mimeType) { throw new Error(`Invalid mimeType for image with source: ${icon.src}`); } if (!supportedMimeTypes.includes(mimeType)) { throw new Error(`Supplied image is not a supported image type: ${imageOptions.src}`); } if (!icon.name) { icon.name = `icon_${getDimensionsId(imageOptions)}.${mime_1.default.getExtension(mimeType)}`; } return icon; } async function generateImageAsync(options, imageOptions) { const icon = await ensureImageOptionsAsync(imageOptions); if (!options.cacheType) { await maybeWarnAboutInstallingSharpAsync(); return { name: icon.name, source: await resizeAsync(icon) }; } const cacheKey = await Cache.createCacheKeyWithDirectoryAsync(options.projectRoot, options.cacheType, icon); const name = icon.name; let source = await Cache.getImageFromCacheAsync(name, cacheKey); if (!source) { await maybeWarnAboutInstallingSharpAsync(); source = await resizeAsync(icon); await Cache.cacheImageAsync(name, source, cacheKey); } return { name, source }; } exports.generateImageAsync = generateImageAsync; async function generateFaviconAsync(pngImageBuffer, sizes = [16, 32, 48]) { const buffers = await resizeImagesAsync(pngImageBuffer, sizes); return await Ico.generateAsync(buffers); } exports.generateFaviconAsync = generateFaviconAsync; /** * Layers the provided foreground image over the provided background image. * * @param foregroundImageBuffer * @param foregroundImageBuffer * @param x pixel offset from the left edge, defaults to 0. * @param y pixel offset from the top edge, defaults to 0. */ async function compositeImagesAsync({ foreground, background, x = 0, y = 0, }) { const sharp = await getSharpAsync(); if (!sharp) { const image = (await Jimp.getJimpImageAsync(background)).composite(await Jimp.getJimpImageAsync(foreground), x, y); return await image.getBufferAsync(image.getMIME()); } return await sharp(background) .composite([{ input: foreground, left: x, top: y }]) .toBuffer(); } exports.compositeImagesAsync = compositeImagesAsync; //# sourceMappingURL=Image.js.map