@kitware/vtk.js
Version:
Visualization Toolkit for the Web
157 lines (136 loc) • 5.19 kB
JavaScript
import { m as macro } from '../../macros2.js';
const {
vtkErrorMacro
} = macro;
// ----------------------------------------------------------------------------
const getRemoteFileSize = url =>
// This function only works if the server provides a 'Content-Length'.
// For some reason, the 'Content-Length' header does not appear to be
// given for CORS HEAD requests on firefox. So this will not work on
// firefox if the images do not have the same origin as the html file.
// TODO: figure out how to make this work for CORS requests on firefox.
new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('HEAD', url, true);
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
const size = xhr.getResponseHeader('Content-Length');
resolve(size);
} else {
console.log('Failed to get remote file size of', url);
reject(xhr);
}
}
};
xhr.send();
});
// ----------------------------------------------------------------------------
// vtkTextureLODsDownloader methods
// ----------------------------------------------------------------------------
function vtkTextureLODsDownloader(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkTextureLODsDownloader');
const internal = {
downloadStack: []
};
//--------------------------------------------------------------------------
publicAPI.startDownloads = () => {
if (!model.texture) {
vtkErrorMacro('Texture was not set.');
return;
}
if (!model.files || model.files.length === 0) {
vtkErrorMacro('No files set.');
return;
}
let baseUrl = model.baseUrl;
if (baseUrl && !baseUrl.endsWith('/')) {
baseUrl += '/';
}
// Create the download stack
internal.downloadStack = [];
model.files.forEach(file => internal.downloadStack.push(`${baseUrl}${file}`));
const downloadNextTexture = () => {
if (internal.downloadStack.length === 0) {
return;
}
// For later use
const asyncDownloadNextTexture = () => {
setTimeout(downloadNextTexture, model.waitTimeBetweenDownloads);
};
const img = new Image();
if (model.crossOrigin) {
img.crossOrigin = model.crossOrigin;
}
const url = internal.downloadStack.shift();
getRemoteFileSize(url).then(size => {
if (!size || size / 1024 > model.maxTextureLODSize) {
if (!size) {
console.log('Failed to get image size');
} else {
console.log('Skipping image', url, ', because it is larger', 'than the max texture size:', model.maxTextureLODSize, 'KiB');
}
asyncDownloadNextTexture();
return;
}
img.src = url;
// Decode the image asynchronously in an attempt to prevent a
// freeze during rendering.
// In theory, this should help, but my profiling indicates that
// it does not help much... maybe it is running in the main
// thread anyways?
img.decode().then(() => {
model.texture.setImage(img);
if (model.stepFinishedCallback) {
model.stepFinishedCallback();
}
asyncDownloadNextTexture();
}).catch(encodingError => {
console.log('Failed to decode image:', img.src);
console.log('Error is:', encodingError);
asyncDownloadNextTexture();
});
}).catch(xhr => {
console.log('Failed to get size of:', url);
console.log('status was:', xhr.status);
console.log('statusText was:', xhr.statusText);
asyncDownloadNextTexture();
});
};
setTimeout(downloadNextTexture, model.waitTimeToStart);
};
}
// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------
const DEFAULT_VALUES = {
baseUrl: '',
files: [],
texture: null,
crossOrigin: undefined,
// The max texture LOD file size in KiB
maxTextureLODSize: 50000,
stepFinishedCallback: null,
// These are in milliseconds
waitTimeToStart: 4000,
waitTimeBetweenDownloads: 0
};
// ----------------------------------------------------------------------------
function extend(publicAPI, model) {
let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
Object.assign(model, DEFAULT_VALUES, initialValues);
macro.obj(publicAPI, model);
// Create get-set macros
macro.setGet(publicAPI, model, ['baseUrl', 'files', 'texture', 'crossOrigin', 'maxTextureLODSize', 'stepFinishedCallback', 'waitTimeToStart', 'waitTimeBetweenDownloads']);
// Object specific methods
vtkTextureLODsDownloader(publicAPI, model);
}
// ----------------------------------------------------------------------------
const newInstance = macro.newInstance(extend, 'vtkTextureLODsDownloader');
// ----------------------------------------------------------------------------
var vtkTextureLODsDownloader$1 = {
newInstance,
extend
};
export { vtkTextureLODsDownloader$1 as default, extend, newInstance };