2017-03-13 15:28:51 -04:00
|
|
|
'use strict';
|
|
|
|
var Cesium = require('cesium');
|
2017-03-21 14:37:52 -04:00
|
|
|
var fsExtra = require('fs-extra');
|
2017-04-18 11:56:08 -04:00
|
|
|
var jpeg = require('jpeg-js');
|
2015-10-16 17:32:23 -04:00
|
|
|
var path = require('path');
|
2017-03-15 13:05:32 -04:00
|
|
|
var PNG = require('pngjs').PNG;
|
2016-07-22 14:09:13 -04:00
|
|
|
|
2017-04-18 11:56:08 -04:00
|
|
|
var defaultValue = Cesium.defaultValue;
|
2017-03-13 15:28:51 -04:00
|
|
|
|
2016-06-09 13:33:08 -04:00
|
|
|
module.exports = loadImage;
|
2015-10-16 17:32:23 -04:00
|
|
|
|
2017-03-13 15:28:51 -04:00
|
|
|
/**
|
|
|
|
* Load an image file and get information about it.
|
|
|
|
*
|
|
|
|
* @param {String} imagePath Path to the image file.
|
2017-04-10 17:57:56 -04:00
|
|
|
* @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.
|
|
|
|
* @param {Boolean} [options.decode=false] Decode image.
|
2017-03-13 15:28:51 -04:00
|
|
|
* @returns {Promise} A promise resolving to the image information, or undefined if the file doesn't exist.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
*/
|
2017-03-17 16:05:51 -04:00
|
|
|
function loadImage(imagePath, options) {
|
2017-04-18 11:56:08 -04:00
|
|
|
options = defaultValue(options, {});
|
|
|
|
options.checkTransparency = defaultValue(options.checkTransparency, false);
|
|
|
|
options.decode = defaultValue(options.decode, false);
|
|
|
|
|
Update npm dependencies
A few npm dependencies were major versions behind, so this updates `yargs`,
`fs-extra`, and `jasmin-spec-reporter` to their latest versions.
The major change here is `fs-extra`, which now has promise implementations
of all functions by default, this means there's no reason to manually
`Promisify` a function any more, the result is less code overall.
There is one important edge case, `fs-extra` uses built-in native Node
promises, which do not have a `finally` function. If you start a promise
change with an `fs-extra` function, you need to wrap it in `Promise.resolve`
in order to make use of finally at the end (assuming you are using finally
at all, if not you don't need to worry about it. The upside is that your
code will always error if you forget to do this.
2017-05-19 11:37:33 -04:00
|
|
|
return fsExtra.readFile(imagePath)
|
2017-03-13 15:28:51 -04:00
|
|
|
.then(function(data) {
|
2017-04-10 17:57:56 -04:00
|
|
|
var extension = path.extname(imagePath).toLowerCase();
|
2017-03-13 15:28:51 -04:00
|
|
|
|
|
|
|
var info = {
|
|
|
|
transparent : false,
|
2017-03-17 15:44:01 -04:00
|
|
|
source : data,
|
2017-04-18 11:56:08 -04:00
|
|
|
extension : extension,
|
2017-05-03 17:59:24 -04:00
|
|
|
path : imagePath,
|
2017-04-18 11:56:08 -04:00
|
|
|
decoded : undefined,
|
|
|
|
width : undefined,
|
|
|
|
height : undefined
|
2017-03-13 15:28:51 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
if (extension === '.png') {
|
2017-04-10 17:57:56 -04:00
|
|
|
return getPngInfo(data, info, options);
|
2017-04-18 11:56:08 -04:00
|
|
|
} else if (extension === '.jpg' || extension === '.jpeg') {
|
|
|
|
return getJpegInfo(data, info, options);
|
2017-03-13 15:28:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return info;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-04-18 11:56:08 -04:00
|
|
|
function hasTransparency(info) {
|
|
|
|
var pixels = info.decoded;
|
|
|
|
var pixelsLength = info.width * info.height;
|
|
|
|
for (var i = 0; i < pixelsLength; ++i) {
|
|
|
|
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-04-18 11:56:08 -04:00
|
|
|
function getPngInfo(data, info, options) {
|
|
|
|
// Color type is encoded in the 25th bit of the png
|
|
|
|
var colorType = data[25];
|
|
|
|
var channels = getChannels(colorType);
|
|
|
|
|
|
|
|
var checkTransparency = (channels === 4 && options.checkTransparency);
|
|
|
|
var decode = options.decode || checkTransparency;
|
|
|
|
|
|
|
|
if (decode) {
|
|
|
|
var decodedResults = PNG.sync.read(data);
|
|
|
|
info.decoded = decodedResults.data;
|
|
|
|
info.width = decodedResults.width;
|
|
|
|
info.height = decodedResults.height;
|
|
|
|
if (checkTransparency) {
|
|
|
|
info.transparent = hasTransparency(info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getJpegInfo(data, info, options) {
|
|
|
|
if (options.decode) {
|
|
|
|
var decodedResults = jpeg.decode(data);
|
|
|
|
info.decoded = decodedResults.data;
|
|
|
|
info.width = decodedResults.width;
|
|
|
|
info.height = decodedResults.height;
|
2017-03-13 15:28:51 -04:00
|
|
|
}
|
2017-04-18 11:56:08 -04:00
|
|
|
return info;
|
2015-10-16 17:32:23 -04:00
|
|
|
}
|