magica
Version:
ImageMagick for browser and Node.js, easy setup, high level API and Command Line Interface, including WASM binary for an easy setup.
328 lines • 12.8 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const assert_1 = require("assert");
const cross_fetch_1 = __importDefault(require("cross-fetch"));
const fs_1 = require("fs");
const misc_utils_of_mine_generic_1 = require("misc-utils-of-mine-generic");
const html_1 = require("../image/html");
const imageCompare_1 = require("../image/imageCompare");
const imageInfo_1 = require("../image/imageInfo");
const imageUtil_1 = require("../image/imageUtil");
const magickLoaded_1 = require("../imageMagick/magickLoaded");
const run_1 = require("../main/run");
const options_1 = require("../options");
const base64_1 = require("../util/base64");
const fileUtil_1 = require("../util/fileUtil");
const protected_1 = require("./protected");
/**
* Default File implementation with utilities for creating from file system or urls.
*
* Also instances have utilities to cache and get image information like size, mimeType, image comparison,
* interacting with HTML DOM, etc.
*/
class File {
constructor(name, content, isProtected = false, url, width, height) {
this.name = name;
this.content = content;
this.url = url;
this.width = width;
this.height = height;
if (isProtected) {
protected_1.protectFile(name);
}
}
/**
* Same as [info] but returning only the first image's data.
*/
infoOne() {
return __awaiter(this, void 0, void 0, function* () {
var i = yield this.info();
if (!i || !i.length) {
throw new Error('Expected image info extract to work');
}
return i[0];
});
}
/**
* Get image information, like geometry, important numbers, mimeType, etc.
* The first time it calls `identify` command, but then it will cache ths value.
*/
info() {
return new Promise(resolve => {
if (this._info) {
resolve(this._info);
}
else {
imageInfo_1.imageInfo(this).then(data => {
this._info = (data || []).map(i => i.image);
resolve(this._info);
});
}
});
}
size() {
return __awaiter(this, void 0, void 0, function* () {
if (this.width && this.height) {
return { width: this.width, height: this.height };
}
var i = yield this.infoOne();
this.width = i.geometry ? i.geometry.width : this.width;
this.height = i.geometry ? i.geometry.height : this.height;
return { width: this.width || 0, height: this.height || 0 };
});
}
widthXHeight() {
return __awaiter(this, void 0, void 0, function* () {
if (this.width && this.height) {
return `${this.width}x${this.height}`;
}
var s = yield this.size();
return `${s.width}x${s.height}`;
});
}
mimeType() {
return __awaiter(this, void 0, void 0, function* () {
var i = yield this.infoOne();
return i.mimeType;
});
}
pixel(x, y) {
return __awaiter(this, void 0, void 0, function* () {
if (this._pixels) {
return imageUtil_1.rgbaToString(this._pixels[imageUtil_1.coordsToIndex(this.width, x, y)]);
}
return yield imageUtil_1.imagePixelColor(this, x, y);
});
}
rgba(x, y) {
return __awaiter(this, void 0, void 0, function* () {
yield this.pixelCalculate();
return this._pixels[imageUtil_1.coordsToIndex(this.width, x, y)];
});
}
/**
* it will compute all pixel colors so following [pixel] and [rgba] calls will be fast
*/
pixelCalculate() {
return __awaiter(this, void 0, void 0, function* () {
this._pixels = yield imageUtil_1.getPixels(this);
});
}
/**
* Creates a DataUrl like `data:image/png;name=f.png;base64,` using given base64 content, mimeType and fileName.
*/
asDataUrl(mime) {
return __awaiter(this, void 0, void 0, function* () {
return File.toDataUrl(this, mime);
});
}
/**
* Returns base64 representation of this image in an encoded format like PNG
*/
asBase64(file) {
return File.toBase64(file);
}
/**
* Returns base64 representation of this image in an encoded format like PNG
*/
equals(file) {
return __awaiter(this, void 0, void 0, function* () {
return yield imageCompare_1.imageCompare(this, file);
});
}
/**
* Returns base64 representation of this image in an encoded format like PNG
*/
asArrayBuffer() {
return __awaiter(this, void 0, void 0, function* () {
return this.content.buffer;
});
}
asHTMLImageData() {
return __awaiter(this, void 0, void 0, function* () {
var d = yield this.asRGBAImageData();
return new ImageData(d.data, d.width, d.height);
});
}
asRGBAImageData() {
return __awaiter(this, void 0, void 0, function* () {
var size = yield this.size();
var { outputFiles } = this.name.endsWith('.rgba') && this.width && this.height ?
{ outputFiles: [this] } :
yield run_1.run({
script: `convert ${yield this.sizeDepthArgs()} '${this.name}[0]' ${yield this.sizeDepthArgs(false)} output.rgba`,
inputFiles: [this]
});
return {
data: new Uint8ClampedArray(outputFiles[0].content.buffer),
width: size.width,
height: size.height
};
});
}
sizeDepthArgs(onlyIfRGBA = true) {
return __awaiter(this, void 0, void 0, function* () {
return File.getSizeDepthArgs(this, onlyIfRGBA);
});
}
static getSizeDepthArgs(f, onlyIfRGBA = true) {
return __awaiter(this, void 0, void 0, function* () {
return (!onlyIfRGBA || f.name.endsWith('.rgba')) ? `-size ${yield f.widthXHeight()} -depth 8` : '';
});
}
/**
* Creates a DataUrl like `data:image/png;name=f.png;base64,` using given base64 content, mimeType and fileName.
*/
static toDataUrl(file, mime) {
return __awaiter(this, void 0, void 0, function* () {
return yield html_1.toDataUrl(file, mime);
});
}
/**
* Creates a File from given url. In Node.js urls must be absolute!.
*/
static fromUrl(url, o = {}) {
return __awaiter(this, void 0, void 0, function* () {
try {
const response = yield cross_fetch_1.default(url, o);
return new File(o.name || misc_utils_of_mine_generic_1.getFileNameFromUrl(url), new Uint8ClampedArray(yield response.arrayBuffer()), o.protected, url);
}
catch (error) {
console.error(error);
return undefined;
}
});
}
/**
* Creates a File from given ArrayBuffer.
*/
static fromArrayBuffer(b, o = {}) {
return __awaiter(this, void 0, void 0, function* () {
const f = new File(o.name || 'unknown', new Uint8ClampedArray(b), o.protected);
if (!o.name) {
const info = yield f.infoOne();
return new File(info.format ? 'unammed.' + info.format.toLowerCase() : 'unknown', f.content, o.protected);
}
return f;
});
}
/**
* Creates a File from given file system path. Only Node.js.
*/
static fromFile(f, o = {}) {
if (!misc_utils_of_mine_generic_1.isNode()) {
throw new Error('File.readFile() called in the browser.');
}
try {
return new File(o.name || misc_utils_of_mine_generic_1.basename(f), new Uint8ClampedArray(fs_1.readFileSync(f)), o.protected);
}
catch (error) {
console.error(error);
return undefined;
}
}
/**
* Returns the file content as plain string. This is useful to read the content of a .json or .txt file
* but not for images or other binary file content.
*/
static asString(f) {
return String.fromCharCode.apply(null, f.content);
}
/**
* Returns base64 representation of this image in an encoded format like PNG
*/
static toBase64(file) {
return base64_1.arrayBufferToBase64(file.content.buffer);
}
/**
* Loads file from given base64 string.
*/
static fromBase64(base64, name) {
return new File(name, Buffer.from(Base64.decode(base64), 'base64'));
}
/**
* Loads file from given data url string.
*/
static fromDataUrl(dataUrl, name) {
return File.fromBase64(base64_1.urlToBase64(dataUrl), name);
}
/**
* Loads files from files in html input element of type "file".
*/
static fromHtmlFileInputElement(el) {
return Promise.all(Array.from(el.files).map(file => new Promise((resolve, reject) => {
var reader = new FileReader();
reader.addEventListener('loadend', e => resolve(new File(file.name, new Uint8ClampedArray(reader.result))));
reader.readAsArrayBuffer(file);
})));
}
/**
* Shortcut for [resolve] that returns the first result.
*/
static resolveOne(files, options = { protected: false }) {
return __awaiter(this, void 0, void 0, function* () {
var a = yield File.resolve(files, options);
return a.length > 0 ? a[0] : undefined;
});
}
/**
* Given paths, urls or files it will try to load them all and return a list of File for those succeed.
*/
static resolve(files, options = { protected: false }) {
return __awaiter(this, void 0, void 0, function* () {
var fs = (misc_utils_of_mine_generic_1.asArray(files || [])).filter(misc_utils_of_mine_generic_1.notUndefined);
var result = yield misc_utils_of_mine_generic_1.serial(fs.map(f => () => __awaiter(this, void 0, void 0, function* () {
if (typeof f === 'string') {
if (misc_utils_of_mine_generic_1.isNode() && fs_1.existsSync(f)) {
return yield File.fromFile(f, options);
}
else {
return yield File.fromUrl(f, options);
}
}
else {
assert_1.ok(ArrayBuffer.isView(f.content));
return f;
}
})));
return result.filter(misc_utils_of_mine_generic_1.notUndefined).map(File.asFile);
});
}
static isFile(f) {
return !!f && !!f.name && !!f.content && typeof f.constructor !== 'undefined' && !!f.size && !!f.infoOne;
}
static asFile(f) {
return File.isFile(f) ? f : typeof f === 'string' ? fileUtil_1.readFile(f, magickLoaded_1.getFS()) : new File(f.name, f.content);
}
static asPath(f) {
return typeof f === 'string' ? f : f.name;
}
static fromRGBAImageData(d, name = 'img.rgba') {
return new File(name, d.data, undefined, undefined, d.width, d.height);
}
static fromHTMLImageData(d, name = 'img.rgba') {
return File.fromRGBAImageData(d, name);
}
static fileExists(f) {
return __awaiter(this, void 0, void 0, function* () {
const { FS } = yield magickLoaded_1.magickLoaded;
FS.chdir(options_1.getOption('emscriptenNodeFsRoot'));
return fileUtil_1.isDir(File.asPath(f), FS) || fileUtil_1.isFile(File.asPath(f), FS);
});
}
}
exports.File = File;
File.equals = (a, b) => File.asPath(a) !== File.asPath(b);
//# sourceMappingURL=file.js.map