2017-03-13 15:28:51 -04:00
|
|
|
'use strict';
|
2019-02-05 20:59:09 -05:00
|
|
|
const Cesium = require('cesium');
|
|
|
|
const fsExtra = require('fs-extra');
|
|
|
|
const jpeg = require('jpeg-js');
|
|
|
|
const path = require('path');
|
|
|
|
const PNG = require('pngjs').PNG;
|
|
|
|
const Promise = require('bluebird');
|
|
|
|
const Texture = require('./Texture');
|
2016-07-22 14:09:13 -04:00
|
|
|
|
2019-02-05 20:59:09 -05:00
|
|
|
const defaultValue = Cesium.defaultValue;
|
|
|
|
const defined = Cesium.defined;
|
2017-03-13 15:28:51 -04:00
|
|
|
|
2017-07-29 13:23:33 -04:00
|
|
|
module.exports = loadTexture;
|
2015-10-16 17:32:23 -04:00
|
|
|
|
2017-03-13 15:28:51 -04:00
|
|
|
/**
|
2017-07-29 13:23:33 -04:00
|
|
|
* Load a texture file.
|
2017-03-13 15:28:51 -04:00
|
|
|
*
|
2017-07-29 13:23:33 -04:00
|
|
|
* @param {String} texturePath Path to the texture file.
|
|
|
|
* @param {Object} [options] An object with the following properties:
|
2017-04-18 11:56:08 -04:00
|
|
|
* @param {Boolean} [options.checkTransparency=false] Do a more exhaustive check for texture transparency by looking at the alpha channel of each pixel.
|
2017-07-29 13:23:33 -04:00
|
|
|
* @param {Boolean} [options.decode=false] Whether to decode the texture.
|
2019-10-26 19:03:32 -04:00
|
|
|
* @param {Boolean} [options.keepSource=false] Whether to keep the source image contents in memory.
|
2017-07-29 13:23:33 -04:00
|
|
|
* @returns {Promise} A promise resolving to a Texture object.
|
2017-03-13 15:28:51 -04:00
|
|
|
*
|
|
|
|
* @private
|
|
|
|
*/
|
2017-07-29 13:23:33 -04:00
|
|
|
function loadTexture(texturePath, options) {
|
2017-04-18 11:56:08 -04:00
|
|
|
options = defaultValue(options, {});
|
|
|
|
options.checkTransparency = defaultValue(options.checkTransparency, false);
|
|
|
|
options.decode = defaultValue(options.decode, false);
|
2019-10-26 19:03:32 -04:00
|
|
|
options.keepSource = defaultValue(options.keepSource, false);
|
2017-04-18 11:56:08 -04:00
|
|
|
|
2017-07-29 13:23:33 -04:00
|
|
|
return fsExtra.readFile(texturePath)
|
|
|
|
.then(function(source) {
|
2019-02-05 20:59:09 -05:00
|
|
|
const name = path.basename(texturePath, path.extname(texturePath));
|
|
|
|
const extension = path.extname(texturePath).toLowerCase();
|
|
|
|
const texture = new Texture();
|
2017-07-29 13:23:33 -04:00
|
|
|
texture.source = source;
|
|
|
|
texture.name = name;
|
|
|
|
texture.extension = extension;
|
|
|
|
texture.path = texturePath;
|
2017-03-13 15:28:51 -04:00
|
|
|
|
2019-02-05 20:59:09 -05:00
|
|
|
let decodePromise;
|
2017-03-13 15:28:51 -04:00
|
|
|
if (extension === '.png') {
|
2017-07-29 13:23:33 -04:00
|
|
|
decodePromise = decodePng(texture, options);
|
2017-04-18 11:56:08 -04:00
|
|
|
} else if (extension === '.jpg' || extension === '.jpeg') {
|
2017-07-29 13:23:33 -04:00
|
|
|
decodePromise = decodeJpeg(texture, options);
|
2017-07-28 16:56:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (defined(decodePromise)) {
|
2019-10-26 19:03:32 -04:00
|
|
|
return decodePromise
|
|
|
|
.then(function() {
|
|
|
|
return texture;
|
|
|
|
});
|
2017-03-13 15:28:51 -04:00
|
|
|
}
|
|
|
|
|
2017-07-29 13:23:33 -04:00
|
|
|
return texture;
|
2017-03-13 15:28:51 -04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-07-29 13:23:33 -04:00
|
|
|
function hasTransparency(pixels) {
|
2019-02-05 20:59:09 -05:00
|
|
|
const pixelsLength = pixels.length / 4;
|
|
|
|
for (let i = 0; i < pixelsLength; ++i) {
|
2017-04-18 11:56:08 -04:00
|
|
|
if (pixels[i * 4 + 3] < 255) {
|
|
|
|
return true;
|
2017-04-10 17:57:56 -04:00
|
|
|
}
|
|
|
|
}
|
2017-04-18 11:56:08 -04:00
|
|
|
return false;
|
2017-03-15 13:05:32 -04:00
|
|
|
}
|
|
|
|
|
2015-10-16 17:32:23 -04:00
|
|
|
function getChannels(colorType) {
|
|
|
|
switch (colorType) {
|
|
|
|
case 0: // greyscale
|
|
|
|
return 1;
|
|
|
|
case 2: // RGB
|
|
|
|
return 3;
|
|
|
|
case 4: // greyscale + alpha
|
|
|
|
return 2;
|
|
|
|
case 6: // RGB + alpha
|
|
|
|
return 4;
|
|
|
|
default:
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-27 11:23:12 -04:00
|
|
|
function parsePng(data) {
|
|
|
|
return new Promise(function(resolve, reject) {
|
|
|
|
new PNG().parse(data, function(error, decodedResults) {
|
|
|
|
if (defined(error)) {
|
|
|
|
reject(error);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
resolve(decodedResults);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-07-29 13:23:33 -04:00
|
|
|
function decodePng(texture, options) {
|
2017-04-18 11:56:08 -04:00
|
|
|
// Color type is encoded in the 25th bit of the png
|
2019-02-05 20:59:09 -05:00
|
|
|
const source = texture.source;
|
|
|
|
const colorType = source[25];
|
|
|
|
const channels = getChannels(colorType);
|
2017-04-18 11:56:08 -04:00
|
|
|
|
2019-02-05 20:59:09 -05:00
|
|
|
const checkTransparency = (channels === 4 && options.checkTransparency);
|
|
|
|
const decode = options.decode || checkTransparency;
|
2017-04-18 11:56:08 -04:00
|
|
|
|
|
|
|
if (decode) {
|
2017-07-28 16:56:28 -04:00
|
|
|
return parsePng(source)
|
2017-07-27 11:23:12 -04:00
|
|
|
.then(function(decodedResults) {
|
2017-07-29 13:23:33 -04:00
|
|
|
if (options.checkTransparency) {
|
|
|
|
texture.transparent = hasTransparency(decodedResults.data);
|
|
|
|
}
|
|
|
|
if (options.decode) {
|
|
|
|
texture.pixels = decodedResults.data;
|
|
|
|
texture.width = decodedResults.width;
|
|
|
|
texture.height = decodedResults.height;
|
2019-10-26 19:03:32 -04:00
|
|
|
if (!options.keepSource) {
|
|
|
|
texture.source = undefined; // Unload resources
|
|
|
|
}
|
2017-07-27 11:23:12 -04:00
|
|
|
}
|
|
|
|
});
|
2017-04-18 11:56:08 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-29 13:23:33 -04:00
|
|
|
function decodeJpeg(texture, options) {
|
2017-04-18 11:56:08 -04:00
|
|
|
if (options.decode) {
|
2019-02-05 20:59:09 -05:00
|
|
|
const source = texture.source;
|
|
|
|
const decodedResults = jpeg.decode(source);
|
2017-07-29 13:23:33 -04:00
|
|
|
texture.pixels = decodedResults.data;
|
|
|
|
texture.width = decodedResults.width;
|
|
|
|
texture.height = decodedResults.height;
|
2019-10-26 19:03:32 -04:00
|
|
|
if (!options.keepSource) {
|
|
|
|
texture.source = undefined; // Unload resources
|
|
|
|
}
|
2017-03-13 15:28:51 -04:00
|
|
|
}
|
2015-10-16 17:32:23 -04:00
|
|
|
}
|