tgaimage
Version:
TGA Image Loader for Web browsers
1,799 lines (1,587 loc) • 74.3 kB
JavaScript
var TGAImage =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* WEBPACK VAR INJECTION */(function(Buffer) {
/*global Buffer*/
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var _ImageType = {
noImage: 0,
colorMapped: 1,
RGB: 2,
blackAndWhite: 3,
runlengthColorMapped: 9,
runlengthRGB: 10,
compressedBlackAndWhite: 11,
compressedColorMapped: 32,
compressed4PassQTColorMapped: 33
};
var _headerLength = 18;
var TGAImage = function () {
/**
* constructor
* @param {Buffer|ArrayBuffer} data -
* @constructor
*/
function TGAImage(data) {
var _this = this;
_classCallCheck(this, TGAImage);
if (data instanceof Buffer) {
this._buffer = data;
} else if (typeof data === 'string') {
this._buffer = Buffer.from(data, 'binary');
} else if (data) {
this._buffer = Buffer.from(data);
} else {
this._buffer = null;
}
// Header
this._idLength = 0;
this._colorMapType = 0;
this._imageType = 0;
this._colorMapOrigin = 0;
this._colorMapLength = 0;
this._colorMapDepth = 0;
this._imageXOrigin = 0;
this._imageYOrigin = 0;
this._imageWidth = 0;
this._imageHeight = 0;
this._imageDepth = 0;
this._alphaDepth = 0;
this._leftToRight = true;
this._topToBottom = false;
this._interleave = false;
this._hasAlpha = false;
// Image Identification Field
this._imageID = null;
// Image Data
this._canvas = null;
this._context = null;
this._imageData = null;
this._image = null;
// for HTML Image tag compatibility
this._src = null;
this.onload = null;
this.onerror = null;
this._resolveFunc = null;
this._rejectFunc = null;
this._didLoad = new Promise(function (resolve, reject) {
_this._resolveFunc = resolve;
_this._rejectFunc = reject;
});
if (data) {
this._parseData();
}
}
_createClass(TGAImage, [{
key: '_loadURL',
value: function _loadURL(url) {
var _this2 = this;
this._src = url;
this._requestBinaryFile(url).then(function (data) {
_this2._buffer = Buffer.from(data);
_this2._parseData();
}).catch(function (error) {
_this2._reject(error);
});
}
}, {
key: '_requestBinaryFile',
value: function _requestBinaryFile(url) {
return new Promise(function (resolve, reject) {
var request = new XMLHttpRequest();
request.open('GET', url);
request.responseType = 'arraybuffer';
request.onload = function (ev) {
if (request.response) {
resolve(request.response);
} else {
reject(request);
}
};
request.onerror = function (ev) {
reject(ev);
};
request.send(null);
});
}
}, {
key: '_parseData',
value: function _parseData() {
this._readHeader();
this._readImageID();
this._initImage();
var data = this._getImageData();
switch (this._imageType) {
case _ImageType.noImage:
{
// nothing to do
break;
}
case _ImageType.colorMapped:
{
this._parseColorMapData(data);
break;
}
case _ImageType.RGB:
{
this._parseRGBData(data);
break;
}
case _ImageType.blackAndWhite:
{
this._parseBlackAndWhiteData(data);
break;
}
case _ImageType.runlengthColorMapped:
{
this._parseColorMapData(data);
break;
}
case _ImageType.runlengthRGB:
{
this._parseRGBData(data);
break;
}
case _ImageType.compressedBlackAndWhite:
{
this._parseBlackAndWhiteData(data);
break;
}
case _ImageType.compressedColorMapped:
{
console.error('parser for compressed TGA is not implemeneted');
break;
}
case _ImageType.compressed4PassQTColorMapped:
{
console.error('parser for compressed TGA is not implemeneted');
break;
}
default:
{
throw new Error('unknown imageType: ' + this._imageType);
}
}
this._setImage();
this._deleteBuffer();
}
}, {
key: '_readHeader',
value: function _readHeader() {
this._idLength = this._buffer.readUIntLE(0, 1);
this._colorMapType = this._buffer.readUIntLE(1, 1);
this._imageType = this._buffer.readUIntLE(2, 1);
this._colorMapOrigin = this._buffer.readUIntLE(3, 2);
this._colorMapLength = this._buffer.readUIntLE(5, 2);
this._colorMapDepth = this._buffer.readUIntLE(7, 1);
this._imageXOrigin = this._buffer.readUIntLE(8, 2);
this._imageYOrigin = this._buffer.readUIntLE(10, 2);
this._imageWidth = this._buffer.readUIntLE(12, 2);
this._imageHeight = this._buffer.readUIntLE(14, 2);
this._imageDepth = this._buffer.readUIntLE(16, 1);
var descriptor = this._buffer.readUIntLE(17, 1);
this._alphaDepth = descriptor & 0x0F;
this._leftToRight = (descriptor & 0x10) === 0;
this._topToBottom = (descriptor & 0x20) > 0;
this._interleave = descriptor & 0xC0;
}
}, {
key: '_readImageID',
value: function _readImageID() {
if (this._idLength > 0) {
this._imageID = this._buffer.subarray(_headerLength, this._idLength);
}
}
}, {
key: '_initImage',
value: function _initImage() {
if (this._imageType === _ImageType.noImage) {
return;
}
if (this._imageWidth <= 0 || this._imageHeight <= 0) {
return;
}
this._canvas = document.createElement('canvas');
this._canvas.width = this._imageWidth;
this._canvas.height = this._imageHeight;
this._context = this._canvas.getContext('2d');
this._imageData = this._context.createImageData(this._imageWidth, this._imageHeight);
}
}, {
key: '_setImage',
value: function _setImage() {
var _this3 = this;
this._context.putImageData(this._imageData, 0, 0);
this._image = new Image();
this._image.width = this._imageWidth;
this._image.height = this._imageHeight;
this._image.onload = function () {
_this3._resolve();
};
this._image.src = this._canvas.toDataURL();
}
}, {
key: '_deleteBuffer',
value: function _deleteBuffer() {
if (this._buffer) {
delete this._buffer;
this._buffer = null;
}
if (this._imageData) {
delete this._imageData;
this._imageData = null;
}
}
}, {
key: '_parseColorMapData',
value: function _parseColorMapData(buf) {
if (this._colorMapDepth === 24 || this._colorMapDepth === 16 || this._colorMapDepth === 15) {
this._hasAlpha = false;
} else if (this._colorMapDepth === 32) {
this._hasAlpha = true;
} else {
throw new Error('unknown colorMapDepth: ' + this._colorMapDepth);
}
var colorMapDataPos = _headerLength + this._idLength;
var colorMapDataSize = Math.ceil(this._colorMapDepth / 8);
var colorMapDataLen = colorMapDataSize * this._colorMapLength;
var imageDataSize = 1;
var colorMap = [];
var pos = colorMapDataPos;
for (var i = 0; i < this._colorMapLength; i++) {
var rgba = this._getRGBA(this._buffer, pos, this._colorMapDepth);
colorMap.push(rgba);
pos += colorMapDataSize;
}
var data = this._imageData.data;
var initX = 0;
var initY = 0;
var xStep = 1;
var yStep = 1;
if (!this._leftToRight) {
initX = this._imageWidth - 1;
xStep = -1;
}
if (!this._topToBottom) {
initY = this._imageHeight - 1;
yStep = -1;
}
pos = 0;
var y = initY;
var defaultColor = [0xFF, 0xFF, 0xFF, 0xFF];
for (var iy = 0; iy < this._imageHeight; iy++) {
var x = initX;
for (var ix = 0; ix < this._imageWidth; ix++) {
var index = (y * this._imageWidth + x) * 4;
var color = defaultColor;
var mapNo = buf[pos] - this._colorMapOrigin;
if (mapNo >= 0) {
color = colorMap[mapNo];
}
data[index] = color[0];
data[index + 1] = color[1];
data[index + 2] = color[2];
data[index + 3] = color[3];
x += xStep;
pos += imageDataSize;
}
y += yStep;
}
}
}, {
key: '_parseRGBData',
value: function _parseRGBData(buf) {
if (this._imageDepth === 24 || this._imageDepth === 16 || this._imageDepth === 15) {
this._hasAlpha = false;
} else if (this._imageDepth === 32) {
this._hasAlpha = true;
} else {
throw new Error('unknown imageDepth: ' + this._imageDepth);
}
var imageDataSize = Math.ceil(this._imageDepth / 8);
var data = this._imageData.data;
var initX = 0;
var initY = 0;
var xStep = 1;
var yStep = 1;
if (!this._leftToRight) {
initX = this._imageWidth - 1;
xStep = -1;
}
if (!this._topToBottom) {
initY = this._imageHeight - 1;
yStep = -1;
}
var pos = 0;
var y = initY;
for (var iy = 0; iy < this._imageHeight; iy++) {
var x = initX;
for (var ix = 0; ix < this._imageWidth; ix++) {
var index = (y * this._imageWidth + x) * 4;
var rgba = this._getRGBA(buf, pos, this._imageDepth);
data[index] = rgba[0];
data[index + 1] = rgba[1];
data[index + 2] = rgba[2];
data[index + 3] = rgba[3];
x += xStep;
pos += imageDataSize;
}
y += yStep;
}
}
}, {
key: '_getRGBA',
value: function _getRGBA(buf, offset, depth) {
if (depth === 15) {
var r = (buf[offset + 1] & 0x7c) << 1;
var g = (buf[offset + 1] & 0x03) << 6 | (buf[offset] & 0xe0) >> 2;
var b = (buf[offset] & 0x1f) << 3;
//const a = (buf[offset+1] & 0x80) > 0 ? 255 : 0
var a = 255;
return [r, g, b, a];
} else if (depth === 16) {
var _r = (buf[offset + 1] & 0x7c) << 1;
var _g = (buf[offset + 1] & 0x03) << 6 | (buf[offset] & 0xe0) >> 2;
var _b = (buf[offset] & 0x1f) << 3;
var _a = 255;
return [_r, _g, _b, _a];
} else if (depth === 24) {
return [buf[offset + 2], buf[offset + 1], buf[offset], 255];
} else if (depth === 32) {
return [buf[offset + 2], buf[offset + 1], buf[offset], buf[offset + 3]];
}
throw new Error('unsupported imageDepth: ' + depth);
}
}, {
key: '_parseBlackAndWhiteData',
value: function _parseBlackAndWhiteData(buf) {
if (this._imageDepth == 8) {
this._hasAlpha = false;
} else if (this._imageDepth == 16) {
this._hasAlpha = true;
} else {
throw new Error('unknown imageDepth: ' + this._imageDepth);
}
var imageDataSize = this._imageDepth / 8;
var data = this._imageData.data;
var initX = 0;
var initY = 0;
var xStep = 1;
var yStep = 1;
if (!this._leftToRight) {
initX = this._imageWidth - 1;
xStep = -1;
}
if (!this._topToBottom) {
initY = this._imageHeight - 1;
yStep = -1;
}
var pos = 0;
if (this._hasAlpha) {
var y = initY;
for (var iy = 0; iy < this._imageHeight; iy++) {
var x = initX;
for (var ix = 0; ix < this._imageWidth; ix++) {
var index = (y * this._imageWidth + x) * 4;
var c = buf[pos];
var a = buf[pos + 1];
data[index] = c;
data[index + 1] = c;
data[index + 2] = c;
data[index + 3] = a;
x += xStep;
pos += imageDataSize;
}
y += yStep;
}
} else {
var _y = initY;
for (var _iy = 0; _iy < this._imageHeight; _iy++) {
var _x = initX;
for (var _ix = 0; _ix < this._imageWidth; _ix++) {
var _index = (_y * this._imageWidth + _x) * 4;
var _c = buf[pos];
var _a2 = 255;
data[_index] = _c;
data[_index + 1] = _c;
data[_index + 2] = _c;
data[_index + 3] = _a2;
_x += xStep;
pos += imageDataSize;
}
_y += yStep;
}
}
}
}, {
key: '_getImageData',
value: function _getImageData() {
var data = null;
if (this._imageType !== _ImageType.none) {
var colorMapDataLen = Math.ceil(this._colorMapDepth / 8) * this._colorMapLength;
var start = _headerLength + this._idLength + colorMapDataLen;
data = this._buffer.subarray(start);
}
if (this._imageType === _ImageType.runlengthColorMapped || this._imageType === _ImageType.runlengthRGB) {
data = this._decompressRunlengthData(data);
} else if (this._imageType === _ImageType.compressedBlackAndWhite) {
data = this._decompressRunlengthData(data);
} else if (this._imageType === _ImageType.compressedColorMapped) {
// TODO: implement
console.error('Compressed Color Mapped TGA Image data is not supported');
} else if (this._imageType === _ImageType.compressed4PassQTColorMapped) {
// TODO: implement
console.error('Compressed Color Mapped TGA Image data is not supported');
}
return data;
}
}, {
key: '_decompressRunlengthData',
value: function _decompressRunlengthData(data) {
var d = [];
var elementCount = Math.ceil(this._imageDepth / 8);
var dataLength = elementCount * this._imageWidth * this._imageHeight;
var pos = 0;
while (d.length < dataLength) {
var packet = data[pos];
pos += 1;
if ((packet & 0x80) !== 0) {
// RLE
var elements = data.slice(pos, pos + elementCount);
pos += elementCount;
var count = (packet & 0x7F) + 1;
for (var i = 0; i < count; i++) {
d.push.apply(d, _toConsumableArray(elements));
}
} else {
// RAW
var len = (packet + 1) * elementCount;
d.push.apply(d, _toConsumableArray(data.slice(pos, pos + len)));
pos += len;
}
}
return d;
}
}, {
key: '_resolve',
value: function _resolve(e) {
if (this.onload) {
this.onload(e);
}
this._resolveFunc(e);
}
}, {
key: '_reject',
value: function _reject(e) {
if (this.onerror) {
this.onerror(e);
}
this._rejectFunc(e);
}
}, {
key: 'image',
get: function get() {
return this._image;
}
}, {
key: 'canvas',
get: function get() {
return this._canvas;
}
}, {
key: 'didLoad',
get: function get() {
return this._didLoad;
}
}, {
key: 'src',
get: function get() {
return this._src;
},
set: function set(newValue) {
this._loadURL(newValue);
}
}], [{
key: 'imageWithData',
value: function imageWithData(data) {
return new TGAImage(data);
}
}, {
key: 'imageWithURL',
value: function imageWithURL(url) {
var image = new TGAImage();
image._loadURL(url);
return image;
}
}]);
return TGAImage;
}();
module.exports = TGAImage;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1).Buffer))
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* WEBPACK VAR INJECTION */(function(global) {/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
* @license MIT
*/
/* eslint-disable no-proto */
var base64 = __webpack_require__(3)
var ieee754 = __webpack_require__(4)
var isArray = __webpack_require__(5)
exports.Buffer = Buffer
exports.SlowBuffer = SlowBuffer
exports.INSPECT_MAX_BYTES = 50
/**
* If `Buffer.TYPED_ARRAY_SUPPORT`:
* === true Use Uint8Array implementation (fastest)
* === false Use Object implementation (most compatible, even IE6)
*
* Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
* Opera 11.6+, iOS 4.2+.
*
* Due to various browser bugs, sometimes the Object implementation will be used even
* when the browser supports typed arrays.
*
* Note:
*
* - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
* See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
*
* - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
*
* - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
* incorrect length in some situations.
* We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
* get the Object implementation, which is slower but behaves correctly.
*/
Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
? global.TYPED_ARRAY_SUPPORT
: typedArraySupport()
/*
* Export kMaxLength after typed array support is determined.
*/
exports.kMaxLength = kMaxLength()
function typedArraySupport () {
try {
var arr = new Uint8Array(1)
arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}
return arr.foo() === 42 && // typed array instances can be augmented
typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
} catch (e) {
return false
}
}
function kMaxLength () {
return Buffer.TYPED_ARRAY_SUPPORT
? 0x7fffffff
: 0x3fffffff
}
function createBuffer (that, length) {
if (kMaxLength() < length) {
throw new RangeError('Invalid typed array length')
}
if (Buffer.TYPED_ARRAY_SUPPORT) {
// Return an augmented `Uint8Array` instance, for best performance
that = new Uint8Array(length)
that.__proto__ = Buffer.prototype
} else {
// Fallback: Return an object instance of the Buffer class
if (that === null) {
that = new Buffer(length)
}
that.length = length
}
return that
}
/**
* The Buffer constructor returns instances of `Uint8Array` that have their
* prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
* `Uint8Array`, so the returned instances will have all the node `Buffer` methods
* and the `Uint8Array` methods. Square bracket notation works as expected -- it
* returns a single octet.
*
* The `Uint8Array` prototype remains unmodified.
*/
function Buffer (arg, encodingOrOffset, length) {
if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) {
return new Buffer(arg, encodingOrOffset, length)
}
// Common case.
if (typeof arg === 'number') {
if (typeof encodingOrOffset === 'string') {
throw new Error(
'If encoding is specified then the first argument must be a string'
)
}
return allocUnsafe(this, arg)
}
return from(this, arg, encodingOrOffset, length)
}
Buffer.poolSize = 8192 // not used by this implementation
// TODO: Legacy, not needed anymore. Remove in next major version.
Buffer._augment = function (arr) {
arr.__proto__ = Buffer.prototype
return arr
}
function from (that, value, encodingOrOffset, length) {
if (typeof value === 'number') {
throw new TypeError('"value" argument must not be a number')
}
if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
return fromArrayBuffer(that, value, encodingOrOffset, length)
}
if (typeof value === 'string') {
return fromString(that, value, encodingOrOffset)
}
return fromObject(that, value)
}
/**
* Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
* if value is a number.
* Buffer.from(str[, encoding])
* Buffer.from(array)
* Buffer.from(buffer)
* Buffer.from(arrayBuffer[, byteOffset[, length]])
**/
Buffer.from = function (value, encodingOrOffset, length) {
return from(null, value, encodingOrOffset, length)
}
if (Buffer.TYPED_ARRAY_SUPPORT) {
Buffer.prototype.__proto__ = Uint8Array.prototype
Buffer.__proto__ = Uint8Array
if (typeof Symbol !== 'undefined' && Symbol.species &&
Buffer[Symbol.species] === Buffer) {
// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
Object.defineProperty(Buffer, Symbol.species, {
value: null,
configurable: true
})
}
}
function assertSize (size) {
if (typeof size !== 'number') {
throw new TypeError('"size" argument must be a number')
} else if (size < 0) {
throw new RangeError('"size" argument must not be negative')
}
}
function alloc (that, size, fill, encoding) {
assertSize(size)
if (size <= 0) {
return createBuffer(that, size)
}
if (fill !== undefined) {
// Only pay attention to encoding if it's a string. This
// prevents accidentally sending in a number that would
// be interpretted as a start offset.
return typeof encoding === 'string'
? createBuffer(that, size).fill(fill, encoding)
: createBuffer(that, size).fill(fill)
}
return createBuffer(that, size)
}
/**
* Creates a new filled Buffer instance.
* alloc(size[, fill[, encoding]])
**/
Buffer.alloc = function (size, fill, encoding) {
return alloc(null, size, fill, encoding)
}
function allocUnsafe (that, size) {
assertSize(size)
that = createBuffer(that, size < 0 ? 0 : checked(size) | 0)
if (!Buffer.TYPED_ARRAY_SUPPORT) {
for (var i = 0; i < size; ++i) {
that[i] = 0
}
}
return that
}
/**
* Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
* */
Buffer.allocUnsafe = function (size) {
return allocUnsafe(null, size)
}
/**
* Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
*/
Buffer.allocUnsafeSlow = function (size) {
return allocUnsafe(null, size)
}
function fromString (that, string, encoding) {
if (typeof encoding !== 'string' || encoding === '') {
encoding = 'utf8'
}
if (!Buffer.isEncoding(encoding)) {
throw new TypeError('"encoding" must be a valid string encoding')
}
var length = byteLength(string, encoding) | 0
that = createBuffer(that, length)
var actual = that.write(string, encoding)
if (actual !== length) {
// Writing a hex string, for example, that contains invalid characters will
// cause everything after the first invalid character to be ignored. (e.g.
// 'abxxcd' will be treated as 'ab')
that = that.slice(0, actual)
}
return that
}
function fromArrayLike (that, array) {
var length = array.length < 0 ? 0 : checked(array.length) | 0
that = createBuffer(that, length)
for (var i = 0; i < length; i += 1) {
that[i] = array[i] & 255
}
return that
}
function fromArrayBuffer (that, array, byteOffset, length) {
array.byteLength // this throws if `array` is not a valid ArrayBuffer
if (byteOffset < 0 || array.byteLength < byteOffset) {
throw new RangeError('\'offset\' is out of bounds')
}
if (array.byteLength < byteOffset + (length || 0)) {
throw new RangeError('\'length\' is out of bounds')
}
if (byteOffset === undefined && length === undefined) {
array = new Uint8Array(array)
} else if (length === undefined) {
array = new Uint8Array(array, byteOffset)
} else {
array = new Uint8Array(array, byteOffset, length)
}
if (Buffer.TYPED_ARRAY_SUPPORT) {
// Return an augmented `Uint8Array` instance, for best performance
that = array
that.__proto__ = Buffer.prototype
} else {
// Fallback: Return an object instance of the Buffer class
that = fromArrayLike(that, array)
}
return that
}
function fromObject (that, obj) {
if (Buffer.isBuffer(obj)) {
var len = checked(obj.length) | 0
that = createBuffer(that, len)
if (that.length === 0) {
return that
}
obj.copy(that, 0, 0, len)
return that
}
if (obj) {
if ((typeof ArrayBuffer !== 'undefined' &&
obj.buffer instanceof ArrayBuffer) || 'length' in obj) {
if (typeof obj.length !== 'number' || isnan(obj.length)) {
return createBuffer(that, 0)
}
return fromArrayLike(that, obj)
}
if (obj.type === 'Buffer' && isArray(obj.data)) {
return fromArrayLike(that, obj.data)
}
}
throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')
}
function checked (length) {
// Note: cannot use `length < kMaxLength()` here because that fails when
// length is NaN (which is otherwise coerced to zero.)
if (length >= kMaxLength()) {
throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
'size: 0x' + kMaxLength().toString(16) + ' bytes')
}
return length | 0
}
function SlowBuffer (length) {
if (+length != length) { // eslint-disable-line eqeqeq
length = 0
}
return Buffer.alloc(+length)
}
Buffer.isBuffer = function isBuffer (b) {
return !!(b != null && b._isBuffer)
}
Buffer.compare = function compare (a, b) {
if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
throw new TypeError('Arguments must be Buffers')
}
if (a === b) return 0
var x = a.length
var y = b.length
for (var i = 0, len = Math.min(x, y); i < len; ++i) {
if (a[i] !== b[i]) {
x = a[i]
y = b[i]
break
}
}
if (x < y) return -1
if (y < x) return 1
return 0
}
Buffer.isEncoding = function isEncoding (encoding) {
switch (String(encoding).toLowerCase()) {
case 'hex':
case 'utf8':
case 'utf-8':
case 'ascii':
case 'latin1':
case 'binary':
case 'base64':
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return true
default:
return false
}
}
Buffer.concat = function concat (list, length) {
if (!isArray(list)) {
throw new TypeError('"list" argument must be an Array of Buffers')
}
if (list.length === 0) {
return Buffer.alloc(0)
}
var i
if (length === undefined) {
length = 0
for (i = 0; i < list.length; ++i) {
length += list[i].length
}
}
var buffer = Buffer.allocUnsafe(length)
var pos = 0
for (i = 0; i < list.length; ++i) {
var buf = list[i]
if (!Buffer.isBuffer(buf)) {
throw new TypeError('"list" argument must be an Array of Buffers')
}
buf.copy(buffer, pos)
pos += buf.length
}
return buffer
}
function byteLength (string, encoding) {
if (Buffer.isBuffer(string)) {
return string.length
}
if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' &&
(ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) {
return string.byteLength
}
if (typeof string !== 'string') {
string = '' + string
}
var len = string.length
if (len === 0) return 0
// Use a for loop to avoid recursion
var loweredCase = false
for (;;) {
switch (encoding) {
case 'ascii':
case 'latin1':
case 'binary':
return len
case 'utf8':
case 'utf-8':
case undefined:
return utf8ToBytes(string).length
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return len * 2
case 'hex':
return len >>> 1
case 'base64':
return base64ToBytes(string).length
default:
if (loweredCase) return utf8ToBytes(string).length // assume utf8
encoding = ('' + encoding).toLowerCase()
loweredCase = true
}
}
}
Buffer.byteLength = byteLength
function slowToString (encoding, start, end) {
var loweredCase = false
// No need to verify that "this.length <= MAX_UINT32" since it's a read-only
// property of a typed array.
// This behaves neither like String nor Uint8Array in that we set start/end
// to their upper/lower bounds if the value passed is out of range.
// undefined is handled specially as per ECMA-262 6th Edition,
// Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
if (start === undefined || start < 0) {
start = 0
}
// Return early if start > this.length. Done here to prevent potential uint32
// coercion fail below.
if (start > this.length) {
return ''
}
if (end === undefined || end > this.length) {
end = this.length
}
if (end <= 0) {
return ''
}
// Force coersion to uint32. This will also coerce falsey/NaN values to 0.
end >>>= 0
start >>>= 0
if (end <= start) {
return ''
}
if (!encoding) encoding = 'utf8'
while (true) {
switch (encoding) {
case 'hex':
return hexSlice(this, start, end)
case 'utf8':
case 'utf-8':
return utf8Slice(this, start, end)
case 'ascii':
return asciiSlice(this, start, end)
case 'latin1':
case 'binary':
return latin1Slice(this, start, end)
case 'base64':
return base64Slice(this, start, end)
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return utf16leSlice(this, start, end)
default:
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
encoding = (encoding + '').toLowerCase()
loweredCase = true
}
}
}
// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect
// Buffer instances.
Buffer.prototype._isBuffer = true
function swap (b, n, m) {
var i = b[n]
b[n] = b[m]
b[m] = i
}
Buffer.prototype.swap16 = function swap16 () {
var len = this.length
if (len % 2 !== 0) {
throw new RangeError('Buffer size must be a multiple of 16-bits')
}
for (var i = 0; i < len; i += 2) {
swap(this, i, i + 1)
}
return this
}
Buffer.prototype.swap32 = function swap32 () {
var len = this.length
if (len % 4 !== 0) {
throw new RangeError('Buffer size must be a multiple of 32-bits')
}
for (var i = 0; i < len; i += 4) {
swap(this, i, i + 3)
swap(this, i + 1, i + 2)
}
return this
}
Buffer.prototype.swap64 = function swap64 () {
var len = this.length
if (len % 8 !== 0) {
throw new RangeError('Buffer size must be a multiple of 64-bits')
}
for (var i = 0; i < len; i += 8) {
swap(this, i, i + 7)
swap(this, i + 1, i + 6)
swap(this, i + 2, i + 5)
swap(this, i + 3, i + 4)
}
return this
}
Buffer.prototype.toString = function toString () {
var length = this.length | 0
if (length === 0) return ''
if (arguments.length === 0) return utf8Slice(this, 0, length)
return slowToString.apply(this, arguments)
}
Buffer.prototype.equals = function equals (b) {
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
if (this === b) return true
return Buffer.compare(this, b) === 0
}
Buffer.prototype.inspect = function inspect () {
var str = ''
var max = exports.INSPECT_MAX_BYTES
if (this.length > 0) {
str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
if (this.length > max) str += ' ... '
}
return '<Buffer ' + str + '>'
}
Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {
if (!Buffer.isBuffer(target)) {
throw new TypeError('Argument must be a Buffer')
}
if (start === undefined) {
start = 0
}
if (end === undefined) {
end = target ? target.length : 0
}
if (thisStart === undefined) {
thisStart = 0
}
if (thisEnd === undefined) {
thisEnd = this.length
}
if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
throw new RangeError('out of range index')
}
if (thisStart >= thisEnd && start >= end) {
return 0
}
if (thisStart >= thisEnd) {
return -1
}
if (start >= end) {
return 1
}
start >>>= 0
end >>>= 0
thisStart >>>= 0
thisEnd >>>= 0
if (this === target) return 0
var x = thisEnd - thisStart
var y = end - start
var len = Math.min(x, y)
var thisCopy = this.slice(thisStart, thisEnd)
var targetCopy = target.slice(start, end)
for (var i = 0; i < len; ++i) {
if (thisCopy[i] !== targetCopy[i]) {
x = thisCopy[i]
y = targetCopy[i]
break
}
}
if (x < y) return -1
if (y < x) return 1
return 0
}
// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
// OR the last index of `val` in `buffer` at offset <= `byteOffset`.
//
// Arguments:
// - buffer - a Buffer to search
// - val - a string, Buffer, or number
// - byteOffset - an index into `buffer`; will be clamped to an int32
// - encoding - an optional encoding, relevant is val is a string
// - dir - true for indexOf, false for lastIndexOf
function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
// Empty buffer means no match
if (buffer.length === 0) return -1
// Normalize byteOffset
if (typeof byteOffset === 'string') {
encoding = byteOffset
byteOffset = 0
} else if (byteOffset > 0x7fffffff) {
byteOffset = 0x7fffffff
} else if (byteOffset < -0x80000000) {
byteOffset = -0x80000000
}
byteOffset = +byteOffset // Coerce to Number.
if (isNaN(byteOffset)) {
// byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
byteOffset = dir ? 0 : (buffer.length - 1)
}
// Normalize byteOffset: negative offsets start from the end of the buffer
if (byteOffset < 0) byteOffset = buffer.length + byteOffset
if (byteOffset >= buffer.length) {
if (dir) return -1
else byteOffset = buffer.length - 1
} else if (byteOffset < 0) {
if (dir) byteOffset = 0
else return -1
}
// Normalize val
if (typeof val === 'string') {
val = Buffer.from(val, encoding)
}
// Finally, search either indexOf (if dir is true) or lastIndexOf
if (Buffer.isBuffer(val)) {
// Special case: looking for empty string/buffer always fails
if (val.length === 0) {
return -1
}
return arrayIndexOf(buffer, val, byteOffset, encoding, dir)
} else if (typeof val === 'number') {
val = val & 0xFF // Search for a byte value [0-255]
if (Buffer.TYPED_ARRAY_SUPPORT &&
typeof Uint8Array.prototype.indexOf === 'function') {
if (dir) {
return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)
} else {
return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)
}
}
return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir)
}
throw new TypeError('val must be string, number or Buffer')
}
function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
var indexSize = 1
var arrLength = arr.length
var valLength = val.length
if (encoding !== undefined) {
encoding = String(encoding).toLowerCase()
if (encoding === 'ucs2' || encoding === 'ucs-2' ||
encoding === 'utf16le' || encoding === 'utf-16le') {
if (arr.length < 2 || val.length < 2) {
return -1
}
indexSize = 2
arrLength /= 2
valLength /= 2
byteOffset /= 2
}
}
function read (buf, i) {
if (indexSize === 1) {
return buf[i]
} else {
return buf.readUInt16BE(i * indexSize)
}
}
var i
if (dir) {
var foundIndex = -1
for (i = byteOffset; i < arrLength; i++) {
if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
if (foundIndex === -1) foundIndex = i
if (i - foundIndex + 1 === valLength) return foundIndex * indexSize
} else {
if (foundIndex !== -1) i -= i - foundIndex
foundIndex = -1
}
}
} else {
if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength
for (i = byteOffset; i >= 0; i--) {
var found = true
for (var j = 0; j < valLength; j++) {
if (read(arr, i + j) !== read(val, j)) {
found = false
break
}
}
if (found) return i
}
}
return -1
}
Buffer.prototype.includes = function includes (val, byteOffset, encoding) {
return this.indexOf(val, byteOffset, encoding) !== -1
}
Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {
return bidirectionalIndexOf(this, val, byteOffset, encoding, true)
}
Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {
return bidirectionalIndexOf(this, val, byteOffset, encoding, false)
}
function hexWrite (buf, string, offset, length) {
offset = Number(offset) || 0
var remaining = buf.length - offset
if (!length) {
length = remaining
} else {
length = Number(length)
if (length > remaining) {
length = remaining
}
}
// must be an even number of digits
var strLen = string.length
if (strLen % 2 !== 0) throw new TypeError('Invalid hex string')
if (length > strLen / 2) {
length = strLen / 2
}
for (var i = 0; i < length; ++i) {
var parsed = parseInt(string.substr(i * 2, 2), 16)
if (isNaN(parsed)) return i
buf[offset + i] = parsed
}
return i
}
function utf8Write (buf, string, offset, length) {
return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
}
function asciiWrite (buf, string, offset, length) {
return blitBuffer(asciiToBytes(string), buf, offset, length)
}
function latin1Write (buf, string, offset, length) {
return asciiWrite(buf, string, offset, length)
}
function base64Write (buf, string, offset, length) {
return blitBuffer(base64ToBytes(string), buf, offset, length)
}
function ucs2Write (buf, string, offset, length) {
return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
}
Buffer.prototype.write = function write (string, offset, length, encoding) {
// Buffer#write(string)
if (offset === undefined) {
encoding = 'utf8'
length = this.length
offset = 0
// Buffer#write(string, encoding)
} else if (length === undefined && typeof offset === 'string') {
encoding = offset
length = this.length
offset = 0
// Buffer#write(string, offset[, length][, encoding])
} else if (isFinite(offset)) {
offset = offset | 0
if (isFinite(length)) {
length = length | 0
if (encoding === undefined) encoding = 'utf8'
} else {
encoding = length
length = undefined
}
// legacy write(string, encoding, offset, length) - remove in v0.13
} else {
throw new Error(
'Buffer.write(string, encoding, offset[, length]) is no longer supported'
)
}
var remaining = this.length - offset
if (length === undefined || length > remaining) length = remaining
if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
throw new RangeError('Attempt to write outside buffer bounds')
}
if (!encoding) encoding = 'utf8'
var loweredCase = false
for (;;) {
switch (encoding) {
case 'hex':
return hexWrite(this, string, offset, length)
case 'utf8':
case 'utf-8':
return utf8Write(this, string, offset, length)
case 'ascii':
return asciiWrite(this, string, offset, length)
case 'latin1':
case 'binary':
return latin1Write(this, string, offset, length)
case 'base64':
// Warning: maxLength not taken into account in base64Write
return base64Write(this, string, offset, length)
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return ucs2Write(this, string, offset, length)
default:
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
encoding = ('' + encoding).toLowerCase()
loweredCase = true
}
}
}
Buffer.prototype.toJSON = function toJSON () {
return {
type: 'Buffer',
data: Array.prototype.slice.call(this._arr || this, 0)
}
}
function base64Slice (buf, start, end) {
if (start === 0 && end === buf.length) {
return base64.fromByteArray(buf)
} else {
return base64.fromByteArray(buf.slice(start, end))
}
}
function utf8Slice (buf, start, end) {
end = Math.min(buf.length, end)
var res = []
var i = start
while (i < end) {
var firstByte = buf[i]
var codePoint = null
var bytesPerSequence = (firstByte > 0xEF) ? 4
: (firstByte > 0xDF) ? 3
: (firstByte > 0xBF) ? 2
: 1
if (i + bytesPerSequence <= end) {
var secondByte, thirdByte, fourthByte, tempCodePoint
switch (bytesPerSequence) {
case 1:
if (firstByte < 0x80) {
codePoint = firstByte
}
break
case 2:
secondByte = buf[i + 1]
if ((secondByte & 0xC0) === 0x80) {
tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
if (tempCodePoint > 0x7F) {
codePoint = tempCodePoint
}
}
break
case 3:
secondByte = buf[i + 1]
thirdByte = buf[i + 2]
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
codePoint = tempCodePoint
}
}
break
case 4:
secondByte = buf[i + 1]
thirdByte = buf[i + 2]
fourthByte = buf[i + 3]
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
codePoint = tempCodePoint
}
}
}
}
if (codePoint === null) {
// we did not generate a valid codePoint so insert a
// replacement char (U+FFFD) and advance only 1 byte
codePoint = 0xFFFD
bytesPerSequence = 1
} else if (codePoint > 0xFFFF) {
// encode to utf16 (surrogate pair dance)
codePoint -= 0x10000
res.push(codePoint >>> 10 & 0x3FF | 0xD800)
codePoint = 0xDC00 | codePoint & 0x3FF
}
res.push(codePoint)
i += bytesPerSequence
}
return decodeCodePointsArray(res)
}
// Based on http://stackoverflow.com/a/22747272/680742, the browser with
// the lowest limit is Chrome, with 0x10000 args.
// We go 1 magnitude less, for safety
var MAX_ARGUMENTS_LENGTH = 0x1000
function decodeCodePointsArray (codePoints) {
var len = codePoints.length
if (len <= MAX_ARGUMENTS_LENGTH) {
return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
}
// Decode in chunks to avoid "call stack size exceeded".
var res = ''
var i = 0
while (i < len) {
res += String.fromCharCode.apply(
String,
codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
)
}
return res
}
function asciiSlice (buf, start, end) {
var ret = ''
end = Math.min(buf.length, end)
for (var i = start; i < end; ++i) {
ret += String.fromCharCode(buf[i] & 0x7F)
}
return ret
}
function latin1Slice (buf, start, end) {
var ret = ''
end = Math.min(buf.length, end)
for (var i = start; i < end; ++i) {
ret += String.fromCharCode(buf[i])
}
return ret
}
function hexSlice (buf, start, end) {
var len = buf.length
if (!start || start < 0) start = 0
if (!end || end < 0 || end > len) end = len
var out = ''
for (var i = start; i < end; ++i) {
out += toHex(buf[i])
}
return out
}
function utf16leSlice (buf, start, end) {
var bytes = buf.slice(start, end)
var res = ''
for (var i = 0; i < bytes.length; i += 2) {
res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
}
return res
}
Buffer.prototype.slice = function slice (start, end) {
var len = this.length
start = ~~start
end = end === undefined ? len : ~~end
if (start < 0) {
start += len
if (start < 0) start = 0
} else if (start > len) {
start = len
}
if (end < 0) {
end += len
if (end < 0) end = 0
} else if (end > len) {
end = len
}
if (end < start) end = start
var newBuf
if (Buffer.TYPED_ARRAY_SUPPORT) {
newBuf = this.subarray(start, end)
newBuf.__proto__ = Buffer.prototype
} else {
var sliceLen = end - start
newBuf = new Buffer(sliceLen, undefined)
for (var i = 0; i < sliceLen; ++i) {
newBuf[i] = this[i + start]
}
}
return newBuf
}
/*
* Need to make sure that buffer isn't trying to write out of bounds.
*/
function checkOffset (offset, ext, length) {
if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
}
Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) checkOffset(offset, byteLength, this.length)
var val = this[offset]
var mul = 1
var i = 0
while (++i < byteLength && (mul *= 0x100)) {
val += this[offset + i] * mul
}
return val
}
Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) {
checkOffset(offset, byteLength, this.length)
}
var val = this[offset + --byteLength]
var mul = 1
while (byteLength > 0 && (mul *= 0x100)) {
val += this[offset + --byteLength] * mul
}
return val
}
Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
if (!noAssert) checkOffset(offset, 1, this.length)
return this[offset]
}
Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 2, this.length)
return this[offset] | (this[offset + 1] << 8)
}
Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 2, this.length)
return (this[offset] << 8) | this[offset + 1]
}
Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return ((this[offset]) |
(this[offset + 1] << 8) |
(this[offset + 2] << 16)) +
(this[offset + 3] * 0x1000000)
}
Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return (this[offset] * 0x1000000) +
((this[offset + 1] << 16) |
(this[