diff --git a/LICENSE b/LICENSE
index 53272a9b3..b037264c4 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,7 +1,7 @@
The MIT License (MIT)
Copyright (c) 2014-2015 Jérémy Heleine
-Copyright (c) 2016-2022 Damien Sorel
+Copyright (c) 2016-2023 Damien Sorel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/build/tsup.config.js b/build/tsup.config.js
index 177b77f9c..72abb29b2 100644
--- a/build/tsup.config.js
+++ b/build/tsup.config.js
@@ -18,7 +18,7 @@ const externals = {
'@photo-sphere-viewer/settings-plugin': 'PhotoSphereViewer.SettingsPlugin',
};
-export default function createConfig(pkg, entry = 'src/index.ts') {
+export default function createConfig(pkg) {
const banner = `/*!
* ${pkg.psv.globalName} ${pkg.version}
${
@@ -32,7 +32,7 @@ ${
const dts = !dev && options.define?.['dts'] !== 'off';
return {
- entryPoints: [entry],
+ entryPoints: [pkg.main],
outDir: 'dist',
format: dev ? ['esm'] : ['iife', 'esm'],
globalName: pkg.psv.globalName,
diff --git a/docs/guide/adapters/equirectangular-tiles.md b/docs/guide/adapters/equirectangular-tiles.md
index d1fb4a8b8..f129dc289 100644
--- a/docs/guide/adapters/equirectangular-tiles.md
+++ b/docs/guide/adapters/equirectangular-tiles.md
@@ -82,11 +82,9 @@ Shows a warning sign on tiles that cannot be loaded.
Applies antialiasing to high resolutions tiles.
-#### `canvasBackround`
+#### `backgroundColor`
-See the [equirectangular adapter configuration](./equirectangular.md#canvasbackround).
-
-_Note:_ `'auto'` is only applicable if a `baseUrl` is provided on the panorama.
+See the [equirectangular adapter configuration](./equirectangular.md#backgroundcolor).
#### `resolution`
diff --git a/docs/guide/adapters/equirectangular.md b/docs/guide/adapters/equirectangular.md
index f5c30c37d..a273845a5 100644
--- a/docs/guide/adapters/equirectangular.md
+++ b/docs/guide/adapters/equirectangular.md
@@ -26,12 +26,23 @@ const viewer = new PhotoSphereViewer.Viewer({
Read real image size from XMP data, must be kept `true` if the panorama has been cropped after shot. This is used for [cropped panorama](#cropped-panorama).
-#### `canvasBackground`
+#### `backgroundColor`
-- type: `'auto' | string`
+- type: `string`
- default: `#000`
-Background color of the canvas, which will be visible when using cropped panoramas. When set to `auto`, a blurry background will be generated from the panorama image.
+Background color of the viewer, which will be visible when using cropped panoramas.
+
+#### `interpolateBackground`
+
+- type: `boolean`
+- default: `false`
+
+Interpolate the missing parts of cropped panorama with a blur effect.
+
+::: warning
+The interpolation is done asynchronously in a web worker, as such the panorama will be first be displayed without interpolation with only `canvasBackground` applied, then the interpolated image will be shown (takes about 1-3 seconds depending on the hardware).
+:::
#### `resolution`
diff --git a/docs/guide/config.md b/docs/guide/config.md
index e0ac2459d..3fbf938b3 100644
--- a/docs/guide/config.md
+++ b/docs/guide/config.md
@@ -312,7 +312,7 @@ requestHeaders: (url) => ({
#### ~~`canvasBackground`~~
-Deprecated : must be configured [on the adapter](./adapters/equirectangular.md#canvasbackround).
+Deprecated : must be configured [on the adapter](./adapters/equirectangular.md#backgroundcolor).
#### `moveInertia`
diff --git a/examples/misc-equirectangular-cropped.html b/examples/misc-equirectangular-cropped.html
index 8c825ce35..8ea4d0e02 100644
--- a/examples/misc-equirectangular-cropped.html
+++ b/examples/misc-equirectangular-cropped.html
@@ -31,7 +31,8 @@
caption: 'Parc national du Mercantour © Damien Sorel',
loadingImg: baseUrl + 'loader.gif',
adapter: [EquirectangularAdapter, {
- canvasBackground: 'auto',
+ backgroundColor: '#77addb',
+ interpolateBackground: true,
}],
});
diff --git a/packages/core/src/adapters/EquirectangularAdapter.ts b/packages/core/src/adapters/EquirectangularAdapter.ts
index f3e2acb5d..fca0df916 100644
--- a/packages/core/src/adapters/EquirectangularAdapter.ts
+++ b/packages/core/src/adapters/EquirectangularAdapter.ts
@@ -5,18 +5,15 @@ import { SPHERE_RADIUS } from '../data/constants';
import { SYSTEM } from '../data/system';
import { PanoData, PanoDataProvider, TextureData } from '../model';
import {
- averageRgb,
- createHorizontalGradient,
createTexture,
firstNonNull,
- getAverageColor,
getConfigParser,
getXMPValue,
isNil,
- logWarn,
- rgbCss,
+ logWarn
} from '../utils';
import { AbstractAdapter } from './AbstractAdapter';
+import { interpolationWorkerSrc } from './interpolationWorker';
/**
* Configuration for {@link EquirectangularAdapter}
@@ -26,7 +23,11 @@ export type EquirectangularAdapterConfig = {
* Background color of the canvas, which will be visible when using cropped panoramas
* @default '#000'
*/
- canvasBackground?: 'auto' | string;
+ backgroundColor?: string;
+ /**
+ * Interpolate the missing parts of cropped panoramas (async)
+ */
+ interpolateBackground?: boolean;
/**
* number of faces of the sphere geometry, higher values may decrease performances
* @default 64
@@ -49,7 +50,8 @@ type EquirectangularTexture = TextureData;
const getConfig = getConfigParser(
{
- canvasBackground: '#000',
+ backgroundColor: '#000',
+ interpolateBackground: false,
resolution: 64,
useXmpData: true,
blur: false,
@@ -74,6 +76,8 @@ export class EquirectangularAdapter extends AbstractAdapter {
private readonly config: EquirectangularAdapterConfig;
+ private interpolationWorker: Worker;
+
private readonly SPHERE_SEGMENTS: number;
private readonly SPHERE_HORIZONTAL_SEGMENTS: number;
@@ -85,7 +89,11 @@ export class EquirectangularAdapter extends AbstractAdapter {
this.config.useXmpData = this.viewer.config.useXmpData;
}
if (!isNil(this.viewer.config.canvasBackground)) {
- this.config.canvasBackground = this.viewer.config.canvasBackground;
+ this.config.backgroundColor = this.viewer.config.canvasBackground;
+ }
+
+ if (this.config.interpolateBackground) {
+ this.interpolationWorker = new Worker(interpolationWorkerSrc);
}
this.SPHERE_SEGMENTS = this.config.resolution;
@@ -100,6 +108,12 @@ export class EquirectangularAdapter extends AbstractAdapter {
return true;
}
+ override destroy(): void {
+ this.interpolationWorker?.terminate();
+
+ super.destroy();
+ }
+
async loadTexture(
panorama: string,
newPanoData: PanoData | PanoDataProvider,
@@ -220,16 +234,15 @@ export class EquirectangularAdapter extends AbstractAdapter {
const ctx = buffer.getContext('2d');
- if (this.config.canvasBackground === 'auto') {
- this.__autoBackground(buffer, img, resizedPanoData);
- } else {
- ctx.fillStyle = this.config.canvasBackground ?? '#000';
+ if (this.config.backgroundColor) {
+ ctx.fillStyle = this.config.backgroundColor;
ctx.fillRect(0, 0, buffer.width, buffer.height);
}
- ctx.filter = this.config.blur ? `blur(${buffer.width / 2048}px)` : 'none';
+ if (this.config.blur) {
+ ctx.filter = `blur(${buffer.width / 2048}px)`;
+ }
- // final draw
ctx.drawImage(
img,
resizedPanoData.croppedX,
@@ -238,7 +251,30 @@ export class EquirectangularAdapter extends AbstractAdapter {
resizedPanoData.croppedHeight
);
- return createTexture(buffer);
+ const t = createTexture(buffer);
+
+ if (this.config.interpolateBackground && (
+ panoData.croppedWidth !== panoData.fullWidth
+ || panoData.croppedHeight !== panoData.fullHeight
+ )) {
+ this.interpolationWorker.postMessage({
+ image: ctx.getImageData(
+ resizedPanoData.croppedX,
+ resizedPanoData.croppedY,
+ resizedPanoData.croppedWidth,
+ resizedPanoData.croppedHeight
+ ),
+ panoData: resizedPanoData,
+ });
+
+ this.interpolationWorker.onmessage = (e) => {
+ ctx.putImageData(e.data, 0, 0);
+ t.needsUpdate = true;
+ this.viewer.needsUpdate();
+ };
+ }
+
+ return t;
}
return createTexture(img);
@@ -304,150 +340,4 @@ export class EquirectangularAdapter extends AbstractAdapter {
};
}
- /**
- * Many operations draw outside the canvas in order to have a correct blur filter
- */
- private __autoBackground(buffer: HTMLCanvasElement, img: HTMLImageElement, panoData: PanoData) {
- const croppedY2 = panoData.fullHeight - panoData.croppedHeight - panoData.croppedY;
- const croppedX2 = panoData.fullWidth - panoData.croppedWidth - panoData.croppedX;
- const middleY = panoData.croppedY + panoData.croppedHeight / 2;
-
- if (panoData.croppedX <= 0 && panoData.croppedY <= 0 && croppedX2 <= 0 && croppedY2 <= 0) {
- return;
- }
-
- const blurSize = buffer.width / 32;
- const padding = blurSize;
- const edge = 10;
- const filter = `blur(${blurSize}px)`;
-
- const ctx = buffer.getContext('2d');
-
- // first draw to get the colors
- ctx.drawImage(
- img,
- panoData.croppedX,
- panoData.croppedY,
- panoData.croppedWidth,
- panoData.croppedHeight
- );
-
- // top section
- if (panoData.croppedY > 0) {
- if (panoData.croppedX > 0 || croppedX2 > 0) {
- ctx.filter = 'none';
-
- const colorLeft = getAverageColor(ctx, panoData.croppedX, panoData.croppedY, edge, edge, 2);
- const colorRight = getAverageColor(ctx, buffer.width - croppedX2 - 11, panoData.croppedY, edge, edge, 2);
- const colorCenter = averageRgb(colorLeft, colorRight);
-
- // top-left corner
- if (panoData.croppedX > 0) {
- ctx.fillStyle = createHorizontalGradient(ctx, 0, panoData.croppedX, colorCenter, colorLeft);
- ctx.fillRect(-padding, -padding, panoData.croppedX + padding * 2, middleY + padding);
- }
-
- // top right corner
- if (croppedX2 > 0) {
- ctx.fillStyle = createHorizontalGradient(ctx, buffer.width - croppedX2, buffer.width, colorRight, colorCenter);
- ctx.fillRect(buffer.width - croppedX2 - padding, -padding, croppedX2 + padding * 2, middleY + padding);
- }
- }
-
- ctx.filter = filter;
-
- // top
- ctx.drawImage(
- img,
- 0, 0,
- img.width, edge,
- panoData.croppedX, -padding,
- panoData.croppedWidth, panoData.croppedY + padding * 2
- );
-
- // hide to top seam
- ctx.fillStyle = rgbCss(getAverageColor(ctx, 0, 0, buffer.width, edge, edge));
- ctx.fillRect(-padding, -padding, buffer.width + padding * 2, padding * 2);
- }
-
- // bottom section
- if (croppedY2 > 0) {
- if (panoData.croppedX > 0 || croppedX2 > 0) {
- ctx.filter = 'none';
-
- const colorLeft = getAverageColor(ctx, panoData.croppedX, buffer.height - croppedY2 - 1 - edge, edge, edge, 2);
- const colorRight = getAverageColor(ctx, buffer.width - croppedX2 - 1 - edge, buffer.height - croppedY2 - 1 - edge, edge, edge, 2);
- const colorCenter = averageRgb(colorLeft, colorRight);
-
- // bottom-left corner
- if (panoData.croppedX > 0) {
- ctx.fillStyle = createHorizontalGradient(ctx, 0, panoData.croppedX, colorCenter, colorLeft);
- ctx.fillRect(-padding, middleY, panoData.croppedX + padding * 2, buffer.height - middleY + padding);
- }
-
- // bottom-right corner
- if (croppedX2 > 0) {
- ctx.fillStyle = createHorizontalGradient(ctx, buffer.width - croppedX2, buffer.width, colorRight, colorCenter);
- ctx.fillRect(buffer.width - croppedX2 - padding, middleY, croppedX2 + padding * 2, buffer.height - middleY + padding);
- }
- }
-
- ctx.filter = filter;
-
- // bottom
- ctx.drawImage(
- img,
- 0, img.height - edge,
- img.width, edge,
- panoData.croppedX, buffer.height - croppedY2 - padding,
- panoData.croppedWidth, croppedY2 + padding * 2
- );
-
- // hide the bottom seam
- ctx.fillStyle = rgbCss(getAverageColor(ctx, 0, buffer.height - 1 - edge, buffer.width, edge, edge));
- ctx.fillRect(-padding, buffer.height - padding, buffer.width + padding * 2, padding * 2);
- }
-
- // left section
- if (panoData.croppedX > 0) {
- ctx.filter = filter;
-
- ctx.drawImage(
- img,
- img.width - edge, 0,
- edge, img.height,
- -padding, panoData.croppedY,
- padding * 2, panoData.croppedHeight
- );
-
- ctx.drawImage(
- img,
- 0, 0,
- edge, img.height,
- 0, panoData.croppedY,
- panoData.croppedX + padding, panoData.croppedHeight
- );
- }
-
- // right section
- if (croppedX2 > 0) {
- ctx.filter = filter;
-
- ctx.drawImage(
- img,
- 0, 0,
- edge, img.height,
- buffer.width - padding, panoData.croppedY,
- padding * 2, panoData.croppedHeight
- );
-
- ctx.drawImage(
- img,
- img.width - edge, 0,
- edge, img.height,
- buffer.width - croppedX2 - padding, panoData.croppedY,
- croppedX2 + padding, panoData.croppedHeight
- );
- }
- }
}
diff --git a/packages/core/src/adapters/interpolationWorker.ts b/packages/core/src/adapters/interpolationWorker.ts
new file mode 100644
index 000000000..80ca2d50b
--- /dev/null
+++ b/packages/core/src/adapters/interpolationWorker.ts
@@ -0,0 +1,250 @@
+import type { RGB } from 'three';
+import type { PanoData } from '../model';
+
+/**
+ * Web Worker function to interpolate missing parts of cropped panoramas
+ * WARNING : this function must be autonomous
+ */
+function interpolationWorker() {
+ self.onmessage = (e: MessageEvent) => {
+ const panoData: PanoData = e.data.panoData;
+
+ const buffer = new OffscreenCanvas(panoData.fullWidth, panoData.fullHeight);
+ const ctx = buffer.getContext('2d');
+
+ const img = new OffscreenCanvas(panoData.croppedWidth, panoData.croppedHeight);
+ const ctxImg = img.getContext('2d');
+ ctxImg.putImageData(e.data.image, 0, 0);
+
+ autoBackground(buffer, img, panoData);
+
+ postMessage(ctx.getImageData(0, 0, buffer.width, buffer.height));
+ };
+
+ function autoBackground(buffer: OffscreenCanvas, img: OffscreenCanvas, panoData: PanoData) {
+ const croppedY2 = panoData.fullHeight - panoData.croppedHeight - panoData.croppedY;
+ const croppedX2 = panoData.fullWidth - panoData.croppedWidth - panoData.croppedX;
+ const middleY = panoData.croppedY + panoData.croppedHeight / 2;
+
+ const blurSize = buffer.width / 32;
+ const padding = blurSize;
+ const edge = 10;
+ const filter = `blur(${blurSize}px)`;
+
+ const ctx = buffer.getContext('2d');
+
+ // first draw to get the colors
+ ctx.drawImage(
+ img,
+ panoData.croppedX,
+ panoData.croppedY,
+ panoData.croppedWidth,
+ panoData.croppedHeight
+ );
+
+ // top section
+ if (panoData.croppedY > 0) {
+ if (panoData.croppedX > 0 || croppedX2 > 0) {
+ ctx.filter = 'none';
+
+ const colorLeft = getAverageColor(ctx, panoData.croppedX, panoData.croppedY, edge, edge, 2);
+ const colorRight = getAverageColor(ctx, buffer.width - croppedX2 - 11, panoData.croppedY, edge, edge, 2);
+ const colorCenter = averageRgb(colorLeft, colorRight);
+
+ // top-left corner
+ if (panoData.croppedX > 0) {
+ ctx.fillStyle = createHorizontalGradient(ctx, 0, panoData.croppedX, colorCenter, colorLeft);
+ ctx.fillRect(-padding, -padding, panoData.croppedX + padding * 2, middleY + padding);
+ }
+
+ // top right corner
+ if (croppedX2 > 0) {
+ ctx.fillStyle = createHorizontalGradient(ctx, buffer.width - croppedX2, buffer.width, colorRight, colorCenter);
+ ctx.fillRect(buffer.width - croppedX2 - padding, -padding, croppedX2 + padding * 2, middleY + padding);
+ }
+ }
+
+ ctx.filter = filter;
+
+ // top
+ ctx.drawImage(
+ img,
+ 0, 0,
+ img.width, edge,
+ panoData.croppedX, -padding,
+ panoData.croppedWidth, panoData.croppedY + padding * 2
+ );
+
+ // hide to top seam
+ ctx.fillStyle = rgbCss(getAverageColor(ctx, 0, 0, buffer.width, edge, edge));
+ ctx.fillRect(-padding, -padding, buffer.width + padding * 2, padding * 2);
+ }
+
+ // bottom section
+ if (croppedY2 > 0) {
+ if (panoData.croppedX > 0 || croppedX2 > 0) {
+ ctx.filter = 'none';
+
+ const colorLeft = getAverageColor(ctx, panoData.croppedX, buffer.height - croppedY2 - 1 - edge, edge, edge, 2);
+ const colorRight = getAverageColor(ctx, buffer.width - croppedX2 - 1 - edge, buffer.height - croppedY2 - 1 - edge, edge, edge, 2);
+ const colorCenter = averageRgb(colorLeft, colorRight);
+
+ // bottom-left corner
+ if (panoData.croppedX > 0) {
+ ctx.fillStyle = createHorizontalGradient(ctx, 0, panoData.croppedX, colorCenter, colorLeft);
+ ctx.fillRect(-padding, middleY, panoData.croppedX + padding * 2, buffer.height - middleY + padding);
+ }
+
+ // bottom-right corner
+ if (croppedX2 > 0) {
+ ctx.fillStyle = createHorizontalGradient(ctx, buffer.width - croppedX2, buffer.width, colorRight, colorCenter);
+ ctx.fillRect(buffer.width - croppedX2 - padding, middleY, croppedX2 + padding * 2, buffer.height - middleY + padding);
+ }
+ }
+
+ ctx.filter = filter;
+
+ // bottom
+ ctx.drawImage(
+ img,
+ 0, img.height - edge,
+ img.width, edge,
+ panoData.croppedX, buffer.height - croppedY2 - padding,
+ panoData.croppedWidth, croppedY2 + padding * 2
+ );
+
+ // hide the bottom seam
+ ctx.fillStyle = rgbCss(getAverageColor(ctx, 0, buffer.height - 1 - edge, buffer.width, edge, edge));
+ ctx.fillRect(-padding, buffer.height - padding, buffer.width + padding * 2, padding * 2);
+ }
+
+ // left section
+ if (panoData.croppedX > 0) {
+ ctx.filter = filter;
+
+ ctx.drawImage(
+ img,
+ img.width - edge, 0,
+ edge, img.height,
+ -padding, panoData.croppedY,
+ padding * 2, panoData.croppedHeight
+ );
+
+ ctx.drawImage(
+ img,
+ 0, 0,
+ edge, img.height,
+ 0, panoData.croppedY,
+ panoData.croppedX + padding, panoData.croppedHeight
+ );
+ }
+
+ // right section
+ if (croppedX2 > 0) {
+ ctx.filter = filter;
+
+ ctx.drawImage(
+ img,
+ 0, 0,
+ edge, img.height,
+ buffer.width - padding, panoData.croppedY,
+ padding * 2, panoData.croppedHeight
+ );
+
+ ctx.drawImage(
+ img,
+ img.width - edge, 0,
+ edge, img.height,
+ buffer.width - croppedX2 - padding, panoData.croppedY,
+ croppedX2 + padding, panoData.croppedHeight
+ );
+ }
+
+ ctx.filter = 'none';
+
+ // final draw
+ ctx.drawImage(
+ img,
+ panoData.croppedX,
+ panoData.croppedY,
+ panoData.croppedWidth,
+ panoData.croppedHeight
+ );
+ }
+
+ /**
+ * Returns the CSS string for RGB color
+ */
+ function rgbCss(color: RGB): string {
+ return `rgb(${color.r}, ${color.g}, ${color.b})`;
+ }
+
+ /**
+ * Returns the average of two RGB colors
+ */
+ function averageRgb(c1: RGB, c2: RGB): RGB {
+ return {
+ r: Math.round(c1.r / 2 + c2.r / 2),
+ g: Math.round(c1.g / 2 + c2.g / 2),
+ b: Math.round(c1.b / 2 + c2.b / 2),
+ };
+ }
+
+ /**
+ * Creates a simple horizontal gradient
+ */
+ function createHorizontalGradient(
+ ctx: OffscreenCanvasRenderingContext2D,
+ x1: number,
+ x2: number,
+ c1: RGB,
+ c2: RGB
+ ) {
+ const grad = ctx.createLinearGradient(x1, 0, x2, 0);
+ grad.addColorStop(0, rgbCss(c1));
+ grad.addColorStop(1, rgbCss(c2));
+ return grad;
+ }
+
+ /**
+ * Gets the average RGB color of a portion from a canvas element
+ */
+ function getAverageColor(
+ ctx: OffscreenCanvasRenderingContext2D,
+ x: number,
+ y: number,
+ w: number,
+ h: number,
+ every: number
+ ): RGB {
+ every = Math.round(every);
+
+ let r = 0;
+ let g = 0;
+ let b = 0;
+ let count = 0;
+
+ const data = ctx.getImageData(x, y, w, h);
+
+ for (let row = 0; row < h; row += every) {
+ for (let col = 0; col < w; col += every) {
+ const i = 4 * (row * w + col);
+ r += data.data[i];
+ g += data.data[i + 1];
+ b += data.data[i + 2];
+ count++;
+ }
+ }
+
+ r = Math.round(r / count);
+ g = Math.round(g / count);
+ b = Math.round(b / count);
+
+ return { r, g, b };
+ }
+}
+
+export const interpolationWorkerSrc = URL.createObjectURL(
+ new Blob(['(', interpolationWorker.toString(), ')()'],
+ { type: 'application/javascript' })
+);
diff --git a/packages/core/src/model.ts b/packages/core/src/model.ts
index 18c765654..f23e412a5 100644
--- a/packages/core/src/model.ts
+++ b/packages/core/src/model.ts
@@ -313,12 +313,12 @@ export type ViewerConfig = {
mousewheelCtrlKey?: boolean;
/** @default false */
touchmoveTwoFingers?: boolean;
- /** @deprecated configure on EquirectangularAdapter */
+ /** @deprecated configure `useXmpData` on EquirectangularAdapter */
useXmpData?: boolean;
panoData?: PanoData | PanoDataProvider;
requestHeaders?: Record | ((url: string) => Record);
- /** @deprecated configure on EquirectangularAdapter */
- canvasBackground?: 'auto' | string;
+ /** @deprecated configure `backgroundColor` on EquirectangularAdapter */
+ canvasBackground?: string;
/** @default '{ alpha: true, antialias: true }' */
rendererParameters?: WebGLRendererParameters;
/** @default false */
diff --git a/packages/core/src/utils/canvas.ts b/packages/core/src/utils/canvas.ts
deleted file mode 100644
index 823a8cdd1..000000000
--- a/packages/core/src/utils/canvas.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import { RGB } from 'three';
-import { rgbCss } from './misc';
-
-/**
- * Creates a simple horizontal gradient
- */
-export function createHorizontalGradient(ctx: CanvasRenderingContext2D, x1: number, x2: number, c1: RGB, c2: RGB) {
- const grad = ctx.createLinearGradient(x1, 0, x2, 0);
- grad.addColorStop(0, rgbCss(c1));
- grad.addColorStop(1, rgbCss(c2));
- return grad;
-}
-
-/**
- * Gets the average RGB color of a portion from a canvas element
- */
-export function getAverageColor(
- ctx: CanvasRenderingContext2D,
- x: number,
- y: number,
- w: number,
- h: number,
- every: number
-): RGB {
- every = Math.round(every);
-
- let r = 0;
- let g = 0;
- let b = 0;
- let count = 0;
-
- const data = ctx.getImageData(x, y, w, h);
-
- for (let row = 0; row < h; row += every) {
- for (let col = 0; col < w; col += every) {
- const i = 4 * (row * w + col);
- r += data.data[i];
- g += data.data[i + 1];
- b += data.data[i + 2];
- count++;
- }
- }
-
- r = Math.round(r / count);
- g = Math.round(g / count);
- b = Math.round(b / count);
-
- return { r, g, b };
-}
diff --git a/packages/core/src/utils/index.ts b/packages/core/src/utils/index.ts
index 7d46269fc..9fa960c0a 100644
--- a/packages/core/src/utils/index.ts
+++ b/packages/core/src/utils/index.ts
@@ -1,5 +1,4 @@
export * from './browser';
-export * from './canvas';
export * from './math';
export * from './misc';
export * from './psv';
diff --git a/packages/core/src/utils/misc.ts b/packages/core/src/utils/misc.ts
index 6f21da348..e5680c5f7 100644
--- a/packages/core/src/utils/misc.ts
+++ b/packages/core/src/utils/misc.ts
@@ -1,5 +1,3 @@
-import { RGB } from 'three';
-
/**
* Transforms a string to dash-case
* @link https://github.com/shahata/dasherize
@@ -148,21 +146,3 @@ export function deepEqual(obj1: any, obj2: any): boolean {
function isObject(obj: any): boolean {
return typeof obj === 'object' && obj !== null;
}
-
-/**
- * Returns the CSS string for RGB color
- */
-export function rgbCss(color: RGB): string {
- return `rgb(${color.r}, ${color.g}, ${color.b})`;
-}
-
-/**
- * Returns the average of two RGB colors
- */
-export function averageRgb(c1: RGB, c2: RGB): RGB {
- return {
- r: Math.round(c1.r / 2 + c2.r / 2),
- g: Math.round(c1.g / 2 + c2.g / 2),
- b: Math.round(c1.b / 2 + c2.b / 2),
- };
-}
diff --git a/packages/equirectangular-tiles-adapter/src/EquirectangularTilesAdapter.ts b/packages/equirectangular-tiles-adapter/src/EquirectangularTilesAdapter.ts
index e0bca04d6..3239fd208 100644
--- a/packages/equirectangular-tiles-adapter/src/EquirectangularTilesAdapter.ts
+++ b/packages/equirectangular-tiles-adapter/src/EquirectangularTilesAdapter.ts
@@ -78,13 +78,12 @@ function tileId(tile: EquirectangularTile): string {
const getConfig = utils.getConfigParser(
{
- canvasBackground: '#000',
+ backgroundColor: '#000',
resolution: 64,
showErrorTile: true,
baseBlur: true,
antialias: true,
debug: false,
- blur: false,
useXmpData: false,
},
{
@@ -220,7 +219,8 @@ export class EquirectangularTilesAdapter extends AbstractAdapter<
if (panorama.baseUrl) {
if (!this.adapter) {
this.adapter = new EquirectangularAdapter(this.viewer, {
- canvasBackground: this.config.canvasBackground,
+ backgroundColor: this.config.backgroundColor,
+ interpolateBackground: false,
blur: this.config.baseBlur,
useXmpData: false,
});
@@ -300,9 +300,7 @@ export class EquirectangularTilesAdapter extends AbstractAdapter<
if (texture) {
material = new MeshBasicMaterial({ map: texture });
} else {
- material = new MeshBasicMaterial({
- color: this.config.canvasBackground === 'auto' ? '#000' : this.config.canvasBackground,
- });
+ material = new MeshBasicMaterial({ color: this.config.backgroundColor });
}
for (let i = 0; i < this.NB_GROUPS; i++) {
diff --git a/packages/equirectangular-tiles-adapter/src/model.ts b/packages/equirectangular-tiles-adapter/src/model.ts
index a986e1786..4d9861bc3 100644
--- a/packages/equirectangular-tiles-adapter/src/model.ts
+++ b/packages/equirectangular-tiles-adapter/src/model.ts
@@ -71,7 +71,7 @@ export type EquirectangularMultiTilesPanorama = {
tileUrl: (col: number, row: number, level: number) => string | null;
};
-export type EquirectangularTilesAdapterConfig = EquirectangularAdapterConfig & {
+export type EquirectangularTilesAdapterConfig = Omit & {
/**
* shows a warning sign on tiles that cannot be loaded
* @default true
diff --git a/packages/equirectangular-video-adapter/src/EquirectangularVideoAdapter.ts b/packages/equirectangular-video-adapter/src/EquirectangularVideoAdapter.ts
index 1f52bfe3e..d6e02beb2 100644
--- a/packages/equirectangular-video-adapter/src/EquirectangularVideoAdapter.ts
+++ b/packages/equirectangular-video-adapter/src/EquirectangularVideoAdapter.ts
@@ -12,7 +12,6 @@ const getConfig = utils.getConfigParser(
resolution: 64,
autoplay: false,
muted: false,
- blur: false,
},
{
resolution: (resolution) => {
diff --git a/packages/equirectangular-video-adapter/src/model.ts b/packages/equirectangular-video-adapter/src/model.ts
index a0cdb8bf6..24a24be70 100644
--- a/packages/equirectangular-video-adapter/src/model.ts
+++ b/packages/equirectangular-video-adapter/src/model.ts
@@ -6,4 +6,4 @@ import type { AbstractVideoAdapterConfig, AbstractVideoPanorama } from '../../sh
*/
export type EquirectangularVideoPanorama = AbstractVideoPanorama;
-export type EquirectangularVideoAdapterConfig = Omit & AbstractVideoAdapterConfig;
+export type EquirectangularVideoAdapterConfig = Omit & AbstractVideoAdapterConfig;
diff --git a/packages/shared/package.json b/packages/shared/package.json
index e3820ce60..e200315e4 100644
--- a/packages/shared/package.json
+++ b/packages/shared/package.json
@@ -2,8 +2,8 @@
"name": "@photo-sphere-viewer/shared",
"version": "0.0.0",
"private": true,
- "main": "./src/index.ts",
- "types": "./src/index.ts",
+ "main": "./index.ts",
+ "types": "./index.ts",
"dependencies": {
"@photo-sphere-viewer/core": "0.0.0"
},
diff --git a/packages/shared/tsup.config.js b/packages/shared/tsup.config.js
index 0af0c0f6c..a1aaf53f1 100644
--- a/packages/shared/tsup.config.js
+++ b/packages/shared/tsup.config.js
@@ -1,4 +1,4 @@
import createConfig from '../../build/tsup.config';
import pkg from './package.json' assert { type: 'json' };
-export default createConfig(pkg, 'index.ts');
+export default createConfig(pkg);