diff --git a/src/image_processor.js b/src/image_processor.js new file mode 100644 index 00000000..a6fad4dd --- /dev/null +++ b/src/image_processor.js @@ -0,0 +1,80 @@ +import { HDRImage } from '../libs/hdrpng.js'; + +class gltfImageProcessor +{ + processImages(gltf) + { + for (const gltfImage of gltf.images) + { + const image = gltfImage.image; + if (image instanceof HDRImage) + { + continue; + } + + let newDimensions = undefined; + + if (image.width === image.height) + { + newDimensions = this.processSquareImage(image); + } + else + { + newDimensions = this.processNonSquareImage(image); + } + + if (newDimensions.width === image.width && newDimensions.height === image.height) + { + continue; + } + + this.resizeImage(image, newDimensions); + } + } + + processSquareImage(image) + { + const power = this.nearestPowerOf2(image.height); + return { width: power, height: power }; + } + + processNonSquareImage(image) + { + return { width: this.makeEven(image.width), height: this.makeEven(image.height) }; + } + + resizeImage(image, newDimensions) + { + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d'); + canvas.width = newDimensions.width; + canvas.height = newDimensions.height; + context.drawImage(image, 0, 0, canvas.width, canvas.height); + image.src = canvas.toDataURL("image/png"); + } + + nearestPowerOf2(n) + { + if (this.isPowerOf2(n)) + { + return n; + } + return Math.pow(2.0, Math.round(Math.log(n) / Math.log(2.0))); + } + + isPowerOf2(n) + { + return n && (n & (n - 1)) === 0; + } + + makeEven(n) + { + if (n % 2 === 1) + { + return n + 1; + } + return n; + } +} + +export { gltfImageProcessor }; diff --git a/src/viewer.js b/src/viewer.js index 7ad9fc5a..a496e913 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -9,7 +9,8 @@ import { gltfTexture } from './texture.js'; import { gltfUserInterface } from './user_interface.js'; import { UserCamera } from './user_camera.js'; import { jsToGl, getIsGlb, getIsGltf, getFileNameWithoutExtension, Timer } from './utils.js'; -import { GlbParser } from './glbParser'; +import { GlbParser } from './glbParser.js'; +import { gltfImageProcessor } from './image_processor.js'; class gltfViewer { @@ -174,97 +175,14 @@ class gltfViewer let assetPromises = gltfLoader.load(gltf, buffers); - let self = this; + const self = this; + const imageProcessor = new gltfImageProcessor(); Promise.all(assetPromises) - .then(() => self.onResize(gltf)) - .then(() => self.onGltfLoaded(gltf)); - } - - isPowerOf2(n) - { - return n && (n & (n - 1)) === 0; - } - - onResize(gltf) - { - const imagePromises = []; - if (gltf.images !== undefined) - { - let i; - for (i = 0; i < gltf.images.length; i++) - { - if (gltf.images[i].image.dataRGBE !== undefined || - this.isPowerOf2(gltf.images[i].image.width) && (gltf.images[i].image.width === gltf.images[i].image.height)) - { - // Square image and power of two, so no resize needed. - continue; - } - - let doPower = false; - - if (gltf.images[i].image.width == gltf.images[i].image.height) - { - // Square image but not power of two. Resize it to power of two. - doPower = true; - } - else - { - // Rectangle image, so not mip-mapped and ... - - if ((gltf.images[i].image.width % 2 == 0) && (gltf.images[i].image.height % 2 == 0)) - { - // ... with even size, so no resize needed. - continue; - } - - // ... with odd size, so resize needed to make even size. - } - - const currentImagePromise = new Promise(function(resolve) - { - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - - function nearestPowerOf2(n) - { - return Math.pow(2.0, Math.round(Math.log(n) / Math.log(2.0))); - } - - function makeEven(n) - { - if (n % 2 === 1) - { - return n + 1; - } - return n; - } - - if (doPower) - { - canvas.width = nearestPowerOf2(gltf.images[i].image.width); - canvas.height = nearestPowerOf2(gltf.images[i].image.height); - } - else - { - canvas.width = makeEven(gltf.images[i].image.width); - canvas.height = makeEven(gltf.images[i].image.height); - } - - context.drawImage(gltf.images[i].image, 0, 0, canvas.width, canvas.height); - - gltf.images[i].image.src = canvas.toDataURL("image/png"); - - resolve(); - }); - - imagePromises.push(currentImagePromise); - } - } - - return Promise.all(imagePromises); + .then(() => imageProcessor.processImages(gltf)) + .then(() => self.startRendering(gltf)); } - onGltfLoaded(gltf) + startRendering(gltf) { this.notifyLoadingEnded(gltf.path);