UNPKG

illustrator.js

Version:

JavaScript image processing library

104 lines (103 loc) 4.38 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ImageLoader = void 0; const canvas_1 = require("@napi-rs/canvas"); const fs = require("fs"); const http = require("http"); const https = require("https"); const stream_1 = require("stream"); const Illustrator_1 = require("../illustrator/Illustrator"); const IllustratorImage_1 = require("./IllustratorImage"); const Layer_1 = require("../layer/Layer"); const isBufferLike = require("is-buffer-like"); const REDIRECT_STATUSES = new Set([301, 302]); function createImage(source, bufferOnly = false) { if (bufferOnly) return source; const image = new canvas_1.Image(); image.src = source; return image; } // TODO: use stream/consumers for this? function consumeStream(stream) { return new Promise((resolve, reject) => { const body = []; stream.on("data", (chunk) => body.push(chunk)); stream.on("end", () => resolve(Buffer.concat(body))); stream.on("error", (err) => reject(err)); }); } function makeRequest(link, redirectCount, resolve, reject) { const url = typeof link === "string" ? new URL(link) : link; const reqBy = url.protocol === "http:" ? http : https; reqBy.get(url, (res) => { const shouldRedirect = REDIRECT_STATUSES.has(res.statusCode) && typeof res.headers.location === "string"; if (shouldRedirect && redirectCount > 0) return makeRequest(res.headers.location, redirectCount - 1, resolve, reject); if (typeof res.statusCode === "number" && (res.statusCode < 200 || res.statusCode >= 300)) { return reject(new Error(`request for the given image source rejected with status code "${res.statusCode}"`)); } consumeStream(res).then(resolve, reject); }); } function httpReq(link) { return new Promise((resolve, reject) => makeRequest(link, 20, resolve, reject)); } class ImageLoader extends null { constructor() { /* no-op */ } static async loadImage(source, bufferOnly) { if (source instanceof stream_1.Readable) return createImage(await consumeStream(source), bufferOnly); if (Buffer.isBuffer(source)) return createImage(source, bufferOnly); // @ts-expect-error if (isBufferLike(source)) return createImage(Buffer.from(source), bufferOnly); if (source instanceof canvas_1.Image) return createImage(source.src, bufferOnly); if (source instanceof canvas_1.Canvas) return createImage(await source.encode("png"), bufferOnly); if (source instanceof Layer_1.Layer) return createImage(await (await source.render()).encode("png"), bufferOnly); if (source instanceof Illustrator_1.Illustrator) return createImage(await source.export(), bufferOnly); if (source instanceof IllustratorImage_1.IllustratorImage) return createImage(await source.png(), bufferOnly); if (source instanceof canvas_1.ImageData) { const img = await IllustratorImage_1.IllustratorImage.fromImageData(source); return createImage(await img.png(), bufferOnly); } if ((typeof source === "string" || source instanceof URL) && fs.existsSync(source)) { const data = await fs.promises.readFile(source); return createImage(data, bufferOnly); } if (typeof source === "string" || source instanceof URL) { if (typeof fetch === "function") { const ab = await fetch(source, { method: "GET", redirect: "follow" }).then((res) => { if (!res.ok) throw new Error(`request for image source rejected with status code "${res.status}"`); return res.arrayBuffer(); }); return createImage(Buffer.from(ab), bufferOnly); } else { const res = await httpReq(source); return createImage(res, bufferOnly); } } throw new TypeError("Unsupported source type"); } /** * Creates `Image` instance * @param data The image source data */ static createImage(data) { return createImage(data, false); } } exports.ImageLoader = ImageLoader;