UNPKG

image-js

Version:

Image processing and manipulation in JavaScript

219 lines (218 loc) 6.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = setExportMethods; var _blobUtil = require("blob-util"); var _fastBmp = require("fast-bmp"); var _fastPng = require("fast-png"); var _jpegJs = require("jpeg-js"); var _base = require("../../util/base64"); var _environment = require("./environment"); var _mediaTypes = require("./mediaTypes"); function encodeJpeg(image, options = {}) { const data = { width: image.width, height: image.height, data: image.getRGBAData() }; return (0, _jpegJs.encode)(data, options.quality).data; } function encodePng(image, options) { const data = { width: image.width, height: image.height, channels: image.channels, depth: image.bitDepth, data: image.data }; if (data.depth === 1 || data.depth === 32) { data.depth = 8; data.channels = 4; data.data = image.getRGBAData(); } return (0, _fastPng.encode)(data, options); } const exportMethods = { /** * Save the image to disk (Node.js only) * @memberof Image * @instance * @param {string} path * @param {object} [options] * @param {string} [options.format] - One of: png, jpg, bmp (limited support for bmp). If not specified will try to infer from filename * @param {boolean} [options.useCanvas=false] - Force use of the canvas API to save the image instead of a JavaScript implementation * @param {object} [options.encoder] - Specify options for the encoder if applicable. * @return {Promise} - Resolves when the file is fully written */ save(path, options = {}) { const { useCanvas = false, encoder: encoderOptions = undefined } = options; let { format } = options; if (!format) { // try to infer format from filename const m = /\.(?<format>[a-zA-Z]+)$/.exec(path); if (m) { format = m.groups.format.toLowerCase(); } } if (!format) { throw new Error('file format not provided'); } return new Promise((resolve, reject) => { let stream, buffer; switch (format.toLowerCase()) { case 'png': { if (useCanvas) { stream = this.getCanvas().pngStream(); } else { buffer = encodePng(this, encoderOptions); } break; } case 'jpg': case 'jpeg': if (useCanvas) { stream = this.getCanvas().jpegStream(); } else { buffer = encodeJpeg(this, encoderOptions); } break; case 'bmp': buffer = (0, _fastBmp.encode)(this, encoderOptions); break; default: throw new RangeError(`invalid output format: ${format}`); } if (stream) { let out = (0, _environment.createWriteStream)(path); out.on('finish', resolve); out.on('error', reject); stream.pipe(out); } else if (buffer) { (0, _environment.writeFile)(path, buffer, err => { if (err) { reject(err); return; } resolve(); }); } }); }, /** * Creates a dataURL string from the image. * @memberof Image * @instance * @param {string} [type='image/png'] * @param {object} [options] * @param {boolean} [options.useCanvas=false] - Force use of the canvas API to save the image instead of JavaScript implementation. * @param {object} [options.encoder] - Specify options for the encoder if applicable. * @return {string|Promise<string>} */ toDataURL(type = 'image/png', options = {}) { if (typeof type === 'object') { options = type; type = 'image/png'; } const { useCanvas = false, encoder: encoderOptions = undefined } = options; type = (0, _mediaTypes.getType)(type); function dataUrl(encoder, ctx) { const u8 = encoder(ctx, encoderOptions); return (0, _base.toBase64URL)(u8, type); } if (type === 'image/bmp') { return dataUrl(_fastBmp.encode, this); } else if (type === 'image/png' && !useCanvas) { return dataUrl(encodePng, this); } else if (type === 'image/jpeg' && !useCanvas) { return dataUrl(encodeJpeg, this); } else { return this.getCanvas().toDataURL(type); } }, /** * Encodes the image and returns a buffer * @memberof Image * @instance * @param {object} [options] * @param {string} [options.format='png'] * @param {object} [options.encoder] - Specify options for the encoder if applicable. * @return {Uint8Array} */ toBuffer(options = {}) { const { format = 'png', encoder: encoderOptions = undefined } = options; switch (format.toLowerCase()) { case 'png': return encodePng(this, encoderOptions); case 'jpeg': case 'jpg': return encodeJpeg(this, encoderOptions); case 'bmp': return (0, _fastBmp.encode)(this, encoderOptions); default: throw new RangeError(`invalid output format: ${format}`); } }, /** * Creates a base64 string from the image. * @memberof Image * @instance * @param {string} [type='image/png'] * @param {object} [options] - Same options as toDataURL * @return {string|Promise<string>} */ toBase64(type = 'image/png', options = {}) { if (options.async) { return this.toDataURL(type, options).then(function (dataURL) { return dataURL.substring(dataURL.indexOf(',') + 1); }); } else { const dataURL = this.toDataURL(type, options); return dataURL.substring(dataURL.indexOf(',') + 1); } }, /** * Creates a blob from the image and return a Promise. * This function is only available in the browser. * @memberof Image * @instance * @param {string} [type='image/png'] A String indicating the image format. The default type is image/png. * @param {string} [quality=0.8] A Number between 0 and 1 indicating image quality if the requested type is image/jpeg or image/webp. If this argument is anything else, the default value for image quality is used. Other arguments are ignored. * @return {Promise} */ toBlob(type = 'image/png', quality = 0.8) { return (0, _blobUtil.canvasToBlob)(this.getCanvas(), type, quality); }, /** * Creates a new canvas element and draw the image inside it * @memberof Image * @instance * @return {Canvas} */ getCanvas() { const data = new _environment.ImageData(this.getRGBAData({ clamped: true }), this.width, this.height); let canvas = (0, _environment.createCanvas)(this.width, this.height); let ctx = canvas.getContext('2d'); ctx.putImageData(data, 0, 0); return canvas; } }; function setExportMethods(Image) { for (const i in exportMethods) { Image.prototype[i] = exportMethods[i]; } }