UNPKG

@mescius/dsimageviewer

Version:

Document Solutions Image Viewer

393 lines (392 loc) 13.7 kB
var s = /* @__PURE__ */ ((i) => (i[i.Default = 0] = "Default", i[i.JPEG = 1] = "JPEG", i[i.PNG = 2] = "PNG", i[i.TIFF = 3] = "TIFF", i[i.GIF = 4] = "GIF", i[i.BMP = 5] = "BMP", i[i.ICO = 6] = "ICO", i[i.SVG = 7] = "SVG", i[i.WEBP = 8] = "WEBP", i))(s || {}); navigator.userAgent.indexOf("Trident/") > -1; let c; function g() { return c || (c = {}, c[s.TIFF] = ["tif", "tiff", "xif", "xiff", "image/tiff", "image/tiff-fx", "image/x-tif", "image/x-tiff", "image/vnd.xiff", "images/xif", "application/tif", "application/tiff", "application/x-tif", "application/x-tiff"], c[s.BMP] = ["bmp", "bitmap", "application/bmp", "application/x-bmp", "application/x-win-bitmap", "image/ms-bmp", "image/x-bitmap", "image/x-bmp", "image/x-ms-bmp", "image/x-win-bitmap", "image/x-windows-bmp", "image/x-xbitmap"], c[s.SVG] = ["svg", "svg+xml", "text/xml-svg", "text/xml+svg", "image/svg", "image/svg-xml", "image/svg+xml", "image/vnd.adobe.svg+xml"], c[s.ICO] = ["ico", "image/ico", "image/x-icon", "application/ico", "application/x-ico"], c[s.GIF] = ["gif", "image/gi_", "image/gif"], c[s.JPEG] = ["jpg", "jpeg", "image/jp_", "image/jpe_", "image/jpg", "image/jpeg", "image/pipeg", "image/pjpeg", "application/jpg", "application/x-jpg", "image/vnd.swiftview-jpeg"], c[s.PNG] = ["png", "image/png", "application/png", "application/x-png"], c[s.WEBP] = ["webp", "image/webp"]), c; } function f(i, t = s.Default) { if (!i) return t; if (typeof i == "number") return i; const e = []; if (typeof i == "string") e.push(i.toLowerCase().split(".").pop() || i); else { if (i.buffer) return t; i.type && e.push(i.type.toLowerCase()), i.name && e.push(i.name.toLowerCase().split(".").pop() || i.name); } const a = g(); for (const o of e) for (const n in a) if (a[n].find((p) => p === o)) return n * 1; return t; } class m { /** * Gets the internationalization (i18n) instance from the viewer. * @returns {i18n} The i18n instance. */ get in17n() { return this._viewer.in17n; } /** * Viewer instance identifier. * @ignore exclude from docs. **/ get instanceId() { return this._viewer.instanceId; } /** * Returns true if the image is loaded into the viewer and the image format is supported by the plugin. **/ get isReady() { const t = this._viewer; return t ? t.viewerState.session.status === 3 && t.hasImage && this.isImageFormatSupported(t.imageFormat, !0) : !1; } /** * Natural image size. **/ get naturalSize() { return this._viewer.naturalSize; } /** * Gets the paint layer containing the HTML canvas for drawing the image. **/ get paintLayer() { return this._paintLayer || (this._paintLayer = this.viewer.ensurePaintLayer(), this.viewer.invalidate(), this.viewer.selectionBox.invalidate()), this._paintLayer; } /** * Gets the image viewer instance. * @returns {IImageViewer} The image viewer instance. */ get viewer() { return this._viewer; } /** * Initializes the plugin with the given image viewer. * @param {IImageViewer} viewer - The image viewer instance to associate with this plugin. * @returns {void} */ initialize(t) { this._viewer = t; } /** * Cleans up resources and disposes the plugin. * @returns {void} */ dispose() { this._viewer = void 0; } /** * Determines whether the specified image format is supported for modifications. * * @param {ImageFormatCode | string} imageFormat - The image format to check, either as an enum value or string. * @param {boolean} [allowUnknown=false] - If true, allows unknown formats (ImageFormatCode.Default) to be considered supported. * @returns {boolean} True if the format is supported for modifications, false otherwise. * * @remarks * The following formats are explicitly not supported: * - TIFF (ImageFormatCode.TIFF) * - SVG (ImageFormatCode.SVG) * - ICO (ImageFormatCode.ICO) * - GIF (ImageFormatCode.GIF) * * @example * // Check if PNG is supported * const supported = isImageFormatSupported(ImageFormatCode.PNG); * * @example * // Check if an unknown format is supported (returns false by default) * const supported = isImageFormatSupported('custom-format'); * * @example * // Check if an unknown format is supported (returns true when allowUnknown is true) * const supported = isImageFormatSupported('custom-format', true); */ isImageFormatSupported(t, e) { return t = f(t, s.Default), !e && t === s.Default ? !1 : t !== s.TIFF && t !== s.SVG && t !== s.ICO && t !== s.GIF; } /** * Removes and disposes the active paint layer. * If no paint layer exists, this method does nothing. * @returns {void} */ removePaintLayer() { this._paintLayer && (this.viewer.removeLayer(this._paintLayer), this._paintLayer = void 0); } } class v { /** * Constructor. * @param horizontal * @param vertical * @param rotationPlugin */ constructor(t, e, a) { this.horizontal = t, this.vertical = e, this.rotationPlugin = a, this.name = "Flip"; } /** * Action implementation. * @param viewer **/ async execute(t) { await this.rotationPlugin.flip(this.horizontal, this.vertical); } /** * Undo action implementation. * @param viewer **/ async undo(t) { await this.rotationPlugin.flip(this.horizontal, this.vertical); } } class w { /** * Constructor. * @param rotation * @param prevRotation * @param rotationPlugin */ constructor(t, e) { this.rotation = t, this.rotationPlugin = e, this.name = "Rotation"; } /** * Action implementation. * @param viewer **/ async execute(t) { await this.rotationPlugin.rotate(this.rotation); } /** * Undo action implementation. * @param viewer **/ async undo(t) { await this.rotationPlugin.rotate(-this.rotation); } } function h(i) { return i === !1 ? -1 : i || 0; } function _(i, t, e = 0, a = 0, o = !1, n = !1) { i.save(), i.setTransform( o ? -1 : 1, 0, // set the direction of x axis 0, n ? -1 : 1, // set the direction of y axis e + o ? t.width : 0, // set the x origin a + n ? t.height : 0 // set the y origin ), i.drawImage(t, 0, 0), i.restore(); } class y extends m { /** * RotationPlugin constructor. * @param options */ constructor(t) { super(), this.id = "rotation", t = t || { rotatePosition: 1, flipHorizontalPosition: 2, flipVerticalPosition: 3 }, this.options = t; } initialize(t) { this._viewer = t, this._ensureOptions(), t.toolbar.addItem(d(t, this)), t.toolbar.addItem(b(t, this)), t.toolbar.addItem(I(t, this)); const e = { "rotate-image": h(this.options.rotatePosition), "flip-horizontal": h(this.options.flipHorizontalPosition), "flip-vertical": h(this.options.flipVerticalPosition) }, a = []; for (const o in e) { const n = e[o]; n !== -1 && Number.isFinite(n) && (a[n] = o); } for (let o = 0; o < a.length; o++) { const n = a[o]; n && ((t.toolbarLayout.viewer.default || []).splice(o, 0, n), (t.toolbarLayout.viewer.fullscreen || []).splice(o, 0, n), (t.toolbarLayout.viewer.mobile || []).splice(o, 0, n)); } t.applyToolbarLayout(), t.onBeforeOpen.register(this._onBeforeOpen.bind(this)), this._initialized = !0; } dispose() { this._initialized && (this._initialized = !1, this._removeRotateButtonFromLayout(this._viewer.toolbarLayout.viewer.default || [], "rotate-image"), this._removeRotateButtonFromLayout(this._viewer.toolbarLayout.viewer.fullscreen || [], "rotate-image"), this._removeRotateButtonFromLayout(this._viewer.toolbarLayout.viewer.mobile || [], "rotate-image"), this._removeRotateButtonFromLayout(this._viewer.toolbarLayout.viewer.default || [], "flip-horizontal"), this._removeRotateButtonFromLayout(this._viewer.toolbarLayout.viewer.fullscreen || [], "flip-horizontal"), this._removeRotateButtonFromLayout(this._viewer.toolbarLayout.viewer.mobile || [], "flip-horizontal"), this._removeRotateButtonFromLayout(this._viewer.toolbarLayout.viewer.default || [], "flip-vertical"), this._removeRotateButtonFromLayout(this._viewer.toolbarLayout.viewer.fullscreen || [], "flip-vertical"), this._removeRotateButtonFromLayout(this._viewer.toolbarLayout.viewer.mobile || [], "flip-vertical"), this._viewer.toolbar.removeItem("rotate-image"), this._viewer.toolbar.removeItem("flip-horizontal"), this._viewer.toolbar.removeItem("flip-vertical"), this._viewer = null, this._originalNaturalSize = null); } /** * Specifies the rotation in degrees. **/ getRotation() { return this._rotation || 0; } async rotate(t) { return this.setRotation(this._rotation + t); } /** * Specifies the rotation in degrees. **/ async setRotation(t) { t = t % 360; const e = await this._rotateImageData(t); return e && !this._viewer.undoStorage.undoInProgress && this._viewer.undoStorage.onCommandExecuted(new w(t, this)), this._rotation = t, e; } /** * Checks if the image format specified by the imageFormat parameter is supported. * @param imageFormat **/ isImageFormatSupported(t) { return t = f(t), t !== s.TIFF && t !== s.SVG && t !== s.ICO && t !== s.GIF; } /** * Flip image. **/ flip(t = !0, e = !1) { return new Promise((a) => { const o = this._viewer, n = o.naturalSize, p = document.createElement("canvas"); p.width = n.width, p.height = n.height; const u = p.getContext("2d"), l = new Image(); l.onload = () => { _(u, l, 0, 0, t, e); try { const r = o.canvasToDataURL(p); o.setImageDataUrl(r).then(() => { a(!0), this._viewer.undoStorage.undoInProgress || this._viewer.undoStorage.onCommandExecuted(new v(t, e, this)); }); } catch (r) { console.error(r), a(!1); } }, l.onerror = function(r) { console.error(r), a(!1); }, l.crossOrigin = "Anonymous"; try { l.src = o.getImageDataUrl(); } catch (r) { console.error(r), a(!1); } }); } /** * Flip image horizontally. **/ flipHorizontal() { return this.flip(!0, !1); } /** * Flip image vertically. **/ flipVertical() { return this.flip(!1, !0); } //#region ** private _removeRotateButtonFromLayout(t, e) { if (!t) return; const a = t.findIndex((o) => o === e); a !== -1 && t.splice(a, 1); } _onBeforeOpen() { this._originalNaturalSize = null, this._rotation = 0; } /** * Rotate image data action. **/ _rotateImageData(t) { return new Promise((e) => { const a = this._viewer, o = this._originalNaturalSize || a.naturalSize; if (this._originalNaturalSize || (this._originalNaturalSize = o), a.imageFormat === 3) { alert("Cannot rotate TIFF image."), e(!1); return; } if (a.imageFormat === 7) { let r = a.getOriginalImageDataUrl(); t && (r = r.replace("<svg", '<svg transform="rotate(' + t + ')"')), a.setImageDataUrl(r), e(!0); return; } const n = document.createElement("canvas"), p = this._imageSizeAfterRotation([o.width, o.height], t); n.width = p[0], n.height = p[1]; const u = n.getContext("2d"); u.translate(n.width / 2, n.height / 2), u.rotate(t * Math.PI / 180); const l = new Image(); l.onload = function() { u.drawImage(l, -o.width / 2, -o.height / 2); try { const r = a.canvasToDataURL(n); a.setImageDataUrl(r), e(!0); } catch (r) { alert(r), e(!1); } }, l.onerror = function(r) { console.error(r), e(!1); }, l.crossOrigin = "Anonymous"; try { l.src = a.getOriginalImageDataUrl(); } catch (r) { alert(r), e(!1); return; } }); } _imageSizeAfterRotation(t, e) { if (e = e % 180, e < 0 && (e = 180 + e), e >= 90 && (t = [t[1], t[0]], e = e - 90), e === 0) return t; const a = e * Math.PI / 180, o = t[0] * Math.cos(a) + t[1] * Math.sin(a), n = t[0] * Math.sin(a) + t[1] * Math.cos(a); return [o, n]; } _ensureOptions() { const t = this.options || {}; t.rotatePosition === void 0 && (t.rotatePosition = 1), this.options = t; } //#endregion } (window || {}).RotationPlugin = y; function d(i, t) { return { key: "rotate-image", icon: { type: "svg", content: i.getType("svgIcons").rotate }, title: "Rotate image", checked: !1, enabled: !1, action: () => { t.setRotation(t.getRotation() + 90); }, onUpdate: (a) => ({ title: t.getRotation() ? "Rotate image (" + t.getRotation() + "deg)" : "Rotate image", enabled: a.state.session.status === 3 && i.hasImage && t.isImageFormatSupported(i.imageFormat) }) }; } function b(i, t) { return { key: "flip-horizontal", icon: { type: "svg", content: i.getType("svgIcons")["flip-horizontal"] }, title: "Flip horizontal", checked: !1, enabled: !1, action: () => { t.flipHorizontal(); }, onUpdate: (a) => ({ title: "Flip horizontal", enabled: a.state.session.status === 3 && i.hasImage && t.isImageFormatSupported(i.imageFormat) }) }; } function I(i, t) { return { key: "flip-vertical", icon: { type: "svg", content: i.getType("svgIcons")["flip-vertical"] }, title: "Flip vertical", checked: !1, enabled: !1, action: () => { t.flipVertical(); }, onUpdate: (a) => ({ title: "Flip vertical", enabled: a.state.session.status === 3 && i.hasImage && t.isImageFormatSupported(i.imageFormat) }) }; } export { y as RotationPlugin, _ as mirrorImage };