UNPKG

image-in-browser

Version:

Package for encoding / decoding images, transforming images, applying filters, drawing primitives on images on the client side (no need for server Node.js)

493 lines 17.6 kB
import { Rational } from '../common/rational.js'; import { ExifImageTags, ExifTagNameToID } from './exif-tag.js'; import { IfdValueType } from './ifd-value-type.js'; import { IfdContainer } from './ifd-container.js'; import { IfdValue } from './ifd-value/ifd-value.js'; import { IfdAsciiValue } from './ifd-value/ifd-ascii-value.js'; import { IfdShortValue } from './ifd-value/ifd-short-value.js'; import { IfdRationalValue } from './ifd-value/ifd-rational-value.js'; import { IfdByteValue } from './ifd-value/ifd-byte-value.js'; import { IfdLongValue } from './ifd-value/ifd-long-value.js'; import { IfdSByteValue } from './ifd-value/ifd-sbyte-value.js'; import { IfdUndefinedValue } from './ifd-value/ifd-undefined-value.js'; import { IfdSShortValue } from './ifd-value/ifd-sshort-value.js'; import { IfdSLongValue } from './ifd-value/ifd-slong-value.js'; import { IfdSRationalValue } from './ifd-value/ifd-srational-value.js'; import { IfdSingleValue } from './ifd-value/ifd-single-value.js'; import { IfdDoubleValue } from './ifd-value/ifd-double-value.js'; import { StringUtils } from '../common/string-utils.js'; import { ArrayUtils } from '../common/array-utils.js'; export class IfdDirectory { get sub() { return this._sub; } get keys() { return this._data.keys(); } get values() { return this._data.values(); } get entries() { return this._data.entries(); } get size() { return this._data.size; } get isEmpty() { return this._data.size === 0 && this._sub.isEmpty; } get hasUserComment() { return this._data.has(0x9286); } get userComment() { var _a; const data = (_a = this._data.get(0x9286)) === null || _a === void 0 ? void 0 : _a.toData(); return data !== undefined ? StringUtils.utf8Decoder.decode(data) : undefined; } set userComment(v) { if (v === undefined) { this._data.delete(0x9286); } else { const codeUnits = StringUtils.getCodePoints(v); this._data.set(0x9286, new IfdUndefinedValue(codeUnits)); } } get hasImageDescription() { return this._data.has(0x010e); } get imageDescription() { var _a; return (_a = this._data.get(0x010e)) === null || _a === void 0 ? void 0 : _a.toString(); } set imageDescription(v) { if (v === undefined) { this._data.delete(0x010e); } else { this._data.set(0x010e, new IfdAsciiValue(v)); } } get hasMake() { return this._data.has(0x010f); } get make() { var _a; return (_a = this._data.get(0x010f)) === null || _a === void 0 ? void 0 : _a.toString(); } set make(v) { if (v === undefined) { this._data.delete(0x010f); } else { this._data.set(0x010f, new IfdAsciiValue(v)); } } get hasModel() { return this._data.has(0x0110); } get model() { var _a; return (_a = this._data.get(0x0110)) === null || _a === void 0 ? void 0 : _a.toString(); } set model(v) { if (v === undefined) { this._data.delete(0x0110); } else { this._data.set(0x0110, new IfdAsciiValue(v)); } } get hasOrientation() { return this._data.has(0x0112); } get orientation() { var _a; return (_a = this._data.get(0x0112)) === null || _a === void 0 ? void 0 : _a.toInt(); } set orientation(v) { if (v === undefined) { this._data.delete(0x0112); } else { this._data.set(0x0112, new IfdShortValue(v)); } } get hasResolutionX() { return this._data.has(0x011a); } get resolutionX() { var _a; return (_a = this._data.get(0x011a)) === null || _a === void 0 ? void 0 : _a.toRational(); } set resolutionX(v) { if (!this.setRational(0x011a, v)) { this._data.delete(0x011a); } } get hasResolutionY() { return this._data.has(0x011b); } get resolutionY() { var _a; return (_a = this._data.get(0x011b)) === null || _a === void 0 ? void 0 : _a.toRational(); } set resolutionY(v) { if (!this.setRational(0x011b, v)) { this._data.delete(0x011b); } } get hasResolutionUnit() { return this._data.has(0x0128); } get resolutionUnit() { var _a; return (_a = this._data.get(0x0128)) === null || _a === void 0 ? void 0 : _a.toInt(); } set resolutionUnit(v) { if (v === undefined) { this._data.delete(0x0128); } else { this._data.set(0x0128, new IfdShortValue(Math.trunc(v))); } } get hasImageWidth() { return this._data.has(0x0100); } get imageWidth() { var _a; return (_a = this._data.get(0x0100)) === null || _a === void 0 ? void 0 : _a.toInt(); } set imageWidth(v) { if (v === undefined) { this._data.delete(0x0100); } else { this._data.set(0x0100, new IfdShortValue(Math.trunc(v))); } } get hasImageHeight() { return this._data.has(0x0101); } get imageHeight() { var _a; return (_a = this._data.get(0x0101)) === null || _a === void 0 ? void 0 : _a.toInt(); } set imageHeight(v) { if (v === undefined) { this._data.delete(0x0101); } else { this._data.set(0x0101, new IfdShortValue(Math.trunc(v))); } } get hasSoftware() { return this._data.has(0x0131); } get software() { var _a; return (_a = this._data.get(0x0131)) === null || _a === void 0 ? void 0 : _a.toString(); } set software(v) { if (v === undefined) { this._data.delete(0x0131); } else { this._data.set(0x0131, new IfdAsciiValue(v)); } } get hasCopyright() { return this._data.has(0x8298); } get copyright() { var _a; return (_a = this._data.get(0x8298)) === null || _a === void 0 ? void 0 : _a.toString(); } set copyright(v) { if (v === undefined) { this._data.delete(0x8298); } else { this._data.set(0x8298, new IfdAsciiValue(v)); } } get hasGPSLatitudeRef() { return this._data.has(0x0001); } get gpsLatitudeRef() { var _a; return (_a = this._data.get(0x0001)) === null || _a === void 0 ? void 0 : _a.toString(); } set gpsLatitudeRef(v) { if (v === undefined) { this._data.delete(0x0001); } else { this._data.set(0x0001, new IfdAsciiValue(v)); } } get hasGPSLatitude() { return this._data.has(0x0002); } get gpsLatitude() { var _a; return (_a = this._data.get(0x0002)) === null || _a === void 0 ? void 0 : _a.toDouble(); } set gpsLatitude(v) { if (v === undefined) { this._data.delete(0x0002); } else { this._data.set(0x0002, new IfdDoubleValue(v)); } } get hasGPSLongitudeRef() { return this._data.has(0x0003); } get gpsLongitudeRef() { var _a; return (_a = this._data.get(0x0003)) === null || _a === void 0 ? void 0 : _a.toString(); } set gpsLongitudeRef(v) { if (v === undefined) { this._data.delete(0x0003); } else { this._data.set(0x0003, new IfdAsciiValue(v)); } } get hasGPSLongitude() { return this._data.has(0x0004); } get gpsLongitude() { var _a; return (_a = this._data.get(0x0004)) === null || _a === void 0 ? void 0 : _a.toDouble(); } set gpsLongitude(v) { if (v === undefined) { this._data.delete(0x0004); } else { this._data.set(0x0004, new IfdDoubleValue(v)); } } get hasGPSDate() { return this._data.has(0x001d); } get gpsDate() { var _a; return (_a = this._data.get(0x001d)) === null || _a === void 0 ? void 0 : _a.toString(); } set gpsDate(v) { if (v === undefined) { this._data.delete(0x001d); } else { this._data.set(0x001d, new IfdAsciiValue(v)); } } get dataSize() { const numEntries = this.size; let dataOffset = 2 + 12 * numEntries + 4; for (const value of this.values) { const dataSize = value.dataSize; if (dataSize > 4) { dataOffset += dataSize; } } for (const [_subName, subDir] of this.sub.entries) { let subSize = 2 + 12 * subDir.size; for (const value of subDir.values) { const dataSize = value.dataSize; if (dataSize > 4) { subSize += dataSize; } } dataOffset += subSize; } return dataOffset; } constructor(data) { this._sub = new IfdContainer(); this._data = data !== null && data !== void 0 ? data : new Map(); } setRational(tag, value) { if (value instanceof Rational) { this._data.set(tag, IfdRationalValue.from(value)); return true; } else if (ArrayUtils.isNumArrayOrTypedArray(value) && value.length >= 2) { const r = new Rational(value[0], value[1]); this._data.set(tag, IfdRationalValue.from(r)); return true; } return false; } static from(other) { return new IfdDirectory(new Map(other._data)); } static isArrayOfRationalNumbers(value) { return (Array.isArray(value) && value.every((v) => ArrayUtils.isNumArrayOrTypedArray(v) && v.length >= 2)); } has(tag) { return this._data.has(tag); } getValue(tag) { let _tag = tag; if (typeof _tag === 'string') { _tag = ExifTagNameToID.get(_tag); } if (typeof _tag === 'number') { return this._data.get(_tag); } return undefined; } setValue(tag, value) { let _tag = tag; if (typeof _tag === 'string') { _tag = ExifTagNameToID.get(_tag); } if (typeof _tag !== 'number') { return; } if (value === undefined) { this._data.delete(_tag); } else { if (value instanceof IfdValue) { this._data.set(_tag, value); } else { const tagInfo = ExifImageTags.get(_tag); if (tagInfo !== undefined) { const tagType = tagInfo.type; switch (tagType) { case IfdValueType.byte: if (ArrayUtils.isNumArrayOrTypedArray(value)) { this._data.set(_tag, new IfdByteValue(new Uint8Array(value))); } else if (typeof value === 'number') { this._data.set(_tag, new IfdByteValue(value)); } break; case IfdValueType.ascii: if (typeof value === 'string') { this._data.set(_tag, new IfdAsciiValue(value)); } break; case IfdValueType.short: if (ArrayUtils.isNumArrayOrTypedArray(value)) { this._data.set(_tag, new IfdShortValue(new Uint16Array(value))); } else if (typeof value === 'number') { this._data.set(_tag, new IfdShortValue(value)); } break; case IfdValueType.long: if (ArrayUtils.isNumArrayOrTypedArray(value)) { this._data.set(_tag, new IfdLongValue(new Uint32Array(value))); } else if (typeof value === 'number') { this._data.set(_tag, new IfdLongValue(value)); } break; case IfdValueType.rational: if (ArrayUtils.isArrayOfRational(value)) { this._data.set(_tag, new IfdRationalValue(value)); } else if (ArrayUtils.isNumArrayOrTypedArray(value) && value.length >= 2) { const r = new Rational(value[0], value[1]); this._data.set(_tag, new IfdRationalValue(r)); } else if (value instanceof Rational) { this._data.set(_tag, new IfdRationalValue(value)); } break; case IfdValueType.sByte: if (ArrayUtils.isNumArrayOrTypedArray(value)) { this._data.set(_tag, new IfdSByteValue(new Int8Array(value))); } else if (typeof value === 'number') { this._data.set(_tag, new IfdSByteValue(value)); } break; case IfdValueType.undefined: if (ArrayUtils.isNumArrayOrTypedArray(value)) { this._data.set(_tag, new IfdUndefinedValue(new Uint8Array(value))); } break; case IfdValueType.sShort: if (ArrayUtils.isNumArrayOrTypedArray(value)) { this._data.set(_tag, new IfdSShortValue(new Int16Array(value))); } else if (typeof value === 'number') { this._data.set(_tag, new IfdSShortValue(value)); } break; case IfdValueType.sLong: if (ArrayUtils.isNumArrayOrTypedArray(value)) { this._data.set(_tag, new IfdSLongValue(new Int32Array(value))); } else if (typeof value === 'number') { this._data.set(_tag, new IfdSLongValue(value)); } break; case IfdValueType.sRational: if (ArrayUtils.isArrayOfRational(value)) { this._data.set(_tag, new IfdSRationalValue(value)); } else if (ArrayUtils.isNumArrayOrTypedArray(value) && value.length >= 2) { const r = new Rational(value[0], value[1]); this._data.set(_tag, new IfdSRationalValue(r)); } else if (value instanceof Rational) { this._data.set(_tag, new IfdSRationalValue(value)); } break; case IfdValueType.single: if (ArrayUtils.isNumArrayOrTypedArray(value)) { this._data.set(_tag, new IfdSingleValue(new Float32Array(value))); } else if (typeof value === 'number') { this._data.set(_tag, new IfdSingleValue(value)); } break; case IfdValueType.double: if (ArrayUtils.isNumArrayOrTypedArray(value)) { this._data.set(_tag, new IfdDoubleValue(new Float64Array(value))); } else if (typeof value === 'number') { this._data.set(_tag, new IfdDoubleValue(value)); } break; case IfdValueType.none: break; } } } } } setGpsLocation(latitude, longitude) { this.gpsLatitude = Math.abs(latitude); this.gpsLongitude = Math.abs(longitude); this.gpsLatitudeRef = latitude < 0 ? 'S' : 'N'; this.gpsLongitudeRef = longitude < 0 ? 'W' : 'E'; } copyFrom(other) { other._data.forEach((value, tag) => this._data.set(tag, value.clone())); for (const [tag, value] of other._sub.entries) { this._sub.set(tag, value.clone()); } } clone() { return IfdDirectory.from(this); } } //# sourceMappingURL=ifd-directory.js.map