diff --git a/package.json b/package.json index 0563c41..317207d 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "copy-webpack-plugin": "^5.1.1", "focus-visible": "^4.1.5", "framer-motion": "2.0.0-beta.75", + "gif.js": "^0.2.0", "i18next": "^19.4.4", "i18next-browser-languagedetector": "^4.1.1", "i18next-xhr-backend": "^3.2.2", diff --git a/public/api/finishAdminTask.php b/public/api/finishAdminTask.php index 5434d3a..c8ebbe6 100644 --- a/public/api/finishAdminTask.php +++ b/public/api/finishAdminTask.php @@ -2,6 +2,7 @@ require_once "../protected/config.php"; require_once "../protected/db.inc.php"; require_once "../protected/output.inc.php"; +header("Content-type: application/json"); session_start(); // Request can only be GET @@ -18,23 +19,93 @@ if (!isset($_SESSION["u_id"])) { $type = $_POST["type"]; if (!isset($type)) error("Missing argument \"type\".", 401); -header("Content-type: application/json"); +switch ($type) { + case "video-thumbnail": + $file_id = $_POST["id"]; + if (!isset($file_id)) error("Missing argument \"id\".", 401); -if ($type === "video-thumbnail") { - $file_id = $_POST["id"]; - if (!isset($file_id)) error("Missing argument \"id\".", 401); + // Uploaded file size must not exceed 2gb + $file = $_FILES["data"]; + if ($file["size"] > 1.342e+8 || !isset($file["size"])) { + error("Either no file was provided or the size exceeded the predefined limit of the server."); + } - // Uploaded file size must not exceed 2gb - $file = $_FILES["data"]; - if ($file["size"] > 1.342e+8 || !isset($file["size"])) { - error("Either no file was provided or the size exceeded the predefined limit of the server."); - } + generate_thumbnail($GLOBALS["upload_directory"] . $file_id . ".thumb.jpg", $file["tmp_name"], $file["type"]); - generate_thumbnail($GLOBALS["upload_directory"] . $file_id . ".thumb.jpg", $file["tmp_name"], $file["type"]); + $sql = "UPDATE `" . $GLOBALS["table_prefix"] . "file_tasks` SET thumbnail=0 WHERE id=?"; + $db->request($sql, "s", $file_id); + break; - $sql = "UPDATE `" . $GLOBALS["table_prefix"] . "file_tasks` SET thumbnail=0 WHERE id=?"; - $db->request($sql, "s", $file_id); - die(); + case "video-gif-upload": + case "video-gif-stitch": + $file_id = $_POST["id"]; + $chunk_number = $_POST["chunkNum"]; + if (!isset($file_id)) error("Missing argument \"id\".", 401); + if (!isset($chunk_number)) error("Missing argument \"chunkNum\".", 401); + + $temp_dir = "../.temp"; + $chunk_path = $temp_dir . "/" . $file_id . "-"; + mkdir($temp_dir); + + if ($type === "video-gif-upload") { + // Uploaded file size must not exceed 2gb + $file = $_FILES["data"]; + if ($file["size"] > 1.342e+8 || !isset($file["size"])) { + error("Either no file was provided or the size exceeded the predefined limit of the server."); + } + + // Appending $chunk_number to keep chunk order + $chunk_path = $chunk_path . $chunk_number; + + // Check if temporary file exists in order to avoid upload collisions + if (file_exists($chunk_path)) { + error("File already exists; Uploading is not needed.", 423); + } + + if (!move_uploaded_file($file['tmp_name'], $chunk_path)) { + error("File is either too big or no file was sent.", 500); + } + + return; + } + + // Stitching procedure + // We use $chunk_number in this context as the highest chunk number + $stitch_path = $chunk_path . "stitched"; + + if (file_exists($stitch_path)) { + error("Stitched file already exists", 423); + } + + for ($i = 0; $i < $chunk_number; $i++) { + try { + $chunk_i_path = $chunk_path . $i; + $file = fopen($chunk_i_path, 'rb'); + $buff = fread($file, 1024 * 1024); + fclose($file); + + $final = fopen($stitch_path, 'ab'); + $write = fwrite($final, $buff); + fclose($final); + + unlink($chunk_i_path); + } catch (Exception $e) { + error("Error while stitching: " . $e); + } + } + + // Generate optimized gif from upload and delete temporary image + // MySQL update entry happens with the next switch case, since there is no `break` + generate_gif($GLOBALS["upload_directory"] . $file_id . ".gif", $stitch_path); + unlink($stitch_path); + + case "video-gif-too-big": + $file_id = $_POST["id"]; + $sql = "UPDATE `" . $GLOBALS["table_prefix"] . "file_tasks` SET gif=0 WHERE id=?"; + $db->request($sql, "s", $file_id); + break; + + default: + error("Invalid argument value for \"type\"."); + break; } - -error("Invalid argument value for \"type\"."); diff --git a/public/api/getAdminTasks.php b/public/api/getAdminTasks.php index 7747c49..bc6bc14 100644 --- a/public/api/getAdminTasks.php +++ b/public/api/getAdminTasks.php @@ -20,12 +20,28 @@ if (!isset($type)) { error("Missing argument \"type\".", 401); } -if ($type === "video-thumbnail") { - $sql = "SELECT id FROM `" . $GLOBALS["table_prefix"] . "file_tasks` WHERE thumbnail=1"; - $result = mysqli_query($db->con, $sql); - header("Content-type: application/json"); - echo json_encode($result->fetch_all(MYSQLI_ASSOC)); - die(); +// A valid column in the MySQL table +$tableColumn = ""; + +switch ($type) { + case "video-thumbnail": + $tableColumn = "thumbnail"; + break; + + case "video-gif": + $tableColumn = "gif"; + break; + + default: + error("Invalid argument value for \"type\"."); + break; } -error("Invalid argument value for \"type\"."); +// Due to switch, this will only be executed if a valid $reqType was assigned. +$sql = "SELECT id FROM `" . $GLOBALS["table_prefix"] . "file_tasks` WHERE " . $tableColumn . "=1"; +$result = mysqli_query($db->con, $sql); + +if ($result === false) error("Unexpected response from server."); + +header("Content-type: application/json"); +echo json_encode($result->fetch_all(MYSQLI_ASSOC)); diff --git a/public/protected/output.inc.php b/public/protected/output.inc.php index b4906a5..eac4393 100755 --- a/public/protected/output.inc.php +++ b/public/protected/output.inc.php @@ -81,3 +81,30 @@ function generate_thumbnail(string $destination, string $image_path, string $mim // Setting the thumbnail_height according to the newly generated image return exec($GLOBALS["imagick_path"] . " identify -ping -format '%h' " . $destination); } + +/** + * Generates an optimized GIF from an input image. + * @param string $destination Destination path of the thumbnail. + * @param string $image_path A path to the image in question. + * @return string Width and height of the thumbnail; the width is always 200. + */ +function generate_gif(string $destination, string $image_path) +{ + // Using an array to make this part more readable + $exec_array = array( + $GLOBALS["imagick_path"], + "convert", + $image_path, + "-colorspace RGB", + "-ordered-dither o8x8,8,8,4", + "+map", + $destination, + "2>&1", + ); + + // Combining arguments into exec string + exec(implode(" ", $exec_array)); + + // Setting the thumbnail_height according to the newly generated image + return exec($GLOBALS["imagick_path"] . " identify -ping -format '%wx%h' " . $destination); +} diff --git a/public/protected/uploaders/video.inc.php b/public/protected/uploaders/video.inc.php index 6f28277..9c25b18 100755 --- a/public/protected/uploaders/video.inc.php +++ b/public/protected/uploaders/video.inc.php @@ -82,14 +82,16 @@ class VideoPreprocessor /** * Since we cannot access any single frame of a video with * plain PHP, we let the client generate the thumbnails for us. - * * For that, we compile the ids of each video that needs a proper * thumbnail and let the client handle the rest. + * + * We also let the client know that the video is not available in + * GIF form, as it still needs to be generated. */ - private function add_thumbnail_generation_task() + private function add_additional_generation_tasks() { - $sql = "INSERT INTO `" . $GLOBALS["table_prefix"] . "file_tasks` (id, thumbnail) VALUEs (?,?)"; - $GLOBALS["db"]->request($sql, "si", $this->file_id, 1); + $sql = "INSERT INTO `" . $GLOBALS["table_prefix"] . "file_tasks` (id, thumbnail, gif) VALUEs (?,?,?)"; + $GLOBALS["db"]->request($sql, "sii", $this->file_id, 1, 1); } /** @@ -102,7 +104,7 @@ class VideoPreprocessor throw new ErrorException("Generating temporary video thumbnail did not succeed."); } - $this->add_thumbnail_generation_task(); + $this->add_additional_generation_tasks(); return array( "file_width" => $this->file_width, diff --git a/scripts/config-overrides.js b/scripts/config-overrides.js index 02a2b1d..00b015f 100644 --- a/scripts/config-overrides.js +++ b/scripts/config-overrides.js @@ -74,7 +74,7 @@ module.exports = { /** * Force copy everything to build directory - * and include getID3 + * and include getID3 & gif.js */ try { config.plugins.push( @@ -140,6 +140,12 @@ module.exports = { to: "protected/getID3", flatten: true, }, + { + from: "submodules/gif.js/", + to: "static/js", + ignore: ["*.old.*"], + force: true, + }, ]) ); } catch (err) { diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index cb683ba..b42bd1e 100755 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -1,4 +1,5 @@ // We need to declare userData as part of the window object + interface Window { /** * The backend sets a global "userData" object @@ -34,3 +35,4 @@ interface Window { } declare module "react-resize-aware"; +declare module "gif.js"; diff --git a/src/App/App.tsx b/src/App/App.tsx index 1ab692f..b1aef11 100755 --- a/src/App/App.tsx +++ b/src/App/App.tsx @@ -14,6 +14,12 @@ const VideoThumbnailGenerator: LoadableComponent<{}> = loadable(() => ) ); +const VideoGifGenerator: LoadableComponent<{}> = loadable(() => + import( + /* webpackChunkName: "VideoGifGenerator" */ "../_Workers/VideoGifGenerator/VideoGifGenerator" + ) +); + const styles: ComponentStyles = { container: { display: "flex", @@ -34,6 +40,7 @@ const AppContainer: React.ComponentType = ({ managedClasses } {isLoggedIn && } + {/*isLoggedIn && */} ); diff --git a/src/_DesignSystem/Toast/Toast.props.ts b/src/_DesignSystem/Toast/StaticToast/Toast.props.ts similarity index 93% rename from src/_DesignSystem/Toast/Toast.props.ts rename to src/_DesignSystem/Toast/StaticToast/Toast.props.ts index 10dc6c9..ec1bf99 100755 --- a/src/_DesignSystem/Toast/Toast.props.ts +++ b/src/_DesignSystem/Toast/StaticToast/Toast.props.ts @@ -17,4 +17,5 @@ export interface ToastProps extends ManagedClasses, OriginalToastProps { title?: string; + progressPercentage?: number; } diff --git a/src/_DesignSystem/Toast/Toast.tsx b/src/_DesignSystem/Toast/StaticToast/Toast.tsx similarity index 92% rename from src/_DesignSystem/Toast/Toast.tsx rename to src/_DesignSystem/Toast/StaticToast/Toast.tsx index 2152592..7f72b1f 100755 --- a/src/_DesignSystem/Toast/Toast.tsx +++ b/src/_DesignSystem/Toast/StaticToast/Toast.tsx @@ -73,7 +73,12 @@ const BaseToast = (props: ToastProps) => {
{props.title || title()} - {props.children} + + {props.children} +
); diff --git a/src/_DesignSystem/Toast/ToastContainer.props.ts b/src/_DesignSystem/Toast/ToastContainer/ToastContainer.props.ts similarity index 100% rename from src/_DesignSystem/Toast/ToastContainer.props.ts rename to src/_DesignSystem/Toast/ToastContainer/ToastContainer.props.ts diff --git a/src/_DesignSystem/Toast/ToastContainer.tsx b/src/_DesignSystem/Toast/ToastContainer/ToastContainer.tsx similarity index 100% rename from src/_DesignSystem/Toast/ToastContainer.tsx rename to src/_DesignSystem/Toast/ToastContainer/ToastContainer.tsx diff --git a/src/_Workers/VideoGifGenerator/VideoGifGenerator.tsx b/src/_Workers/VideoGifGenerator/VideoGifGenerator.tsx new file mode 100644 index 0000000..f101bc7 --- /dev/null +++ b/src/_Workers/VideoGifGenerator/VideoGifGenerator.tsx @@ -0,0 +1,267 @@ +import React, { useEffect, useCallback, useRef, useState } from "react"; +import { useToasts } from "../../_DesignSystem"; +import gifJS from "gif.js"; +import axios from "../../_interceptedAxios"; +import { Progress } from "@microsoft/fast-components-react-msft"; + +/** + * gif.js can use a faster quantization through WASM + */ +const canWasm = window["WebAssembly"] !== null; + +/** + * Maximal size of a single GIF chunk when uploading + */ +const chunkSize = 1024 * 1024; + +/** + * Framerate of the output GIF + */ +const desiredFramerate = 8; + +/** + * Percentage to compare current percentage to + */ +let lastText = ""; + +/** + * Gif.js instance + */ +const gif = new gifJS({ + workerScript: + window.location.origin + + "/static/js/" + + (canWasm ? "gif.worker-wasm.js" : "gif.worker.js"), + workers: 4, + quality: 8, + // globalPalette: true, + width: 0, + height: 0, + // dither: "Atkinson", + // dither: false, + repeat: 0, +}); + +const VideoGifGenerator: React.ComponentType<{}> = props => { + const { addToast, updateToast, removeToast } = useToasts(); + + /** + * An array containing video IDs that need GIF equivalents. + */ + const taskList = useRef<{ id: string }[]>([]); + + /** + * Current progress with the conversion of a video + */ + type progressPercentage = number; + const [progressPercentage, setProgress] = useState(null); + + /** + * ID of the toast that is used to display the progress + * of generating and uploading a GIF + */ + type toastId = string; + const [toastId, setToastId] = useState(null); + const [curFileId, setCurFileId] = useState(null); + + /** + * Generates a gif from an already uploaded video via gif.js + * @param fileID Already existing id for a video file. + */ + const generateGif = useCallback((fileID: string[8]) => { + if (taskList.current.length <= 0) return; + setCurFileId(fileID); + + const videoEl = document.createElement("video"); + videoEl.style.display = "none"; + videoEl.preload = "metadata"; + videoEl.autoplay = false; + + /** + * Seeks video to given time, adds the frame to gif.js and progresses to + * the next GIF frame by calling itself again. + * + * @param time Video time to seek to in seconds + * @param seekSummand Number in seconds by which `time` should progress after successful seeking + */ + const seekVideo = (time: number, seekSummand: number) => { + const seekHandler = () => { + console.log("Loaded Data at " + videoEl.currentTime + "!"); + videoEl.removeEventListener("seeked", seekHandler); + + // Setting progress for toast + setProgress((videoEl.currentTime * 33) / videoEl.duration); + + // Start GIF rendering if there is no frame to add anymore + if (videoEl.currentTime >= videoEl.duration) { + console.log("Finished at " + videoEl.currentTime + ", now rendering!"); + gif.render(); + document.body.removeChild(videoEl); + return; + } + + gif.addFrame(videoEl, { copy: true, delay: seekSummand * 1000 }); + seekVideo(time + seekSummand, seekSummand); + }; + + videoEl.addEventListener("seeked", seekHandler); + videoEl.currentTime = time; + }; + + videoEl.addEventListener("loadedmetadata", () => { + console.log("Loaded Metadata!", videoEl.duration); + const seekSummand = 1 / desiredFramerate; + + gif.abort(); + gif.frames = []; + gif.setOptions({ + width: videoEl.videoWidth, + height: videoEl.videoHeight, + }); + + seekVideo(0, seekSummand); + }); + + // NOTE: MP4 is hardcoded! + videoEl.src = `${window.location.origin}/${fileID}.mp4`; + document.body.appendChild(videoEl); + }, []); + + /** + * Removes first object from the task list and + * requests a GIF generation for the next item in the list. + */ + const shiftToNextGif = useCallback(() => { + taskList.current.shift(); + if (taskList.current.length <= 0) return; + generateGif(taskList.current[0].id); + }, [generateGif]); + + /** + * Starts uploading procedure. + * + * The GIF is split into small chunks and uploaded into a + * temporary folder. Finally, a stitching request will tell + * the server to combine the chunks and create an optimized + * version of the full GIF. + */ + const uploadGif = useCallback( + (gifBlob: Blob) => { + const uploadGifChunk = async (chunkNum: number) => { + const curID = taskList.current[0].id; + const postData = new FormData(); + + const offset = chunkNum * chunkSize; + const blobChunk = gifBlob.slice(offset, offset + chunkSize); + + /** + * After uploading all chunks, we need to tell the server + * to start stitching them together. + */ + const isStitchRequest = blobChunk.size === 0; + + postData.append( + "type", + !isStitchRequest ? "video-gif-upload" : "video-gif-stitch" + ); + postData.append("id", curID); + postData.append("chunkNum", chunkNum.toString()); + postData.append("data", !isStitchRequest ? blobChunk : null); + + try { + await axios.post(window.location.origin + "/api/finishAdminTask.php", postData); + + if (!isStitchRequest) uploadGifChunk(chunkNum + 1); + else shiftToNextGif(); + } catch (err) { + // Skip current GIF if another client is already uploading + if (typeof err.code !== "undefined" && err.code === 423) { + shiftToNextGif(); + return; + } + + addToast("error.gifUpload", { appearance: "error" }); + console.log("error.gifUpload", "\n", err.message, err, typeof err); + } + }; + + uploadGifChunk(0); + }, + [addToast, shiftToNextGif] + ); + + useEffect(() => { + (async () => { + try { + const res = await axios.get(window.location.origin + "/api/getAdminTasks.php", { + params: { type: "video-gif" }, + }); + + if (res.data) { + taskList.current = res.data; + generateGif(taskList.current[0].id); + } + } catch (err) { + addToast("error.requestTaskList", { appearance: "error" }); + console.log("error.requestTaskList", "\n", err.message); + } + })(); + return () => {}; + }, [addToast, generateGif]); + + useEffect(() => { + const gifFinishHandler = uploadGif; + const handleGifProgress = (progress: number) => { + setProgress((progress * 100 * 33) / 100 + 33); + }; + + gif.addListener("finished", gifFinishHandler); + gif.addListener("progress", handleGifProgress); + return () => { + gif.removeListener("finished", gifFinishHandler); + gif.removeListener("progress", handleGifProgress); + }; + }, [uploadGif]); + + useEffect(() => { + let toastId: string = null; + addToast( + , + { + title: `Spinning up GIF generator...`, + appearance: "info", + autoDismiss: false, + }, + (id: string) => { + setToastId(id); + toastId = id; + } + ); + + return () => { + if (toastId) removeToast(toastId); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [removeToast, addToast]); + + useEffect(() => { + if (!toastId || !curFileId) return; + + let title = ""; + if (progressPercentage < 33) + title = `Preparing ${curFileId}.mp4 to convert to GIF...`; + if (progressPercentage >= 33) title = `Generating ${curFileId}.gif...`; + if (progressPercentage >= 66) title = `Uploading ${curFileId}.gif...`; + + if (title !== lastText) { + lastText = title; + updateToast(toastId, { title } as any); + } + + console.log(`${title} - ${progressPercentage}%`); + }, [curFileId, progressPercentage, toastId, updateToast]); + + return null; +}; + +export default VideoGifGenerator; diff --git a/src/index.tsx b/src/index.tsx index fc20b04..341d965 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -5,14 +5,18 @@ import "./index.scss"; import "./i18n"; import PogodaDesignToolkitProvider from "./_DesignSystem/Toolkit/DesignSystem"; import { ToastProvider } from "react-toast-notifications"; -import loadable from "@loadable/component"; +import Toast from "./_DesignSystem/Toast/StaticToast/Toast"; +import ToastContainer from "./_DesignSystem/Toast/ToastContainer/ToastContainer"; +// import loadable from "@loadable/component"; -const Toast = loadable(() => - import(/* webpackChunkName: "Toast" */ "./_DesignSystem/Toast/Toast") -); -const ToastContainer = loadable(() => - import(/* webpackChunkName: "Toast" */ "./_DesignSystem/Toast/ToastContainer") -); +//const Toast = loadable(() => +// import(/* webpackChunkName: "Toast" */ "./_DesignSystem/Toast/StaticToast/Toast") +//); +//const ToastContainer = loadable(() => +// import( +// /* webpackChunkName: "Toast" */ "./_DesignSystem/Toast/ToastContainer/ToastContainer" +// ) +//);*/ ReactDOM.render( diff --git a/submodules/gif.js/gif.worker-wasm.js b/submodules/gif.js/gif.worker-wasm.js new file mode 100644 index 0000000..aa3af7d --- /dev/null +++ b/submodules/gif.js/gif.worker-wasm.js @@ -0,0 +1,5 @@ +// gif.worker.js 0.2.0-wasm - https://github.com/jnordberg/gif.js +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o0){throw new Error("Invalid string. Length must be a multiple of 4")}return b64[len-2]==="="?2:b64[len-1]==="="?1:0}function byteLength(b64){return b64.length*3/4-placeHoldersCount(b64)}function toByteArray(b64){var i,j,l,tmp,placeHolders,arr;var len=b64.length;placeHolders=placeHoldersCount(b64);arr=new Arr(len*3/4-placeHolders);l=placeHolders>0?len-4:len;var L=0;for(i=0,j=0;i>16&255;arr[L++]=tmp>>8&255;arr[L++]=tmp&255}if(placeHolders===2){tmp=revLookup[b64.charCodeAt(i)]<<2|revLookup[b64.charCodeAt(i+1)]>>4;arr[L++]=tmp&255}else if(placeHolders===1){tmp=revLookup[b64.charCodeAt(i)]<<10|revLookup[b64.charCodeAt(i+1)]<<4|revLookup[b64.charCodeAt(i+2)]>>2;arr[L++]=tmp>>8&255;arr[L++]=tmp&255}return arr}function tripletToBase64(num){return lookup[num>>18&63]+lookup[num>>12&63]+lookup[num>>6&63]+lookup[num&63]}function encodeChunk(uint8,start,end){var tmp;var output=[];for(var i=start;ilen2?len2:i+maxChunkLength))}if(extraBytes===1){tmp=uint8[len-1];output+=lookup[tmp>>2];output+=lookup[tmp<<4&63];output+="=="}else if(extraBytes===2){tmp=(uint8[len-2]<<8)+uint8[len-1];output+=lookup[tmp>>10];output+=lookup[tmp>>4&63];output+=lookup[tmp<<2&63];output+="="}parts.push(output);return parts.join("")}},{}],2:[function(require,module,exports){"use strict";var base64=require("base64-js");var ieee754=require("ieee754");exports.Buffer=Buffer;exports.SlowBuffer=SlowBuffer;exports.INSPECT_MAX_BYTES=50;var K_MAX_LENGTH=2147483647;exports.kMaxLength=K_MAX_LENGTH;Buffer.TYPED_ARRAY_SUPPORT=typedArraySupport();if(!Buffer.TYPED_ARRAY_SUPPORT&&typeof console!=="undefined"&&typeof console.error==="function"){console.error("This browser lacks typed array (Uint8Array) support which is required by "+"`buffer` v5.x. Use `buffer` v4.x if you require old browser support.")}function typedArraySupport(){try{var arr=new Uint8Array(1);arr.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}};return arr.foo()===42}catch(e){return false}}function createBuffer(length){if(length>K_MAX_LENGTH){throw new RangeError("Invalid typed array length")}var buf=new Uint8Array(length);buf.__proto__=Buffer.prototype;return buf}function Buffer(arg,encodingOrOffset,length){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(arg)}return from(arg,encodingOrOffset,length)}if(typeof Symbol!=="undefined"&&Symbol.species&&Buffer[Symbol.species]===Buffer){Object.defineProperty(Buffer,Symbol.species,{value:null,configurable:true,enumerable:false,writable:false})}Buffer.poolSize=8192;function from(value,encodingOrOffset,length){if(typeof value==="number"){throw new TypeError('"value" argument must not be a number')}if(value instanceof ArrayBuffer){return fromArrayBuffer(value,encodingOrOffset,length)}if(typeof value==="string"){return fromString(value,encodingOrOffset)}return fromObject(value)}Buffer.from=function(value,encodingOrOffset,length){return from(value,encodingOrOffset,length)};Buffer.prototype.__proto__=Uint8Array.prototype;Buffer.__proto__=Uint8Array;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(size,fill,encoding){assertSize(size);if(size<=0){return createBuffer(size)}if(fill!==undefined){return typeof encoding==="string"?createBuffer(size).fill(fill,encoding):createBuffer(size).fill(fill)}return createBuffer(size)}Buffer.alloc=function(size,fill,encoding){return alloc(size,fill,encoding)};function allocUnsafe(size){assertSize(size);return createBuffer(size<0?0:checked(size)|0)}Buffer.allocUnsafe=function(size){return allocUnsafe(size)};Buffer.allocUnsafeSlow=function(size){return allocUnsafe(size)};function fromString(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;var buf=createBuffer(length);var actual=buf.write(string,encoding);if(actual!==length){buf=buf.slice(0,actual)}return buf}function fromArrayLike(array){var length=array.length<0?0:checked(array.length)|0;var buf=createBuffer(length);for(var i=0;i=K_MAX_LENGTH){throw new RangeError("Attempt to allocate Buffer larger than maximum "+"size: 0x"+K_MAX_LENGTH.toString(16)+" bytes")}return length|0}function SlowBuffer(length){if(+length!=length){length=0}return Buffer.alloc(+length)}Buffer.isBuffer=function isBuffer(b){return b!=null&&b._isBuffer===true};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>>1;case"base64":return base64ToBytes(string).length;default:if(loweredCase)return utf8ToBytes(string).length;encoding=(""+encoding).toLowerCase();loweredCase=true}}}Buffer.byteLength=byteLength;function slowToString(encoding,start,end){var loweredCase=false;if(start===undefined||start<0){start=0}if(start>this.length){return""}if(end===undefined||end>this.length){end=this.length}if(end<=0){return""}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}}}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;i0){str=this.toString("hex",0,max).match(/.{2}/g).join(" ");if(this.length>max)str+=" ... "}return""};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;i2147483647){byteOffset=2147483647}else if(byteOffset<-2147483648){byteOffset=-2147483648}byteOffset=+byteOffset;if(numberIsNaN(byteOffset)){byteOffset=dir?0:buffer.length-1}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}if(typeof val==="string"){val=Buffer.from(val,encoding)}if(Buffer.isBuffer(val)){if(val.length===0){return-1}return arrayIndexOf(buffer,val,byteOffset,encoding,dir)}else if(typeof val==="number"){val=val&255;if(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;iarrLength)byteOffset=arrLength-valLength;for(i=byteOffset;i>=0;i--){var found=true;for(var j=0;jremaining){length=remaining}}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>>0;if(isFinite(length)){length=length>>>0;if(encoding===undefined)encoding="utf8"}else{encoding=length;length=undefined}}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":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(i239?4:firstByte>223?3:firstByte>191?2:1;if(i+bytesPerSequence<=end){var secondByte,thirdByte,fourthByte,tempCodePoint;switch(bytesPerSequence){case 1:if(firstByte<128){codePoint=firstByte}break;case 2:secondByte=buf[i+1];if((secondByte&192)===128){tempCodePoint=(firstByte&31)<<6|secondByte&63;if(tempCodePoint>127){codePoint=tempCodePoint}}break;case 3:secondByte=buf[i+1];thirdByte=buf[i+2];if((secondByte&192)===128&&(thirdByte&192)===128){tempCodePoint=(firstByte&15)<<12|(secondByte&63)<<6|thirdByte&63;if(tempCodePoint>2047&&(tempCodePoint<55296||tempCodePoint>57343)){codePoint=tempCodePoint}}break;case 4:secondByte=buf[i+1];thirdByte=buf[i+2];fourthByte=buf[i+3];if((secondByte&192)===128&&(thirdByte&192)===128&&(fourthByte&192)===128){tempCodePoint=(firstByte&15)<<18|(secondByte&63)<<12|(thirdByte&63)<<6|fourthByte&63;if(tempCodePoint>65535&&tempCodePoint<1114112){codePoint=tempCodePoint}}}}if(codePoint===null){codePoint=65533;bytesPerSequence=1}else if(codePoint>65535){codePoint-=65536;res.push(codePoint>>>10&1023|55296);codePoint=56320|codePoint&1023}res.push(codePoint);i+=bytesPerSequence}return decodeCodePointsArray(res)}var MAX_ARGUMENTS_LENGTH=4096;function decodeCodePointsArray(codePoints){var len=codePoints.length;if(len<=MAX_ARGUMENTS_LENGTH){return String.fromCharCode.apply(String,codePoints)}var res="";var i=0;while(ilen)end=len;var out="";for(var i=start;ilen){start=len}if(end<0){end+=len;if(end<0)end=0}else if(end>len){end=len}if(endlength)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>>0;byteLength=byteLength>>>0;if(!noAssert){checkOffset(offset,byteLength,this.length)}var val=this[offset+--byteLength];var mul=1;while(byteLength>0&&(mul*=256)){val+=this[offset+--byteLength]*mul}return val};Buffer.prototype.readUInt8=function readUInt8(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,1,this.length);return this[offset]};Buffer.prototype.readUInt16LE=function readUInt16LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);return this[offset]|this[offset+1]<<8};Buffer.prototype.readUInt16BE=function readUInt16BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);return this[offset]<<8|this[offset+1]};Buffer.prototype.readUInt32LE=function readUInt32LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return(this[offset]|this[offset+1]<<8|this[offset+2]<<16)+this[offset+3]*16777216};Buffer.prototype.readUInt32BE=function readUInt32BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return this[offset]*16777216+(this[offset+1]<<16|this[offset+2]<<8|this[offset+3])};Buffer.prototype.readIntLE=function readIntLE(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=mul)val-=Math.pow(2,8*byteLength);return val};Buffer.prototype.readIntBE=function readIntBE(offset,byteLength,noAssert){offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert)checkOffset(offset,byteLength,this.length);var i=byteLength;var mul=1;var val=this[offset+--i];while(i>0&&(mul*=256)){val+=this[offset+--i]*mul}mul*=128;if(val>=mul)val-=Math.pow(2,8*byteLength);return val};Buffer.prototype.readInt8=function readInt8(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,1,this.length);if(!(this[offset]&128))return this[offset];return(255-this[offset]+1)*-1};Buffer.prototype.readInt16LE=function readInt16LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);var val=this[offset]|this[offset+1]<<8;return val&32768?val|4294901760:val};Buffer.prototype.readInt16BE=function readInt16BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);var val=this[offset+1]|this[offset]<<8;return val&32768?val|4294901760:val};Buffer.prototype.readInt32LE=function readInt32LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return this[offset]|this[offset+1]<<8|this[offset+2]<<16|this[offset+3]<<24};Buffer.prototype.readInt32BE=function readInt32BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return this[offset]<<24|this[offset+1]<<16|this[offset+2]<<8|this[offset+3]};Buffer.prototype.readFloatLE=function readFloatLE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return ieee754.read(this,offset,true,23,4)};Buffer.prototype.readFloatBE=function readFloatBE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return ieee754.read(this,offset,false,23,4)};Buffer.prototype.readDoubleLE=function readDoubleLE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,8,this.length);return ieee754.read(this,offset,true,52,8)};Buffer.prototype.readDoubleBE=function readDoubleBE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,8,this.length);return ieee754.read(this,offset,false,52,8)};function checkInt(buf,value,offset,ext,max,min){if(!Buffer.isBuffer(buf))throw new TypeError('"buffer" argument must be a Buffer instance');if(value>max||valuebuf.length)throw new RangeError("Index out of range")}Buffer.prototype.writeUIntLE=function writeUIntLE(value,offset,byteLength,noAssert){value=+value;offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert){var maxBytes=Math.pow(2,8*byteLength)-1;checkInt(this,value,offset,byteLength,maxBytes,0)}var mul=1;var i=0;this[offset]=value&255;while(++i>>0;byteLength=byteLength>>>0;if(!noAssert){var maxBytes=Math.pow(2,8*byteLength)-1;checkInt(this,value,offset,byteLength,maxBytes,0)}var i=byteLength-1;var mul=1;this[offset+i]=value&255;while(--i>=0&&(mul*=256)){this[offset+i]=value/mul&255}return offset+byteLength};Buffer.prototype.writeUInt8=function writeUInt8(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,1,255,0);this[offset]=value&255;return offset+1};Buffer.prototype.writeUInt16LE=function writeUInt16LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,65535,0);this[offset]=value&255;this[offset+1]=value>>>8;return offset+2};Buffer.prototype.writeUInt16BE=function writeUInt16BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,65535,0);this[offset]=value>>>8;this[offset+1]=value&255;return offset+2};Buffer.prototype.writeUInt32LE=function writeUInt32LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,4294967295,0);this[offset+3]=value>>>24;this[offset+2]=value>>>16;this[offset+1]=value>>>8;this[offset]=value&255;return offset+4};Buffer.prototype.writeUInt32BE=function writeUInt32BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,4294967295,0);this[offset]=value>>>24;this[offset+1]=value>>>16;this[offset+2]=value>>>8;this[offset+3]=value&255;return offset+4};Buffer.prototype.writeIntLE=function writeIntLE(value,offset,byteLength,noAssert){value=+value;offset=offset>>>0;if(!noAssert){var limit=Math.pow(2,8*byteLength-1);checkInt(this,value,offset,byteLength,limit-1,-limit)}var i=0;var mul=1;var sub=0;this[offset]=value&255;while(++i>0)-sub&255}return offset+byteLength};Buffer.prototype.writeIntBE=function writeIntBE(value,offset,byteLength,noAssert){value=+value;offset=offset>>>0;if(!noAssert){var limit=Math.pow(2,8*byteLength-1);checkInt(this,value,offset,byteLength,limit-1,-limit)}var i=byteLength-1;var mul=1;var sub=0;this[offset+i]=value&255;while(--i>=0&&(mul*=256)){if(value<0&&sub===0&&this[offset+i+1]!==0){sub=1}this[offset+i]=(value/mul>>0)-sub&255}return offset+byteLength};Buffer.prototype.writeInt8=function writeInt8(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,1,127,-128);if(value<0)value=255+value+1;this[offset]=value&255;return offset+1};Buffer.prototype.writeInt16LE=function writeInt16LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,32767,-32768);this[offset]=value&255;this[offset+1]=value>>>8;return offset+2};Buffer.prototype.writeInt16BE=function writeInt16BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,32767,-32768);this[offset]=value>>>8;this[offset+1]=value&255;return offset+2};Buffer.prototype.writeInt32LE=function writeInt32LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,2147483647,-2147483648);this[offset]=value&255;this[offset+1]=value>>>8;this[offset+2]=value>>>16;this[offset+3]=value>>>24;return offset+4};Buffer.prototype.writeInt32BE=function writeInt32BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,2147483647,-2147483648);if(value<0)value=4294967295+value+1;this[offset]=value>>>24;this[offset+1]=value>>>16;this[offset+2]=value>>>8;this[offset+3]=value&255;return offset+4};function checkIEEE754(buf,value,offset,ext,max,min){if(offset+ext>buf.length)throw new RangeError("Index out of range");if(offset<0)throw new RangeError("Index out of range")}function writeFloat(buf,value,offset,littleEndian,noAssert){value=+value;offset=offset>>>0;if(!noAssert){checkIEEE754(buf,value,offset,4,3.4028234663852886e38,-3.4028234663852886e38)}ieee754.write(buf,value,offset,littleEndian,23,4);return offset+4}Buffer.prototype.writeFloatLE=function writeFloatLE(value,offset,noAssert){return writeFloat(this,value,offset,true,noAssert)};Buffer.prototype.writeFloatBE=function writeFloatBE(value,offset,noAssert){return writeFloat(this,value,offset,false,noAssert)};function writeDouble(buf,value,offset,littleEndian,noAssert){value=+value;offset=offset>>>0;if(!noAssert){checkIEEE754(buf,value,offset,8,1.7976931348623157e308,-1.7976931348623157e308)}ieee754.write(buf,value,offset,littleEndian,52,8);return offset+8}Buffer.prototype.writeDoubleLE=function writeDoubleLE(value,offset,noAssert){return writeDouble(this,value,offset,true,noAssert)};Buffer.prototype.writeDoubleBE=function writeDoubleBE(value,offset,noAssert){return writeDouble(this,value,offset,false,noAssert)};Buffer.prototype.copy=function copy(target,targetStart,start,end){if(!start)start=0;if(!end&&end!==0)end=this.length;if(targetStart>=target.length)targetStart=target.length;if(!targetStart)targetStart=0;if(end>0&&end=this.length)throw new RangeError("sourceStart out of bounds");if(end<0)throw new RangeError("sourceEnd out of bounds");if(end>this.length)end=this.length;if(target.length-targetStart=0;--i){target[i+targetStart]=this[i+start]}}else if(len<1e3){for(i=0;i>>0;end=end===undefined?this.length:end>>>0;if(!val)val=0;var i;if(typeof val==="number"){for(i=start;i55295&&codePoint<57344){if(!leadSurrogate){if(codePoint>56319){if((units-=3)>-1)bytes.push(239,191,189);continue}else if(i+1===length){if((units-=3)>-1)bytes.push(239,191,189);continue}leadSurrogate=codePoint;continue}if(codePoint<56320){if((units-=3)>-1)bytes.push(239,191,189);leadSurrogate=codePoint;continue}codePoint=(leadSurrogate-55296<<10|codePoint-56320)+65536}else if(leadSurrogate){if((units-=3)>-1)bytes.push(239,191,189)}leadSurrogate=null +;if(codePoint<128){if((units-=1)<0)break;bytes.push(codePoint)}else if(codePoint<2048){if((units-=2)<0)break;bytes.push(codePoint>>6|192,codePoint&63|128)}else if(codePoint<65536){if((units-=3)<0)break;bytes.push(codePoint>>12|224,codePoint>>6&63|128,codePoint&63|128)}else if(codePoint<1114112){if((units-=4)<0)break;bytes.push(codePoint>>18|240,codePoint>>12&63|128,codePoint>>6&63|128,codePoint&63|128)}else{throw new Error("Invalid code point")}}return bytes}function asciiToBytes(str){var byteArray=[];for(var i=0;i>8;lo=c%256;byteArray.push(lo);byteArray.push(hi)}return byteArray}function base64ToBytes(str){return base64.toByteArray(base64clean(str))}function blitBuffer(src,dst,offset,length){for(var i=0;i=dst.length||i>=src.length)break;dst[i+offset]=src[i]}return i}function isArrayBufferView(obj){return typeof ArrayBuffer.isView==="function"&&ArrayBuffer.isView(obj)}function numberIsNaN(obj){return obj!==obj}},{"base64-js":1,ieee754:3}],3:[function(require,module,exports){exports.read=function(buffer,offset,isLE,mLen,nBytes){var e,m;var eLen=nBytes*8-mLen-1;var eMax=(1<>1;var nBits=-7;var i=isLE?nBytes-1:0;var d=isLE?-1:1;var s=buffer[offset+i];i+=d;e=s&(1<<-nBits)-1;s>>=-nBits;nBits+=eLen;for(;nBits>0;e=e*256+buffer[offset+i],i+=d,nBits-=8){}m=e&(1<<-nBits)-1;e>>=-nBits;nBits+=mLen;for(;nBits>0;m=m*256+buffer[offset+i],i+=d,nBits-=8){}if(e===0){e=1-eBias}else if(e===eMax){return m?NaN:(s?-1:1)*Infinity}else{m=m+Math.pow(2,mLen);e=e-eBias}return(s?-1:1)*m*Math.pow(2,e-mLen)};exports.write=function(buffer,value,offset,isLE,mLen,nBytes){var e,m,c;var eLen=nBytes*8-mLen-1;var eMax=(1<>1;var rt=mLen===23?Math.pow(2,-24)-Math.pow(2,-77):0;var i=isLE?0:nBytes-1;var d=isLE?1:-1;var s=value<0||value===0&&1/value<0?1:0;value=Math.abs(value);if(isNaN(value)||value===Infinity){m=isNaN(value)?1:0;e=eMax}else{e=Math.floor(Math.log(value)/Math.LN2);if(value*(c=Math.pow(2,-e))<1){e--;c*=2}if(e+eBias>=1){value+=rt/c}else{value+=rt*Math.pow(2,1-eBias)}if(value*c>=2){e++;c/=2}if(e+eBias>=eMax){m=0;e=eMax}else if(e+eBias>=1){m=(value*c-1)*Math.pow(2,mLen);e=e+eBias}else{m=value*Math.pow(2,eBias-1)*Math.pow(2,mLen);e=0}}for(;mLen>=8;buffer[offset+i]=m&255,i+=d,m/=256,mLen-=8){}e=e<0;buffer[offset+i]=e&255,i+=d,e/=256,eLen-=8){}buffer[offset+i-d]|=s*128}},{}],4:[function(require,module,exports){var NeuQuant=require("./WasmNeuQuant.js");var LZWEncoder=require("./LZWEncoder.js");function ByteArray(){this.page=-1;this.pages=[];this.newPage()}ByteArray.pageSize=4096;ByteArray.charMap={};for(var i=0;i<256;i++)ByteArray.charMap[i]=String.fromCharCode(i);ByteArray.prototype.newPage=function(){this.pages[++this.page]=new Uint8Array(ByteArray.pageSize);this.cursor=0};ByteArray.prototype.getData=function(){var rv="";for(var p=0;p=ByteArray.pageSize)this.newPage();this.pages[this.page][this.cursor++]=val};ByteArray.prototype.writeUTFBytes=function(string){for(var l=string.length,i=0;i=0)this.dispose=disposalCode};GIFEncoder.prototype.setRepeat=function(repeat){this.repeat=repeat};GIFEncoder.prototype.setTransparent=function(color){this.transparent=color};GIFEncoder.prototype.addFrame=function(imageData){this.image=imageData;this.colorTab=this.globalPalette&&this.globalPalette.slice?this.globalPalette:null;this.getImagePixels();this.analyzePixels();if(this.globalPalette===true)this.globalPalette=this.colorTab;if(this.firstFrame){this.writeLSD();this.writePalette();if(this.repeat>=0){this.writeNetscapeExt()}}this.writeGraphicCtrlExt();this.writeImageDesc();if(!this.firstFrame&&!this.globalPalette)this.writePalette();this.writePixels();this.firstFrame=false};GIFEncoder.prototype.finish=function(){this.out.writeByte(59)};GIFEncoder.prototype.setQuality=function(quality){if(quality<1)quality=1;this.sample=quality};GIFEncoder.prototype.setDither=function(dither){if(dither===true)dither="FloydSteinberg";this.dither=dither};GIFEncoder.prototype.setGlobalPalette=function(palette){this.globalPalette=palette};GIFEncoder.prototype.getGlobalPalette=function(){return this.globalPalette&&this.globalPalette.slice&&this.globalPalette.slice(0)||this.globalPalette};GIFEncoder.prototype.writeHeader=function(){this.out.writeUTFBytes("GIF89a")};GIFEncoder.prototype.analyzePixels=function(){if(!this.colorTab){this.neuQuant=new NeuQuant(this.pixels,this.sample);this.neuQuant.buildColormap();this.colorTab=this.neuQuant.getColormap()}if(this.dither){this.ditherPixels(this.dither.replace("-serpentine",""),this.dither.match(/-serpentine/)!==null)}else{this.indexPixels()}this.pixels=null;this.colorDepth=8;this.palSize=7;if(this.transparent!==null){this.transIndex=this.findClosest(this.transparent,true)}};GIFEncoder.prototype.indexPixels=function(imgq){var nPix=this.pixels.length/3;this.indexedPixels=new Uint8Array(nPix);var k=0;for(var j=0;j=0&&x1+x=0&&y1+y>16,(c&65280)>>8,c&255,used)};GIFEncoder.prototype.findClosestRGB=function(r,g,b,used){if(this.colorTab===null)return-1;if(this.neuQuant&&!used){return this.neuQuant.lookupRGB(r,g,b)}var c=b|g<<8|r<<16;var minpos=0;var dmin=256*256*256;var len=this.colorTab.length;for(var i=0,index=0;i=0){disp=this.dispose&7}disp<<=2;this.out.writeByte(0|disp|0|transp);this.writeShort(this.delay);this.out.writeByte(this.transIndex);this.out.writeByte(0)};GIFEncoder.prototype.writeImageDesc=function(){this.out.writeByte(44);this.writeShort(0);this.writeShort(0);this.writeShort(this.width);this.writeShort(this.height);if(this.firstFrame||this.globalPalette){this.out.writeByte(0)}else{this.out.writeByte(128|0|0|0|this.palSize)}};GIFEncoder.prototype.writeLSD=function(){this.writeShort(this.width);this.writeShort(this.height);this.out.writeByte(128|112|0|this.palSize);this.out.writeByte(0);this.out.writeByte(0)};GIFEncoder.prototype.writeNetscapeExt=function(){this.out.writeByte(33);this.out.writeByte(255);this.out.writeByte(11);this.out.writeUTFBytes("NETSCAPE2.0");this.out.writeByte(3);this.out.writeByte(1);this.writeShort(this.repeat);this.out.writeByte(0)};GIFEncoder.prototype.writePalette=function(){this.out.writeBytes(this.colorTab);var n=3*256-this.colorTab.length;for(var i=0;i>8&255)};GIFEncoder.prototype.writePixels=function(){var enc=new LZWEncoder(this.width,this.height,this.indexedPixels,this.colorDepth);enc.encode(this.out)};GIFEncoder.prototype.stream=function(){return this.out};module.exports=GIFEncoder},{"./LZWEncoder.js":5,"./WasmNeuQuant.js":6}],5:[function(require,module,exports){var EOF=-1;var BITS=12;var HSIZE=5003;var masks=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535];function LZWEncoder(width,height,pixels,colorDepth){var initCodeSize=Math.max(2,colorDepth);var accum=new Uint8Array(256);var htab=new Int32Array(HSIZE);var codetab=new Int32Array(HSIZE);var cur_accum,cur_bits=0;var a_count;var free_ent=0;var maxcode;var clear_flg=false;var g_init_bits,ClearCode,EOFCode;function char_out(c,outs){accum[a_count++]=c;if(a_count>=254)flush_char(outs)}function cl_block(outs){cl_hash(HSIZE);free_ent=ClearCode+2;clear_flg=true;output(ClearCode,outs)}function cl_hash(hsize){for(var i=0;i=0){disp=hsize_reg-i;if(i===0)disp=1;do{if((i-=disp)<0)i+=hsize_reg;if(htab[i]===fcode){ent=codetab[i];continue outer_loop}}while(htab[i]>=0)}output(ent,outs);ent=c;if(free_ent<1<0){outs.writeByte(a_count);outs.writeBytes(accum,0,a_count);a_count=0}}function MAXCODE(n_bits){return(1<0)cur_accum|=code<=8){char_out(cur_accum&255,outs);cur_accum>>=8;cur_bits-=8}if(free_ent>maxcode||clear_flg){if(clear_flg){maxcode=MAXCODE(n_bits=g_init_bits);clear_flg=false}else{++n_bits;if(n_bits==BITS)maxcode=1<0){char_out(cur_accum&255,outs);cur_accum>>=8;cur_bits-=8}flush_char(outs)}}this.encode=encode}module.exports=LZWEncoder},{}],6:[function(require,module,exports){(function(Buffer){var src=Buffer("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","base64");var wamodule=new WebAssembly.Module(src);var instance;var memarray;function NeuQuant(pixels,samplefac){if(!instance){var table=new WebAssembly.Table({initial:0,element:"anyfunc"});var memory=new WebAssembly.Memory({initial:1});memarray=new Uint8Array(memory.buffer);var env={};env.memoryBase=0;env.memory=memory;env.tableBase=0;env.table=table;env.memset=function(){};env._grow=function(){memarray=new Uint8Array(memory.buffer)};env._abort=function(){throw new Error("Abort")};env._exit=function(){throw new Error("Exit")};instance=new WebAssembly.Instance(wamodule,{env:env})}var pixelPtr=instance.exports.malloc(pixels.byteLength);memarray.set(pixels,pixelPtr);instance.exports.init(pixelPtr,pixels.length,samplefac);this.buildColormap=function(){instance.exports.learn();instance.exports.unbiasnet();instance.exports.inxbuild();instance.exports.free(pixelPtr)};this.getColormap=function(){var map=new Uint8Array(256*3);var mapPtr=instance.exports.getColormap();map.set(memarray.subarray(mapPtr,mapPtr+map.byteLength));return map};this.lookupRGB=instance.exports.inxsearch}module.exports=NeuQuant}).call(this,require("buffer").Buffer)},{buffer:2}],7:[function(require,module,exports){ +var GIFEncoder,renderFrame;GIFEncoder=require("./GIFEncoder.js");renderFrame=function(frame){var encoder,page,stream,transfer;encoder=new GIFEncoder(frame.width,frame.height);if(frame.index===0){encoder.writeHeader()}else{encoder.firstFrame=false}encoder.setTransparent(frame.transparent);encoder.setDispose(frame.dispose);encoder.setRepeat(frame.repeat);encoder.setDelay(frame.delay);encoder.setQuality(frame.quality);encoder.setDither(frame.dither);encoder.setGlobalPalette(frame.globalPalette);encoder.addFrame(frame.data);if(frame.last){encoder.finish()}if(frame.globalPalette===true){frame.globalPalette=encoder.getGlobalPalette()}stream=encoder.stream();frame.data=stream.pages;frame.cursor=stream.cursor;frame.pageSize=stream.constructor.pageSize;if(frame.canTransfer){transfer=function(){var i,len,ref,results;ref=frame.data;results=[];for(i=0,len=ref.length;i 0) {\n throw new Error('Invalid string. Length must be a multiple of 4')\n }\n\n // the number of equal signs (place holders)\n // if there are two placeholders, than the two characters before it\n // represent one byte\n // if there is only one, then the three characters before it represent 2 bytes\n // this is just a cheap hack to not do indexOf twice\n return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0\n}\n\nfunction byteLength (b64) {\n // base64 is 4/3 + up to two characters of the original data\n return b64.length * 3 / 4 - placeHoldersCount(b64)\n}\n\nfunction toByteArray (b64) {\n var i, j, l, tmp, placeHolders, arr\n var len = b64.length\n placeHolders = placeHoldersCount(b64)\n\n arr = new Arr(len * 3 / 4 - placeHolders)\n\n // if there are placeholders, only get up to the last complete 4 chars\n l = placeHolders > 0 ? len - 4 : len\n\n var L = 0\n\n for (i = 0, j = 0; i < l; i += 4, j += 3) {\n tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]\n arr[L++] = (tmp >> 16) & 0xFF\n arr[L++] = (tmp >> 8) & 0xFF\n arr[L++] = tmp & 0xFF\n }\n\n if (placeHolders === 2) {\n tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)\n arr[L++] = tmp & 0xFF\n } else if (placeHolders === 1) {\n tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)\n arr[L++] = (tmp >> 8) & 0xFF\n arr[L++] = tmp & 0xFF\n }\n\n return arr\n}\n\nfunction tripletToBase64 (num) {\n return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]\n}\n\nfunction encodeChunk (uint8, start, end) {\n var tmp\n var output = []\n for (var i = start; i < end; i += 3) {\n tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])\n output.push(tripletToBase64(tmp))\n }\n return output.join('')\n}\n\nfunction fromByteArray (uint8) {\n var tmp\n var len = uint8.length\n var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes\n var output = ''\n var parts = []\n var maxChunkLength = 16383 // must be multiple of 3\n\n // go through the array every three bytes, we'll deal with trailing stuff later\n for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\n parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))\n }\n\n // pad the end with zeros, but make sure to not forget the extra bytes\n if (extraBytes === 1) {\n tmp = uint8[len - 1]\n output += lookup[tmp >> 2]\n output += lookup[(tmp << 4) & 0x3F]\n output += '=='\n } else if (extraBytes === 2) {\n tmp = (uint8[len - 2] << 8) + (uint8[len - 1])\n output += lookup[tmp >> 10]\n output += lookup[(tmp >> 4) & 0x3F]\n output += lookup[(tmp << 2) & 0x3F]\n output += '='\n }\n\n parts.push(output)\n\n return parts.join('')\n}\n","/*!\n * The buffer module from node.js, for the browser.\n *\n * @author Feross Aboukhadijeh \n * @license MIT\n */\n/* eslint-disable no-proto */\n\n'use strict'\n\nvar base64 = require('base64-js')\nvar ieee754 = require('ieee754')\n\nexports.Buffer = Buffer\nexports.SlowBuffer = SlowBuffer\nexports.INSPECT_MAX_BYTES = 50\n\nvar K_MAX_LENGTH = 0x7fffffff\nexports.kMaxLength = K_MAX_LENGTH\n\n/**\n * If `Buffer.TYPED_ARRAY_SUPPORT`:\n * === true Use Uint8Array implementation (fastest)\n * === false Print warning and recommend using `buffer` v4.x which has an Object\n * implementation (most compatible, even IE6)\n *\n * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,\n * Opera 11.6+, iOS 4.2+.\n *\n * We report that the browser does not support typed arrays if the are not subclassable\n * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array`\n * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support\n * for __proto__ and has a buggy typed array implementation.\n */\nBuffer.TYPED_ARRAY_SUPPORT = typedArraySupport()\n\nif (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' &&\n typeof console.error === 'function') {\n console.error(\n 'This browser lacks typed array (Uint8Array) support which is required by ' +\n '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.'\n )\n}\n\nfunction typedArraySupport () {\n // Can typed array instances can be augmented?\n try {\n var arr = new Uint8Array(1)\n arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}\n return arr.foo() === 42\n } catch (e) {\n return false\n }\n}\n\nfunction createBuffer (length) {\n if (length > K_MAX_LENGTH) {\n throw new RangeError('Invalid typed array length')\n }\n // Return an augmented `Uint8Array` instance\n var buf = new Uint8Array(length)\n buf.__proto__ = Buffer.prototype\n return buf\n}\n\n/**\n * The Buffer constructor returns instances of `Uint8Array` that have their\n * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of\n * `Uint8Array`, so the returned instances will have all the node `Buffer` methods\n * and the `Uint8Array` methods. Square bracket notation works as expected -- it\n * returns a single octet.\n *\n * The `Uint8Array` prototype remains unmodified.\n */\n\nfunction Buffer (arg, encodingOrOffset, length) {\n // Common case.\n if (typeof arg === 'number') {\n if (typeof encodingOrOffset === 'string') {\n throw new Error(\n 'If encoding is specified then the first argument must be a string'\n )\n }\n return allocUnsafe(arg)\n }\n return from(arg, encodingOrOffset, length)\n}\n\n// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97\nif (typeof Symbol !== 'undefined' && Symbol.species &&\n Buffer[Symbol.species] === Buffer) {\n Object.defineProperty(Buffer, Symbol.species, {\n value: null,\n configurable: true,\n enumerable: false,\n writable: false\n })\n}\n\nBuffer.poolSize = 8192 // not used by this implementation\n\nfunction from (value, encodingOrOffset, length) {\n if (typeof value === 'number') {\n throw new TypeError('\"value\" argument must not be a number')\n }\n\n if (value instanceof ArrayBuffer) {\n return fromArrayBuffer(value, encodingOrOffset, length)\n }\n\n if (typeof value === 'string') {\n return fromString(value, encodingOrOffset)\n }\n\n return fromObject(value)\n}\n\n/**\n * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError\n * if value is a number.\n * Buffer.from(str[, encoding])\n * Buffer.from(array)\n * Buffer.from(buffer)\n * Buffer.from(arrayBuffer[, byteOffset[, length]])\n **/\nBuffer.from = function (value, encodingOrOffset, length) {\n return from(value, encodingOrOffset, length)\n}\n\n// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug:\n// https://github.com/feross/buffer/pull/148\nBuffer.prototype.__proto__ = Uint8Array.prototype\nBuffer.__proto__ = Uint8Array\n\nfunction assertSize (size) {\n if (typeof size !== 'number') {\n throw new TypeError('\"size\" argument must be a number')\n } else if (size < 0) {\n throw new RangeError('\"size\" argument must not be negative')\n }\n}\n\nfunction alloc (size, fill, encoding) {\n assertSize(size)\n if (size <= 0) {\n return createBuffer(size)\n }\n if (fill !== undefined) {\n // Only pay attention to encoding if it's a string. This\n // prevents accidentally sending in a number that would\n // be interpretted as a start offset.\n return typeof encoding === 'string'\n ? createBuffer(size).fill(fill, encoding)\n : createBuffer(size).fill(fill)\n }\n return createBuffer(size)\n}\n\n/**\n * Creates a new filled Buffer instance.\n * alloc(size[, fill[, encoding]])\n **/\nBuffer.alloc = function (size, fill, encoding) {\n return alloc(size, fill, encoding)\n}\n\nfunction allocUnsafe (size) {\n assertSize(size)\n return createBuffer(size < 0 ? 0 : checked(size) | 0)\n}\n\n/**\n * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.\n * */\nBuffer.allocUnsafe = function (size) {\n return allocUnsafe(size)\n}\n/**\n * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.\n */\nBuffer.allocUnsafeSlow = function (size) {\n return allocUnsafe(size)\n}\n\nfunction fromString (string, encoding) {\n if (typeof encoding !== 'string' || encoding === '') {\n encoding = 'utf8'\n }\n\n if (!Buffer.isEncoding(encoding)) {\n throw new TypeError('\"encoding\" must be a valid string encoding')\n }\n\n var length = byteLength(string, encoding) | 0\n var buf = createBuffer(length)\n\n var actual = buf.write(string, encoding)\n\n if (actual !== length) {\n // Writing a hex string, for example, that contains invalid characters will\n // cause everything after the first invalid character to be ignored. (e.g.\n // 'abxxcd' will be treated as 'ab')\n buf = buf.slice(0, actual)\n }\n\n return buf\n}\n\nfunction fromArrayLike (array) {\n var length = array.length < 0 ? 0 : checked(array.length) | 0\n var buf = createBuffer(length)\n for (var i = 0; i < length; i += 1) {\n buf[i] = array[i] & 255\n }\n return buf\n}\n\nfunction fromArrayBuffer (array, byteOffset, length) {\n if (byteOffset < 0 || array.byteLength < byteOffset) {\n throw new RangeError('\\'offset\\' is out of bounds')\n }\n\n if (array.byteLength < byteOffset + (length || 0)) {\n throw new RangeError('\\'length\\' is out of bounds')\n }\n\n var buf\n if (byteOffset === undefined && length === undefined) {\n buf = new Uint8Array(array)\n } else if (length === undefined) {\n buf = new Uint8Array(array, byteOffset)\n } else {\n buf = new Uint8Array(array, byteOffset, length)\n }\n\n // Return an augmented `Uint8Array` instance\n buf.__proto__ = Buffer.prototype\n return buf\n}\n\nfunction fromObject (obj) {\n if (Buffer.isBuffer(obj)) {\n var len = checked(obj.length) | 0\n var buf = createBuffer(len)\n\n if (buf.length === 0) {\n return buf\n }\n\n obj.copy(buf, 0, 0, len)\n return buf\n }\n\n if (obj) {\n if (isArrayBufferView(obj) || 'length' in obj) {\n if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) {\n return createBuffer(0)\n }\n return fromArrayLike(obj)\n }\n\n if (obj.type === 'Buffer' && Array.isArray(obj.data)) {\n return fromArrayLike(obj.data)\n }\n }\n\n throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')\n}\n\nfunction checked (length) {\n // Note: cannot use `length < K_MAX_LENGTH` here because that fails when\n // length is NaN (which is otherwise coerced to zero.)\n if (length >= K_MAX_LENGTH) {\n throw new RangeError('Attempt to allocate Buffer larger than maximum ' +\n 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes')\n }\n return length | 0\n}\n\nfunction SlowBuffer (length) {\n if (+length != length) { // eslint-disable-line eqeqeq\n length = 0\n }\n return Buffer.alloc(+length)\n}\n\nBuffer.isBuffer = function isBuffer (b) {\n return b != null && b._isBuffer === true\n}\n\nBuffer.compare = function compare (a, b) {\n if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {\n throw new TypeError('Arguments must be Buffers')\n }\n\n if (a === b) return 0\n\n var x = a.length\n var y = b.length\n\n for (var i = 0, len = Math.min(x, y); i < len; ++i) {\n if (a[i] !== b[i]) {\n x = a[i]\n y = b[i]\n break\n }\n }\n\n if (x < y) return -1\n if (y < x) return 1\n return 0\n}\n\nBuffer.isEncoding = function isEncoding (encoding) {\n switch (String(encoding).toLowerCase()) {\n case 'hex':\n case 'utf8':\n case 'utf-8':\n case 'ascii':\n case 'latin1':\n case 'binary':\n case 'base64':\n case 'ucs2':\n case 'ucs-2':\n case 'utf16le':\n case 'utf-16le':\n return true\n default:\n return false\n }\n}\n\nBuffer.concat = function concat (list, length) {\n if (!Array.isArray(list)) {\n throw new TypeError('\"list\" argument must be an Array of Buffers')\n }\n\n if (list.length === 0) {\n return Buffer.alloc(0)\n }\n\n var i\n if (length === undefined) {\n length = 0\n for (i = 0; i < list.length; ++i) {\n length += list[i].length\n }\n }\n\n var buffer = Buffer.allocUnsafe(length)\n var pos = 0\n for (i = 0; i < list.length; ++i) {\n var buf = list[i]\n if (!Buffer.isBuffer(buf)) {\n throw new TypeError('\"list\" argument must be an Array of Buffers')\n }\n buf.copy(buffer, pos)\n pos += buf.length\n }\n return buffer\n}\n\nfunction byteLength (string, encoding) {\n if (Buffer.isBuffer(string)) {\n return string.length\n }\n if (isArrayBufferView(string) || string instanceof ArrayBuffer) {\n return string.byteLength\n }\n if (typeof string !== 'string') {\n string = '' + string\n }\n\n var len = string.length\n if (len === 0) return 0\n\n // Use a for loop to avoid recursion\n var loweredCase = false\n for (;;) {\n switch (encoding) {\n case 'ascii':\n case 'latin1':\n case 'binary':\n return len\n case 'utf8':\n case 'utf-8':\n case undefined:\n return utf8ToBytes(string).length\n case 'ucs2':\n case 'ucs-2':\n case 'utf16le':\n case 'utf-16le':\n return len * 2\n case 'hex':\n return len >>> 1\n case 'base64':\n return base64ToBytes(string).length\n default:\n if (loweredCase) return utf8ToBytes(string).length // assume utf8\n encoding = ('' + encoding).toLowerCase()\n loweredCase = true\n }\n }\n}\nBuffer.byteLength = byteLength\n\nfunction slowToString (encoding, start, end) {\n var loweredCase = false\n\n // No need to verify that \"this.length <= MAX_UINT32\" since it's a read-only\n // property of a typed array.\n\n // This behaves neither like String nor Uint8Array in that we set start/end\n // to their upper/lower bounds if the value passed is out of range.\n // undefined is handled specially as per ECMA-262 6th Edition,\n // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.\n if (start === undefined || start < 0) {\n start = 0\n }\n // Return early if start > this.length. Done here to prevent potential uint32\n // coercion fail below.\n if (start > this.length) {\n return ''\n }\n\n if (end === undefined || end > this.length) {\n end = this.length\n }\n\n if (end <= 0) {\n return ''\n }\n\n // Force coersion to uint32. This will also coerce falsey/NaN values to 0.\n end >>>= 0\n start >>>= 0\n\n if (end <= start) {\n return ''\n }\n\n if (!encoding) encoding = 'utf8'\n\n while (true) {\n switch (encoding) {\n case 'hex':\n return hexSlice(this, start, end)\n\n case 'utf8':\n case 'utf-8':\n return utf8Slice(this, start, end)\n\n case 'ascii':\n return asciiSlice(this, start, end)\n\n case 'latin1':\n case 'binary':\n return latin1Slice(this, start, end)\n\n case 'base64':\n return base64Slice(this, start, end)\n\n case 'ucs2':\n case 'ucs-2':\n case 'utf16le':\n case 'utf-16le':\n return utf16leSlice(this, start, end)\n\n default:\n if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)\n encoding = (encoding + '').toLowerCase()\n loweredCase = true\n }\n }\n}\n\n// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package)\n// to detect a Buffer instance. It's not possible to use `instanceof Buffer`\n// reliably in a browserify context because there could be multiple different\n// copies of the 'buffer' package in use. This method works even for Buffer\n// instances that were created from another copy of the `buffer` package.\n// See: https://github.com/feross/buffer/issues/154\nBuffer.prototype._isBuffer = true\n\nfunction swap (b, n, m) {\n var i = b[n]\n b[n] = b[m]\n b[m] = i\n}\n\nBuffer.prototype.swap16 = function swap16 () {\n var len = this.length\n if (len % 2 !== 0) {\n throw new RangeError('Buffer size must be a multiple of 16-bits')\n }\n for (var i = 0; i < len; i += 2) {\n swap(this, i, i + 1)\n }\n return this\n}\n\nBuffer.prototype.swap32 = function swap32 () {\n var len = this.length\n if (len % 4 !== 0) {\n throw new RangeError('Buffer size must be a multiple of 32-bits')\n }\n for (var i = 0; i < len; i += 4) {\n swap(this, i, i + 3)\n swap(this, i + 1, i + 2)\n }\n return this\n}\n\nBuffer.prototype.swap64 = function swap64 () {\n var len = this.length\n if (len % 8 !== 0) {\n throw new RangeError('Buffer size must be a multiple of 64-bits')\n }\n for (var i = 0; i < len; i += 8) {\n swap(this, i, i + 7)\n swap(this, i + 1, i + 6)\n swap(this, i + 2, i + 5)\n swap(this, i + 3, i + 4)\n }\n return this\n}\n\nBuffer.prototype.toString = function toString () {\n var length = this.length\n if (length === 0) return ''\n if (arguments.length === 0) return utf8Slice(this, 0, length)\n return slowToString.apply(this, arguments)\n}\n\nBuffer.prototype.equals = function equals (b) {\n if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')\n if (this === b) return true\n return Buffer.compare(this, b) === 0\n}\n\nBuffer.prototype.inspect = function inspect () {\n var str = ''\n var max = exports.INSPECT_MAX_BYTES\n if (this.length > 0) {\n str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')\n if (this.length > max) str += ' ... '\n }\n return ''\n}\n\nBuffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {\n if (!Buffer.isBuffer(target)) {\n throw new TypeError('Argument must be a Buffer')\n }\n\n if (start === undefined) {\n start = 0\n }\n if (end === undefined) {\n end = target ? target.length : 0\n }\n if (thisStart === undefined) {\n thisStart = 0\n }\n if (thisEnd === undefined) {\n thisEnd = this.length\n }\n\n if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {\n throw new RangeError('out of range index')\n }\n\n if (thisStart >= thisEnd && start >= end) {\n return 0\n }\n if (thisStart >= thisEnd) {\n return -1\n }\n if (start >= end) {\n return 1\n }\n\n start >>>= 0\n end >>>= 0\n thisStart >>>= 0\n thisEnd >>>= 0\n\n if (this === target) return 0\n\n var x = thisEnd - thisStart\n var y = end - start\n var len = Math.min(x, y)\n\n var thisCopy = this.slice(thisStart, thisEnd)\n var targetCopy = target.slice(start, end)\n\n for (var i = 0; i < len; ++i) {\n if (thisCopy[i] !== targetCopy[i]) {\n x = thisCopy[i]\n y = targetCopy[i]\n break\n }\n }\n\n if (x < y) return -1\n if (y < x) return 1\n return 0\n}\n\n// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,\n// OR the last index of `val` in `buffer` at offset <= `byteOffset`.\n//\n// Arguments:\n// - buffer - a Buffer to search\n// - val - a string, Buffer, or number\n// - byteOffset - an index into `buffer`; will be clamped to an int32\n// - encoding - an optional encoding, relevant is val is a string\n// - dir - true for indexOf, false for lastIndexOf\nfunction bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {\n // Empty buffer means no match\n if (buffer.length === 0) return -1\n\n // Normalize byteOffset\n if (typeof byteOffset === 'string') {\n encoding = byteOffset\n byteOffset = 0\n } else if (byteOffset > 0x7fffffff) {\n byteOffset = 0x7fffffff\n } else if (byteOffset < -0x80000000) {\n byteOffset = -0x80000000\n }\n byteOffset = +byteOffset // Coerce to Number.\n if (numberIsNaN(byteOffset)) {\n // byteOffset: it it's undefined, null, NaN, \"foo\", etc, search whole buffer\n byteOffset = dir ? 0 : (buffer.length - 1)\n }\n\n // Normalize byteOffset: negative offsets start from the end of the buffer\n if (byteOffset < 0) byteOffset = buffer.length + byteOffset\n if (byteOffset >= buffer.length) {\n if (dir) return -1\n else byteOffset = buffer.length - 1\n } else if (byteOffset < 0) {\n if (dir) byteOffset = 0\n else return -1\n }\n\n // Normalize val\n if (typeof val === 'string') {\n val = Buffer.from(val, encoding)\n }\n\n // Finally, search either indexOf (if dir is true) or lastIndexOf\n if (Buffer.isBuffer(val)) {\n // Special case: looking for empty string/buffer always fails\n if (val.length === 0) {\n return -1\n }\n return arrayIndexOf(buffer, val, byteOffset, encoding, dir)\n } else if (typeof val === 'number') {\n val = val & 0xFF // Search for a byte value [0-255]\n if (typeof Uint8Array.prototype.indexOf === 'function') {\n if (dir) {\n return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)\n } else {\n return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)\n }\n }\n return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir)\n }\n\n throw new TypeError('val must be string, number or Buffer')\n}\n\nfunction arrayIndexOf (arr, val, byteOffset, encoding, dir) {\n var indexSize = 1\n var arrLength = arr.length\n var valLength = val.length\n\n if (encoding !== undefined) {\n encoding = String(encoding).toLowerCase()\n if (encoding === 'ucs2' || encoding === 'ucs-2' ||\n encoding === 'utf16le' || encoding === 'utf-16le') {\n if (arr.length < 2 || val.length < 2) {\n return -1\n }\n indexSize = 2\n arrLength /= 2\n valLength /= 2\n byteOffset /= 2\n }\n }\n\n function read (buf, i) {\n if (indexSize === 1) {\n return buf[i]\n } else {\n return buf.readUInt16BE(i * indexSize)\n }\n }\n\n var i\n if (dir) {\n var foundIndex = -1\n for (i = byteOffset; i < arrLength; i++) {\n if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {\n if (foundIndex === -1) foundIndex = i\n if (i - foundIndex + 1 === valLength) return foundIndex * indexSize\n } else {\n if (foundIndex !== -1) i -= i - foundIndex\n foundIndex = -1\n }\n }\n } else {\n if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength\n for (i = byteOffset; i >= 0; i--) {\n var found = true\n for (var j = 0; j < valLength; j++) {\n if (read(arr, i + j) !== read(val, j)) {\n found = false\n break\n }\n }\n if (found) return i\n }\n }\n\n return -1\n}\n\nBuffer.prototype.includes = function includes (val, byteOffset, encoding) {\n return this.indexOf(val, byteOffset, encoding) !== -1\n}\n\nBuffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {\n return bidirectionalIndexOf(this, val, byteOffset, encoding, true)\n}\n\nBuffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {\n return bidirectionalIndexOf(this, val, byteOffset, encoding, false)\n}\n\nfunction hexWrite (buf, string, offset, length) {\n offset = Number(offset) || 0\n var remaining = buf.length - offset\n if (!length) {\n length = remaining\n } else {\n length = Number(length)\n if (length > remaining) {\n length = remaining\n }\n }\n\n // must be an even number of digits\n var strLen = string.length\n if (strLen % 2 !== 0) throw new TypeError('Invalid hex string')\n\n if (length > strLen / 2) {\n length = strLen / 2\n }\n for (var i = 0; i < length; ++i) {\n var parsed = parseInt(string.substr(i * 2, 2), 16)\n if (numberIsNaN(parsed)) return i\n buf[offset + i] = parsed\n }\n return i\n}\n\nfunction utf8Write (buf, string, offset, length) {\n return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)\n}\n\nfunction asciiWrite (buf, string, offset, length) {\n return blitBuffer(asciiToBytes(string), buf, offset, length)\n}\n\nfunction latin1Write (buf, string, offset, length) {\n return asciiWrite(buf, string, offset, length)\n}\n\nfunction base64Write (buf, string, offset, length) {\n return blitBuffer(base64ToBytes(string), buf, offset, length)\n}\n\nfunction ucs2Write (buf, string, offset, length) {\n return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)\n}\n\nBuffer.prototype.write = function write (string, offset, length, encoding) {\n // Buffer#write(string)\n if (offset === undefined) {\n encoding = 'utf8'\n length = this.length\n offset = 0\n // Buffer#write(string, encoding)\n } else if (length === undefined && typeof offset === 'string') {\n encoding = offset\n length = this.length\n offset = 0\n // Buffer#write(string, offset[, length][, encoding])\n } else if (isFinite(offset)) {\n offset = offset >>> 0\n if (isFinite(length)) {\n length = length >>> 0\n if (encoding === undefined) encoding = 'utf8'\n } else {\n encoding = length\n length = undefined\n }\n } else {\n throw new Error(\n 'Buffer.write(string, encoding, offset[, length]) is no longer supported'\n )\n }\n\n var remaining = this.length - offset\n if (length === undefined || length > remaining) length = remaining\n\n if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {\n throw new RangeError('Attempt to write outside buffer bounds')\n }\n\n if (!encoding) encoding = 'utf8'\n\n var loweredCase = false\n for (;;) {\n switch (encoding) {\n case 'hex':\n return hexWrite(this, string, offset, length)\n\n case 'utf8':\n case 'utf-8':\n return utf8Write(this, string, offset, length)\n\n case 'ascii':\n return asciiWrite(this, string, offset, length)\n\n case 'latin1':\n case 'binary':\n return latin1Write(this, string, offset, length)\n\n case 'base64':\n // Warning: maxLength not taken into account in base64Write\n return base64Write(this, string, offset, length)\n\n case 'ucs2':\n case 'ucs-2':\n case 'utf16le':\n case 'utf-16le':\n return ucs2Write(this, string, offset, length)\n\n default:\n if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)\n encoding = ('' + encoding).toLowerCase()\n loweredCase = true\n }\n }\n}\n\nBuffer.prototype.toJSON = function toJSON () {\n return {\n type: 'Buffer',\n data: Array.prototype.slice.call(this._arr || this, 0)\n }\n}\n\nfunction base64Slice (buf, start, end) {\n if (start === 0 && end === buf.length) {\n return base64.fromByteArray(buf)\n } else {\n return base64.fromByteArray(buf.slice(start, end))\n }\n}\n\nfunction utf8Slice (buf, start, end) {\n end = Math.min(buf.length, end)\n var res = []\n\n var i = start\n while (i < end) {\n var firstByte = buf[i]\n var codePoint = null\n var bytesPerSequence = (firstByte > 0xEF) ? 4\n : (firstByte > 0xDF) ? 3\n : (firstByte > 0xBF) ? 2\n : 1\n\n if (i + bytesPerSequence <= end) {\n var secondByte, thirdByte, fourthByte, tempCodePoint\n\n switch (bytesPerSequence) {\n case 1:\n if (firstByte < 0x80) {\n codePoint = firstByte\n }\n break\n case 2:\n secondByte = buf[i + 1]\n if ((secondByte & 0xC0) === 0x80) {\n tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)\n if (tempCodePoint > 0x7F) {\n codePoint = tempCodePoint\n }\n }\n break\n case 3:\n secondByte = buf[i + 1]\n thirdByte = buf[i + 2]\n if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {\n tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)\n if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {\n codePoint = tempCodePoint\n }\n }\n break\n case 4:\n secondByte = buf[i + 1]\n thirdByte = buf[i + 2]\n fourthByte = buf[i + 3]\n if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {\n tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)\n if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {\n codePoint = tempCodePoint\n }\n }\n }\n }\n\n if (codePoint === null) {\n // we did not generate a valid codePoint so insert a\n // replacement char (U+FFFD) and advance only 1 byte\n codePoint = 0xFFFD\n bytesPerSequence = 1\n } else if (codePoint > 0xFFFF) {\n // encode to utf16 (surrogate pair dance)\n codePoint -= 0x10000\n res.push(codePoint >>> 10 & 0x3FF | 0xD800)\n codePoint = 0xDC00 | codePoint & 0x3FF\n }\n\n res.push(codePoint)\n i += bytesPerSequence\n }\n\n return decodeCodePointsArray(res)\n}\n\n// Based on http://stackoverflow.com/a/22747272/680742, the browser with\n// the lowest limit is Chrome, with 0x10000 args.\n// We go 1 magnitude less, for safety\nvar MAX_ARGUMENTS_LENGTH = 0x1000\n\nfunction decodeCodePointsArray (codePoints) {\n var len = codePoints.length\n if (len <= MAX_ARGUMENTS_LENGTH) {\n return String.fromCharCode.apply(String, codePoints) // avoid extra slice()\n }\n\n // Decode in chunks to avoid \"call stack size exceeded\".\n var res = ''\n var i = 0\n while (i < len) {\n res += String.fromCharCode.apply(\n String,\n codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)\n )\n }\n return res\n}\n\nfunction asciiSlice (buf, start, end) {\n var ret = ''\n end = Math.min(buf.length, end)\n\n for (var i = start; i < end; ++i) {\n ret += String.fromCharCode(buf[i] & 0x7F)\n }\n return ret\n}\n\nfunction latin1Slice (buf, start, end) {\n var ret = ''\n end = Math.min(buf.length, end)\n\n for (var i = start; i < end; ++i) {\n ret += String.fromCharCode(buf[i])\n }\n return ret\n}\n\nfunction hexSlice (buf, start, end) {\n var len = buf.length\n\n if (!start || start < 0) start = 0\n if (!end || end < 0 || end > len) end = len\n\n var out = ''\n for (var i = start; i < end; ++i) {\n out += toHex(buf[i])\n }\n return out\n}\n\nfunction utf16leSlice (buf, start, end) {\n var bytes = buf.slice(start, end)\n var res = ''\n for (var i = 0; i < bytes.length; i += 2) {\n res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256))\n }\n return res\n}\n\nBuffer.prototype.slice = function slice (start, end) {\n var len = this.length\n start = ~~start\n end = end === undefined ? len : ~~end\n\n if (start < 0) {\n start += len\n if (start < 0) start = 0\n } else if (start > len) {\n start = len\n }\n\n if (end < 0) {\n end += len\n if (end < 0) end = 0\n } else if (end > len) {\n end = len\n }\n\n if (end < start) end = start\n\n var newBuf = this.subarray(start, end)\n // Return an augmented `Uint8Array` instance\n newBuf.__proto__ = Buffer.prototype\n return newBuf\n}\n\n/*\n * Need to make sure that buffer isn't trying to write out of bounds.\n */\nfunction checkOffset (offset, ext, length) {\n if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')\n if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')\n}\n\nBuffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {\n offset = offset >>> 0\n byteLength = byteLength >>> 0\n if (!noAssert) checkOffset(offset, byteLength, this.length)\n\n var val = this[offset]\n var mul = 1\n var i = 0\n while (++i < byteLength && (mul *= 0x100)) {\n val += this[offset + i] * mul\n }\n\n return val\n}\n\nBuffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {\n offset = offset >>> 0\n byteLength = byteLength >>> 0\n if (!noAssert) {\n checkOffset(offset, byteLength, this.length)\n }\n\n var val = this[offset + --byteLength]\n var mul = 1\n while (byteLength > 0 && (mul *= 0x100)) {\n val += this[offset + --byteLength] * mul\n }\n\n return val\n}\n\nBuffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {\n offset = offset >>> 0\n if (!noAssert) checkOffset(offset, 1, this.length)\n return this[offset]\n}\n\nBuffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {\n offset = offset >>> 0\n if (!noAssert) checkOffset(offset, 2, this.length)\n return this[offset] | (this[offset + 1] << 8)\n}\n\nBuffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {\n offset = offset >>> 0\n if (!noAssert) checkOffset(offset, 2, this.length)\n return (this[offset] << 8) | this[offset + 1]\n}\n\nBuffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {\n offset = offset >>> 0\n if (!noAssert) checkOffset(offset, 4, this.length)\n\n return ((this[offset]) |\n (this[offset + 1] << 8) |\n (this[offset + 2] << 16)) +\n (this[offset + 3] * 0x1000000)\n}\n\nBuffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {\n offset = offset >>> 0\n if (!noAssert) checkOffset(offset, 4, this.length)\n\n return (this[offset] * 0x1000000) +\n ((this[offset + 1] << 16) |\n (this[offset + 2] << 8) |\n this[offset + 3])\n}\n\nBuffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {\n offset = offset >>> 0\n byteLength = byteLength >>> 0\n if (!noAssert) checkOffset(offset, byteLength, this.length)\n\n var val = this[offset]\n var mul = 1\n var i = 0\n while (++i < byteLength && (mul *= 0x100)) {\n val += this[offset + i] * mul\n }\n mul *= 0x80\n\n if (val >= mul) val -= Math.pow(2, 8 * byteLength)\n\n return val\n}\n\nBuffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {\n offset = offset >>> 0\n byteLength = byteLength >>> 0\n if (!noAssert) checkOffset(offset, byteLength, this.length)\n\n var i = byteLength\n var mul = 1\n var val = this[offset + --i]\n while (i > 0 && (mul *= 0x100)) {\n val += this[offset + --i] * mul\n }\n mul *= 0x80\n\n if (val >= mul) val -= Math.pow(2, 8 * byteLength)\n\n return val\n}\n\nBuffer.prototype.readInt8 = function readInt8 (offset, noAssert) {\n offset = offset >>> 0\n if (!noAssert) checkOffset(offset, 1, this.length)\n if (!(this[offset] & 0x80)) return (this[offset])\n return ((0xff - this[offset] + 1) * -1)\n}\n\nBuffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {\n offset = offset >>> 0\n if (!noAssert) checkOffset(offset, 2, this.length)\n var val = this[offset] | (this[offset + 1] << 8)\n return (val & 0x8000) ? val | 0xFFFF0000 : val\n}\n\nBuffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {\n offset = offset >>> 0\n if (!noAssert) checkOffset(offset, 2, this.length)\n var val = this[offset + 1] | (this[offset] << 8)\n return (val & 0x8000) ? val | 0xFFFF0000 : val\n}\n\nBuffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {\n offset = offset >>> 0\n if (!noAssert) checkOffset(offset, 4, this.length)\n\n return (this[offset]) |\n (this[offset + 1] << 8) |\n (this[offset + 2] << 16) |\n (this[offset + 3] << 24)\n}\n\nBuffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {\n offset = offset >>> 0\n if (!noAssert) checkOffset(offset, 4, this.length)\n\n return (this[offset] << 24) |\n (this[offset + 1] << 16) |\n (this[offset + 2] << 8) |\n (this[offset + 3])\n}\n\nBuffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {\n offset = offset >>> 0\n if (!noAssert) checkOffset(offset, 4, this.length)\n return ieee754.read(this, offset, true, 23, 4)\n}\n\nBuffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {\n offset = offset >>> 0\n if (!noAssert) checkOffset(offset, 4, this.length)\n return ieee754.read(this, offset, false, 23, 4)\n}\n\nBuffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {\n offset = offset >>> 0\n if (!noAssert) checkOffset(offset, 8, this.length)\n return ieee754.read(this, offset, true, 52, 8)\n}\n\nBuffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {\n offset = offset >>> 0\n if (!noAssert) checkOffset(offset, 8, this.length)\n return ieee754.read(this, offset, false, 52, 8)\n}\n\nfunction checkInt (buf, value, offset, ext, max, min) {\n if (!Buffer.isBuffer(buf)) throw new TypeError('\"buffer\" argument must be a Buffer instance')\n if (value > max || value < min) throw new RangeError('\"value\" argument is out of bounds')\n if (offset + ext > buf.length) throw new RangeError('Index out of range')\n}\n\nBuffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {\n value = +value\n offset = offset >>> 0\n byteLength = byteLength >>> 0\n if (!noAssert) {\n var maxBytes = Math.pow(2, 8 * byteLength) - 1\n checkInt(this, value, offset, byteLength, maxBytes, 0)\n }\n\n var mul = 1\n var i = 0\n this[offset] = value & 0xFF\n while (++i < byteLength && (mul *= 0x100)) {\n this[offset + i] = (value / mul) & 0xFF\n }\n\n return offset + byteLength\n}\n\nBuffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {\n value = +value\n offset = offset >>> 0\n byteLength = byteLength >>> 0\n if (!noAssert) {\n var maxBytes = Math.pow(2, 8 * byteLength) - 1\n checkInt(this, value, offset, byteLength, maxBytes, 0)\n }\n\n var i = byteLength - 1\n var mul = 1\n this[offset + i] = value & 0xFF\n while (--i >= 0 && (mul *= 0x100)) {\n this[offset + i] = (value / mul) & 0xFF\n }\n\n return offset + byteLength\n}\n\nBuffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {\n value = +value\n offset = offset >>> 0\n if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)\n this[offset] = (value & 0xff)\n return offset + 1\n}\n\nBuffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {\n value = +value\n offset = offset >>> 0\n if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)\n this[offset] = (value & 0xff)\n this[offset + 1] = (value >>> 8)\n return offset + 2\n}\n\nBuffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {\n value = +value\n offset = offset >>> 0\n if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)\n this[offset] = (value >>> 8)\n this[offset + 1] = (value & 0xff)\n return offset + 2\n}\n\nBuffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {\n value = +value\n offset = offset >>> 0\n if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)\n this[offset + 3] = (value >>> 24)\n this[offset + 2] = (value >>> 16)\n this[offset + 1] = (value >>> 8)\n this[offset] = (value & 0xff)\n return offset + 4\n}\n\nBuffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {\n value = +value\n offset = offset >>> 0\n if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)\n this[offset] = (value >>> 24)\n this[offset + 1] = (value >>> 16)\n this[offset + 2] = (value >>> 8)\n this[offset + 3] = (value & 0xff)\n return offset + 4\n}\n\nBuffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {\n value = +value\n offset = offset >>> 0\n if (!noAssert) {\n var limit = Math.pow(2, (8 * byteLength) - 1)\n\n checkInt(this, value, offset, byteLength, limit - 1, -limit)\n }\n\n var i = 0\n var mul = 1\n var sub = 0\n this[offset] = value & 0xFF\n while (++i < byteLength && (mul *= 0x100)) {\n if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {\n sub = 1\n }\n this[offset + i] = ((value / mul) >> 0) - sub & 0xFF\n }\n\n return offset + byteLength\n}\n\nBuffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {\n value = +value\n offset = offset >>> 0\n if (!noAssert) {\n var limit = Math.pow(2, (8 * byteLength) - 1)\n\n checkInt(this, value, offset, byteLength, limit - 1, -limit)\n }\n\n var i = byteLength - 1\n var mul = 1\n var sub = 0\n this[offset + i] = value & 0xFF\n while (--i >= 0 && (mul *= 0x100)) {\n if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {\n sub = 1\n }\n this[offset + i] = ((value / mul) >> 0) - sub & 0xFF\n }\n\n return offset + byteLength\n}\n\nBuffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {\n value = +value\n offset = offset >>> 0\n if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)\n if (value < 0) value = 0xff + value + 1\n this[offset] = (value & 0xff)\n return offset + 1\n}\n\nBuffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {\n value = +value\n offset = offset >>> 0\n if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)\n this[offset] = (value & 0xff)\n this[offset + 1] = (value >>> 8)\n return offset + 2\n}\n\nBuffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {\n value = +value\n offset = offset >>> 0\n if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)\n this[offset] = (value >>> 8)\n this[offset + 1] = (value & 0xff)\n return offset + 2\n}\n\nBuffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {\n value = +value\n offset = offset >>> 0\n if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)\n this[offset] = (value & 0xff)\n this[offset + 1] = (value >>> 8)\n this[offset + 2] = (value >>> 16)\n this[offset + 3] = (value >>> 24)\n return offset + 4\n}\n\nBuffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {\n value = +value\n offset = offset >>> 0\n if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)\n if (value < 0) value = 0xffffffff + value + 1\n this[offset] = (value >>> 24)\n this[offset + 1] = (value >>> 16)\n this[offset + 2] = (value >>> 8)\n this[offset + 3] = (value & 0xff)\n return offset + 4\n}\n\nfunction checkIEEE754 (buf, value, offset, ext, max, min) {\n if (offset + ext > buf.length) throw new RangeError('Index out of range')\n if (offset < 0) throw new RangeError('Index out of range')\n}\n\nfunction writeFloat (buf, value, offset, littleEndian, noAssert) {\n value = +value\n offset = offset >>> 0\n if (!noAssert) {\n checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)\n }\n ieee754.write(buf, value, offset, littleEndian, 23, 4)\n return offset + 4\n}\n\nBuffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {\n return writeFloat(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {\n return writeFloat(this, value, offset, false, noAssert)\n}\n\nfunction writeDouble (buf, value, offset, littleEndian, noAssert) {\n value = +value\n offset = offset >>> 0\n if (!noAssert) {\n checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)\n }\n ieee754.write(buf, value, offset, littleEndian, 52, 8)\n return offset + 8\n}\n\nBuffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {\n return writeDouble(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {\n return writeDouble(this, value, offset, false, noAssert)\n}\n\n// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)\nBuffer.prototype.copy = function copy (target, targetStart, start, end) {\n if (!start) start = 0\n if (!end && end !== 0) end = this.length\n if (targetStart >= target.length) targetStart = target.length\n if (!targetStart) targetStart = 0\n if (end > 0 && end < start) end = start\n\n // Copy 0 bytes; we're done\n if (end === start) return 0\n if (target.length === 0 || this.length === 0) return 0\n\n // Fatal error conditions\n if (targetStart < 0) {\n throw new RangeError('targetStart out of bounds')\n }\n if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')\n if (end < 0) throw new RangeError('sourceEnd out of bounds')\n\n // Are we oob?\n if (end > this.length) end = this.length\n if (target.length - targetStart < end - start) {\n end = target.length - targetStart + start\n }\n\n var len = end - start\n var i\n\n if (this === target && start < targetStart && targetStart < end) {\n // descending copy from end\n for (i = len - 1; i >= 0; --i) {\n target[i + targetStart] = this[i + start]\n }\n } else if (len < 1000) {\n // ascending copy from start\n for (i = 0; i < len; ++i) {\n target[i + targetStart] = this[i + start]\n }\n } else {\n Uint8Array.prototype.set.call(\n target,\n this.subarray(start, start + len),\n targetStart\n )\n }\n\n return len\n}\n\n// Usage:\n// buffer.fill(number[, offset[, end]])\n// buffer.fill(buffer[, offset[, end]])\n// buffer.fill(string[, offset[, end]][, encoding])\nBuffer.prototype.fill = function fill (val, start, end, encoding) {\n // Handle string cases:\n if (typeof val === 'string') {\n if (typeof start === 'string') {\n encoding = start\n start = 0\n end = this.length\n } else if (typeof end === 'string') {\n encoding = end\n end = this.length\n }\n if (val.length === 1) {\n var code = val.charCodeAt(0)\n if (code < 256) {\n val = code\n }\n }\n if (encoding !== undefined && typeof encoding !== 'string') {\n throw new TypeError('encoding must be a string')\n }\n if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {\n throw new TypeError('Unknown encoding: ' + encoding)\n }\n } else if (typeof val === 'number') {\n val = val & 255\n }\n\n // Invalid ranges are not set to a default, so can range check early.\n if (start < 0 || this.length < start || this.length < end) {\n throw new RangeError('Out of range index')\n }\n\n if (end <= start) {\n return this\n }\n\n start = start >>> 0\n end = end === undefined ? this.length : end >>> 0\n\n if (!val) val = 0\n\n var i\n if (typeof val === 'number') {\n for (i = start; i < end; ++i) {\n this[i] = val\n }\n } else {\n var bytes = Buffer.isBuffer(val)\n ? val\n : new Buffer(val, encoding)\n var len = bytes.length\n for (i = 0; i < end - start; ++i) {\n this[i + start] = bytes[i % len]\n }\n }\n\n return this\n}\n\n// HELPER FUNCTIONS\n// ================\n\nvar INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g\n\nfunction base64clean (str) {\n // Node strips out invalid characters like \\n and \\t from the string, base64-js does not\n str = str.trim().replace(INVALID_BASE64_RE, '')\n // Node converts strings with length < 2 to ''\n if (str.length < 2) return ''\n // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not\n while (str.length % 4 !== 0) {\n str = str + '='\n }\n return str\n}\n\nfunction toHex (n) {\n if (n < 16) return '0' + n.toString(16)\n return n.toString(16)\n}\n\nfunction utf8ToBytes (string, units) {\n units = units || Infinity\n var codePoint\n var length = string.length\n var leadSurrogate = null\n var bytes = []\n\n for (var i = 0; i < length; ++i) {\n codePoint = string.charCodeAt(i)\n\n // is surrogate component\n if (codePoint > 0xD7FF && codePoint < 0xE000) {\n // last char was a lead\n if (!leadSurrogate) {\n // no lead yet\n if (codePoint > 0xDBFF) {\n // unexpected trail\n if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n continue\n } else if (i + 1 === length) {\n // unpaired lead\n if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n continue\n }\n\n // valid lead\n leadSurrogate = codePoint\n\n continue\n }\n\n // 2 leads in a row\n if (codePoint < 0xDC00) {\n if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n leadSurrogate = codePoint\n continue\n }\n\n // valid surrogate pair\n codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000\n } else if (leadSurrogate) {\n // valid bmp char, but last char was a lead\n if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n }\n\n leadSurrogate = null\n\n // encode utf8\n if (codePoint < 0x80) {\n if ((units -= 1) < 0) break\n bytes.push(codePoint)\n } else if (codePoint < 0x800) {\n if ((units -= 2) < 0) break\n bytes.push(\n codePoint >> 0x6 | 0xC0,\n codePoint & 0x3F | 0x80\n )\n } else if (codePoint < 0x10000) {\n if ((units -= 3) < 0) break\n bytes.push(\n codePoint >> 0xC | 0xE0,\n codePoint >> 0x6 & 0x3F | 0x80,\n codePoint & 0x3F | 0x80\n )\n } else if (codePoint < 0x110000) {\n if ((units -= 4) < 0) break\n bytes.push(\n codePoint >> 0x12 | 0xF0,\n codePoint >> 0xC & 0x3F | 0x80,\n codePoint >> 0x6 & 0x3F | 0x80,\n codePoint & 0x3F | 0x80\n )\n } else {\n throw new Error('Invalid code point')\n }\n }\n\n return bytes\n}\n\nfunction asciiToBytes (str) {\n var byteArray = []\n for (var i = 0; i < str.length; ++i) {\n // Node's code seems to be doing this and not & 0x7F..\n byteArray.push(str.charCodeAt(i) & 0xFF)\n }\n return byteArray\n}\n\nfunction utf16leToBytes (str, units) {\n var c, hi, lo\n var byteArray = []\n for (var i = 0; i < str.length; ++i) {\n if ((units -= 2) < 0) break\n\n c = str.charCodeAt(i)\n hi = c >> 8\n lo = c % 256\n byteArray.push(lo)\n byteArray.push(hi)\n }\n\n return byteArray\n}\n\nfunction base64ToBytes (str) {\n return base64.toByteArray(base64clean(str))\n}\n\nfunction blitBuffer (src, dst, offset, length) {\n for (var i = 0; i < length; ++i) {\n if ((i + offset >= dst.length) || (i >= src.length)) break\n dst[i + offset] = src[i]\n }\n return i\n}\n\n// Node 0.10 supports `ArrayBuffer` but lacks `ArrayBuffer.isView`\nfunction isArrayBufferView (obj) {\n return (typeof ArrayBuffer.isView === 'function') && ArrayBuffer.isView(obj)\n}\n\nfunction numberIsNaN (obj) {\n return obj !== obj // eslint-disable-line no-self-compare\n}\n","exports.read = function (buffer, offset, isLE, mLen, nBytes) {\n var e, m\n var eLen = nBytes * 8 - mLen - 1\n var eMax = (1 << eLen) - 1\n var eBias = eMax >> 1\n var nBits = -7\n var i = isLE ? (nBytes - 1) : 0\n var d = isLE ? -1 : 1\n var s = buffer[offset + i]\n\n i += d\n\n e = s & ((1 << (-nBits)) - 1)\n s >>= (-nBits)\n nBits += eLen\n for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}\n\n m = e & ((1 << (-nBits)) - 1)\n e >>= (-nBits)\n nBits += mLen\n for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}\n\n if (e === 0) {\n e = 1 - eBias\n } else if (e === eMax) {\n return m ? NaN : ((s ? -1 : 1) * Infinity)\n } else {\n m = m + Math.pow(2, mLen)\n e = e - eBias\n }\n return (s ? -1 : 1) * m * Math.pow(2, e - mLen)\n}\n\nexports.write = function (buffer, value, offset, isLE, mLen, nBytes) {\n var e, m, c\n var eLen = nBytes * 8 - mLen - 1\n var eMax = (1 << eLen) - 1\n var eBias = eMax >> 1\n var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)\n var i = isLE ? 0 : (nBytes - 1)\n var d = isLE ? 1 : -1\n var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0\n\n value = Math.abs(value)\n\n if (isNaN(value) || value === Infinity) {\n m = isNaN(value) ? 1 : 0\n e = eMax\n } else {\n e = Math.floor(Math.log(value) / Math.LN2)\n if (value * (c = Math.pow(2, -e)) < 1) {\n e--\n c *= 2\n }\n if (e + eBias >= 1) {\n value += rt / c\n } else {\n value += rt * Math.pow(2, 1 - eBias)\n }\n if (value * c >= 2) {\n e++\n c /= 2\n }\n\n if (e + eBias >= eMax) {\n m = 0\n e = eMax\n } else if (e + eBias >= 1) {\n m = (value * c - 1) * Math.pow(2, mLen)\n e = e + eBias\n } else {\n m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)\n e = 0\n }\n }\n\n for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}\n\n e = (e << mLen) | m\n eLen += mLen\n for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}\n\n buffer[offset + i - d] |= s * 128\n}\n","/*\n GIFEncoder.js\n\n Authors\n Kevin Weiner (original Java version - kweiner@fmsware.com)\n Thibault Imbert (AS3 version - bytearray.org)\n Johan Nordberg (JS version - code@johan-nordberg.com)\n*/\n\nvar NeuQuant = require('./WasmNeuQuant.js');\nvar LZWEncoder = require('./LZWEncoder.js');\n\nfunction ByteArray() {\n this.page = -1;\n this.pages = [];\n this.newPage();\n}\n\nByteArray.pageSize = 4096;\nByteArray.charMap = {};\n\nfor (var i = 0; i < 256; i++)\n ByteArray.charMap[i] = String.fromCharCode(i);\n\nByteArray.prototype.newPage = function() {\n this.pages[++this.page] = new Uint8Array(ByteArray.pageSize);\n this.cursor = 0;\n};\n\nByteArray.prototype.getData = function() {\n var rv = '';\n for (var p = 0; p < this.pages.length; p++) {\n for (var i = 0; i < ByteArray.pageSize; i++) {\n rv += ByteArray.charMap[this.pages[p][i]];\n }\n }\n return rv;\n};\n\nByteArray.prototype.writeByte = function(val) {\n if (this.cursor >= ByteArray.pageSize) this.newPage();\n this.pages[this.page][this.cursor++] = val;\n};\n\nByteArray.prototype.writeUTFBytes = function(string) {\n for (var l = string.length, i = 0; i < l; i++)\n this.writeByte(string.charCodeAt(i));\n};\n\nByteArray.prototype.writeBytes = function(array, offset, length) {\n for (var l = length || array.length, i = offset || 0; i < l; i++)\n this.writeByte(array[i]);\n};\n\nfunction GIFEncoder(width, height) {\n // image size\n this.width = ~~width;\n this.height = ~~height;\n\n // transparent color if given\n this.transparent = null;\n\n // transparent index in color table\n this.transIndex = 0;\n\n // -1 = no repeat, 0 = forever. anything else is repeat count\n this.repeat = -1;\n\n // frame delay (hundredths)\n this.delay = 0;\n\n this.image = null; // current frame\n this.pixels = null; // BGR byte array from frame\n this.indexedPixels = null; // converted frame indexed to palette\n this.colorDepth = null; // number of bit planes\n this.colorTab = null; // RGB palette\n this.neuQuant = null; // NeuQuant instance that was used to generate this.colorTab.\n this.usedEntry = new Array(); // active palette entries\n this.palSize = 7; // color table size (bits-1)\n this.dispose = -1; // disposal code (-1 = use default)\n this.firstFrame = true;\n this.sample = 10; // default sample interval for quantizer\n this.dither = false; // default dithering\n this.globalPalette = false;\n\n this.out = new ByteArray();\n}\n\n/*\n Sets the delay time between each frame, or changes it for subsequent frames\n (applies to last frame added)\n*/\nGIFEncoder.prototype.setDelay = function(milliseconds) {\n this.delay = Math.round(milliseconds / 10);\n};\n\n/*\n Sets frame rate in frames per second.\n*/\nGIFEncoder.prototype.setFrameRate = function(fps) {\n this.delay = Math.round(100 / fps);\n};\n\n/*\n Sets the GIF frame disposal code for the last added frame and any\n subsequent frames.\n\n Default is 0 if no transparent color has been set, otherwise 2.\n*/\nGIFEncoder.prototype.setDispose = function(disposalCode) {\n if (disposalCode >= 0) this.dispose = disposalCode;\n};\n\n/*\n Sets the number of times the set of GIF frames should be played.\n\n -1 = play once\n 0 = repeat indefinitely\n\n Default is -1\n\n Must be invoked before the first image is added\n*/\n\nGIFEncoder.prototype.setRepeat = function(repeat) {\n this.repeat = repeat;\n};\n\n/*\n Sets the transparent color for the last added frame and any subsequent\n frames. Since all colors are subject to modification in the quantization\n process, the color in the final palette for each frame closest to the given\n color becomes the transparent color for that frame. May be set to null to\n indicate no transparent color.\n*/\nGIFEncoder.prototype.setTransparent = function(color) {\n this.transparent = color;\n};\n\n/*\n Adds next GIF frame. The frame is not written immediately, but is\n actually deferred until the next frame is received so that timing\n data can be inserted. Invoking finish() flushes all frames.\n*/\nGIFEncoder.prototype.addFrame = function(imageData) {\n this.image = imageData;\n\n this.colorTab = this.globalPalette && this.globalPalette.slice ? this.globalPalette : null;\n\n this.getImagePixels(); // convert to correct format if necessary\n this.analyzePixels(); // build color table & map pixels\n\n if (this.globalPalette === true) this.globalPalette = this.colorTab;\n\n if (this.firstFrame) {\n this.writeLSD(); // logical screen descriptior\n this.writePalette(); // global color table\n if (this.repeat >= 0) {\n // use NS app extension to indicate reps\n this.writeNetscapeExt();\n }\n }\n\n this.writeGraphicCtrlExt(); // write graphic control extension\n this.writeImageDesc(); // image descriptor\n if (!this.firstFrame && !this.globalPalette) this.writePalette(); // local color table\n this.writePixels(); // encode and write pixel data\n\n this.firstFrame = false;\n};\n\n/*\n Adds final trailer to the GIF stream, if you don't call the finish method\n the GIF stream will not be valid.\n*/\nGIFEncoder.prototype.finish = function() {\n this.out.writeByte(0x3b); // gif trailer\n};\n\n/*\n Sets quality of color quantization (conversion of images to the maximum 256\n colors allowed by the GIF specification). Lower values (minimum = 1)\n produce better colors, but slow processing significantly. 10 is the\n default, and produces good color mapping at reasonable speeds. Values\n greater than 20 do not yield significant improvements in speed.\n*/\nGIFEncoder.prototype.setQuality = function(quality) {\n if (quality < 1) quality = 1;\n this.sample = quality;\n};\n\n/*\n Sets dithering method. Available are:\n - FALSE no dithering\n - TRUE or FloydSteinberg\n - FalseFloydSteinberg\n - Stucki\n - Atkinson\n You can add '-serpentine' to use serpentine scanning\n*/\nGIFEncoder.prototype.setDither = function(dither) {\n if (dither === true) dither = 'FloydSteinberg';\n this.dither = dither;\n};\n\n/*\n Sets global palette for all frames.\n You can provide TRUE to create global palette from first picture.\n Or an array of r,g,b,r,g,b,...\n*/\nGIFEncoder.prototype.setGlobalPalette = function(palette) {\n this.globalPalette = palette;\n};\n\n/*\n Returns global palette used for all frames.\n If setGlobalPalette(true) was used, then this function will return\n calculated palette after the first frame is added.\n*/\nGIFEncoder.prototype.getGlobalPalette = function() {\n return (this.globalPalette && this.globalPalette.slice && this.globalPalette.slice(0)) || this.globalPalette;\n};\n\n/*\n Writes GIF file header\n*/\nGIFEncoder.prototype.writeHeader = function() {\n this.out.writeUTFBytes(\"GIF89a\");\n};\n\n/*\n Analyzes current frame colors and creates color map.\n*/\nGIFEncoder.prototype.analyzePixels = function() {\n if (!this.colorTab) {\n this.neuQuant = new NeuQuant(this.pixels, this.sample);\n this.neuQuant.buildColormap(); // create reduced palette\n this.colorTab = this.neuQuant.getColormap();\n }\n\n // map image pixels to new palette\n if (this.dither) {\n this.ditherPixels(this.dither.replace('-serpentine', ''), this.dither.match(/-serpentine/) !== null);\n } else {\n this.indexPixels();\n }\n\n this.pixels = null;\n this.colorDepth = 8;\n this.palSize = 7;\n\n // get closest match to transparent color if specified\n if (this.transparent !== null) {\n this.transIndex = this.findClosest(this.transparent, true);\n }\n};\n\n/*\n Index pixels, without dithering\n*/\nGIFEncoder.prototype.indexPixels = function(imgq) {\n var nPix = this.pixels.length / 3;\n this.indexedPixels = new Uint8Array(nPix);\n var k = 0;\n for (var j = 0; j < nPix; j++) {\n var index = this.findClosestRGB(\n this.pixels[k++] & 0xff,\n this.pixels[k++] & 0xff,\n this.pixels[k++] & 0xff\n );\n this.usedEntry[index] = true;\n this.indexedPixels[j] = index;\n }\n};\n\n/*\n Taken from http://jsbin.com/iXofIji/2/edit by PAEz\n*/\nGIFEncoder.prototype.ditherPixels = function(kernel, serpentine) {\n var kernels = {\n FalseFloydSteinberg: [\n [3 / 8, 1, 0],\n [3 / 8, 0, 1],\n [2 / 8, 1, 1]\n ],\n FloydSteinberg: [\n [7 / 16, 1, 0],\n [3 / 16, -1, 1],\n [5 / 16, 0, 1],\n [1 / 16, 1, 1]\n ],\n Stucki: [\n [8 / 42, 1, 0],\n [4 / 42, 2, 0],\n [2 / 42, -2, 1],\n [4 / 42, -1, 1],\n [8 / 42, 0, 1],\n [4 / 42, 1, 1],\n [2 / 42, 2, 1],\n [1 / 42, -2, 2],\n [2 / 42, -1, 2],\n [4 / 42, 0, 2],\n [2 / 42, 1, 2],\n [1 / 42, 2, 2]\n ],\n Atkinson: [\n [1 / 8, 1, 0],\n [1 / 8, 2, 0],\n [1 / 8, -1, 1],\n [1 / 8, 0, 1],\n [1 / 8, 1, 1],\n [1 / 8, 0, 2]\n ]\n };\n\n if (!kernel || !kernels[kernel]) {\n throw 'Unknown dithering kernel: ' + kernel;\n }\n\n var ds = kernels[kernel];\n var index = 0,\n height = this.height,\n width = this.width,\n data = this.pixels;\n var direction = serpentine ? -1 : 1;\n\n this.indexedPixels = new Uint8Array(this.pixels.length / 3);\n\n for (var y = 0; y < height; y++) {\n\n if (serpentine) direction = direction * -1;\n\n for (var x = (direction == 1 ? 0 : width - 1), xend = (direction == 1 ? width : 0); x !== xend; x += direction) {\n\n index = (y * width) + x;\n // Get original colour\n var idx = index * 3;\n var r1 = data[idx];\n var g1 = data[idx + 1];\n var b1 = data[idx + 2];\n\n // Get converted colour\n idx = this.findClosestRGB(r1, g1, b1);\n this.usedEntry[idx] = true;\n this.indexedPixels[index] = idx;\n idx *= 3;\n var r2 = this.colorTab[idx];\n var g2 = this.colorTab[idx + 1];\n var b2 = this.colorTab[idx + 2];\n\n var er = r1 - r2;\n var eg = g1 - g2;\n var eb = b1 - b2;\n\n for (var i = (direction == 1 ? 0: ds.length - 1), end = (direction == 1 ? ds.length : 0); i !== end; i += direction) {\n var x1 = ds[i][1]; // *direction; // Should this by timesd by direction?..to make the kernel go in the opposite direction....got no idea....\n var y1 = ds[i][2];\n if (x1 + x >= 0 && x1 + x < width && y1 + y >= 0 && y1 + y < height) {\n var d = ds[i][0];\n idx = index + x1 + (y1 * width);\n idx *= 3;\n\n data[idx] = Math.max(0, Math.min(255, data[idx] + er * d));\n data[idx + 1] = Math.max(0, Math.min(255, data[idx + 1] + eg * d));\n data[idx + 2] = Math.max(0, Math.min(255, data[idx + 2] + eb * d));\n }\n }\n }\n }\n};\n\n/*\n Returns index of palette color closest to c\n*/\nGIFEncoder.prototype.findClosest = function(c, used) {\n return this.findClosestRGB((c & 0xFF0000) >> 16, (c & 0x00FF00) >> 8, (c & 0x0000FF), used);\n};\n\nGIFEncoder.prototype.findClosestRGB = function(r, g, b, used) {\n if (this.colorTab === null) return -1;\n\n if (this.neuQuant && !used) {\n return this.neuQuant.lookupRGB(r, g, b);\n }\n\n var c = b | (g << 8) | (r << 16);\n\n var minpos = 0;\n var dmin = 256 * 256 * 256;\n var len = this.colorTab.length;\n\n for (var i = 0, index = 0; i < len; index++) {\n var dr = r - (this.colorTab[i++] & 0xff);\n var dg = g - (this.colorTab[i++] & 0xff);\n var db = b - (this.colorTab[i++] & 0xff);\n var d = dr * dr + dg * dg + db * db;\n if ((!used || this.usedEntry[index]) && (d < dmin)) {\n dmin = d;\n minpos = index;\n }\n }\n\n return minpos;\n};\n\n/*\n Extracts image pixels into byte array pixels\n (removes alphachannel from canvas imagedata)\n*/\nGIFEncoder.prototype.getImagePixels = function() {\n var w = this.width;\n var h = this.height;\n this.pixels = new Uint8Array(w * h * 3);\n\n var data = this.image;\n var srcPos = 0;\n var count = 0;\n\n for (var i = 0; i < h; i++) {\n for (var j = 0; j < w; j++) {\n this.pixels[count++] = data[srcPos++];\n this.pixels[count++] = data[srcPos++];\n this.pixels[count++] = data[srcPos++];\n srcPos++;\n }\n }\n};\n\n/*\n Writes Graphic Control Extension\n*/\nGIFEncoder.prototype.writeGraphicCtrlExt = function() {\n this.out.writeByte(0x21); // extension introducer\n this.out.writeByte(0xf9); // GCE label\n this.out.writeByte(4); // data block size\n\n var transp, disp;\n if (this.transparent === null) {\n transp = 0;\n disp = 0; // dispose = no action\n } else {\n transp = 1;\n disp = 2; // force clear if using transparent color\n }\n\n if (this.dispose >= 0) {\n disp = this.dispose & 7; // user override\n }\n disp <<= 2;\n\n // packed fields\n this.out.writeByte(\n 0 | // 1:3 reserved\n disp | // 4:6 disposal\n 0 | // 7 user input - 0 = none\n transp // 8 transparency flag\n );\n\n this.writeShort(this.delay); // delay x 1/100 sec\n this.out.writeByte(this.transIndex); // transparent color index\n this.out.writeByte(0); // block terminator\n};\n\n/*\n Writes Image Descriptor\n*/\nGIFEncoder.prototype.writeImageDesc = function() {\n this.out.writeByte(0x2c); // image separator\n this.writeShort(0); // image position x,y = 0,0\n this.writeShort(0);\n this.writeShort(this.width); // image size\n this.writeShort(this.height);\n\n // packed fields\n if (this.firstFrame || this.globalPalette) {\n // no LCT - GCT is used for first (or only) frame\n this.out.writeByte(0);\n } else {\n // specify normal LCT\n this.out.writeByte(\n 0x80 | // 1 local color table 1=yes\n 0 | // 2 interlace - 0=no\n 0 | // 3 sorted - 0=no\n 0 | // 4-5 reserved\n this.palSize // 6-8 size of color table\n );\n }\n};\n\n/*\n Writes Logical Screen Descriptor\n*/\nGIFEncoder.prototype.writeLSD = function() {\n // logical screen size\n this.writeShort(this.width);\n this.writeShort(this.height);\n\n // packed fields\n this.out.writeByte(\n 0x80 | // 1 : global color table flag = 1 (gct used)\n 0x70 | // 2-4 : color resolution = 7\n 0x00 | // 5 : gct sort flag = 0\n this.palSize // 6-8 : gct size\n );\n\n this.out.writeByte(0); // background color index\n this.out.writeByte(0); // pixel aspect ratio - assume 1:1\n};\n\n/*\n Writes Netscape application extension to define repeat count.\n*/\nGIFEncoder.prototype.writeNetscapeExt = function() {\n this.out.writeByte(0x21); // extension introducer\n this.out.writeByte(0xff); // app extension label\n this.out.writeByte(11); // block size\n this.out.writeUTFBytes('NETSCAPE2.0'); // app id + auth code\n this.out.writeByte(3); // sub-block size\n this.out.writeByte(1); // loop sub-block id\n this.writeShort(this.repeat); // loop count (extra iterations, 0=repeat forever)\n this.out.writeByte(0); // block terminator\n};\n\n/*\n Writes color table\n*/\nGIFEncoder.prototype.writePalette = function() {\n this.out.writeBytes(this.colorTab);\n var n = (3 * 256) - this.colorTab.length;\n for (var i = 0; i < n; i++)\n this.out.writeByte(0);\n};\n\nGIFEncoder.prototype.writeShort = function(pValue) {\n this.out.writeByte(pValue & 0xFF);\n this.out.writeByte((pValue >> 8) & 0xFF);\n};\n\n/*\n Encodes and writes pixel data\n*/\nGIFEncoder.prototype.writePixels = function() {\n var enc = new LZWEncoder(this.width, this.height, this.indexedPixels, this.colorDepth);\n enc.encode(this.out);\n};\n\n/*\n Retrieves the GIF stream\n*/\nGIFEncoder.prototype.stream = function() {\n return this.out;\n};\n\nmodule.exports = GIFEncoder;\n","/*\n LZWEncoder.js\n\n Authors\n Kevin Weiner (original Java version - kweiner@fmsware.com)\n Thibault Imbert (AS3 version - bytearray.org)\n Johan Nordberg (JS version - code@johan-nordberg.com)\n\n Acknowledgements\n GIFCOMPR.C - GIF Image compression routines\n Lempel-Ziv compression based on 'compress'. GIF modifications by\n David Rowley (mgardi@watdcsu.waterloo.edu)\n GIF Image compression - modified 'compress'\n Based on: compress.c - File compression ala IEEE Computer, June 1984.\n By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)\n Jim McKie (decvax!mcvax!jim)\n Steve Davies (decvax!vax135!petsd!peora!srd)\n Ken Turkowski (decvax!decwrl!turtlevax!ken)\n James A. Woods (decvax!ihnp4!ames!jaw)\n Joe Orost (decvax!vax135!petsd!joe)\n*/\n\nvar EOF = -1;\nvar BITS = 12;\nvar HSIZE = 5003; // 80% occupancy\nvar masks = [0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F,\n 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF,\n 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF];\n\nfunction LZWEncoder(width, height, pixels, colorDepth) {\n var initCodeSize = Math.max(2, colorDepth);\n\n var accum = new Uint8Array(256);\n var htab = new Int32Array(HSIZE);\n var codetab = new Int32Array(HSIZE);\n\n var cur_accum, cur_bits = 0;\n var a_count;\n var free_ent = 0; // first unused entry\n var maxcode;\n\n // block compression parameters -- after all codes are used up,\n // and compression rate changes, start over.\n var clear_flg = false;\n\n // Algorithm: use open addressing double hashing (no chaining) on the\n // prefix code / next character combination. We do a variant of Knuth's\n // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime\n // secondary probe. Here, the modular division first probe is gives way\n // to a faster exclusive-or manipulation. Also do block compression with\n // an adaptive reset, whereby the code table is cleared when the compression\n // ratio decreases, but after the table fills. The variable-length output\n // codes are re-sized at this point, and a special CLEAR code is generated\n // for the decompressor. Late addition: construct the table according to\n // file size for noticeable speed improvement on small files. Please direct\n // questions about this implementation to ames!jaw.\n var g_init_bits, ClearCode, EOFCode;\n\n // Add a character to the end of the current packet, and if it is 254\n // characters, flush the packet to disk.\n function char_out(c, outs) {\n accum[a_count++] = c;\n if (a_count >= 254) flush_char(outs);\n }\n\n // Clear out the hash table\n // table clear for block compress\n function cl_block(outs) {\n cl_hash(HSIZE);\n free_ent = ClearCode + 2;\n clear_flg = true;\n output(ClearCode, outs);\n }\n\n // Reset code table\n function cl_hash(hsize) {\n for (var i = 0; i < hsize; ++i) htab[i] = -1;\n }\n\n function compress(init_bits, outs) {\n var fcode, c, i, ent, disp, hsize_reg, hshift;\n\n // Set up the globals: g_init_bits - initial number of bits\n g_init_bits = init_bits;\n\n // Set up the necessary values\n clear_flg = false;\n n_bits = g_init_bits;\n maxcode = MAXCODE(n_bits);\n\n ClearCode = 1 << (init_bits - 1);\n EOFCode = ClearCode + 1;\n free_ent = ClearCode + 2;\n\n a_count = 0; // clear packet\n\n ent = nextPixel();\n\n hshift = 0;\n for (fcode = HSIZE; fcode < 65536; fcode *= 2) ++hshift;\n hshift = 8 - hshift; // set hash code range bound\n hsize_reg = HSIZE;\n cl_hash(hsize_reg); // clear hash table\n\n output(ClearCode, outs);\n\n outer_loop: while ((c = nextPixel()) != EOF) {\n fcode = (c << BITS) + ent;\n i = (c << hshift) ^ ent; // xor hashing\n if (htab[i] === fcode) {\n ent = codetab[i];\n continue;\n } else if (htab[i] >= 0) { // non-empty slot\n disp = hsize_reg - i; // secondary hash (after G. Knott)\n if (i === 0) disp = 1;\n do {\n if ((i -= disp) < 0) i += hsize_reg;\n if (htab[i] === fcode) {\n ent = codetab[i];\n continue outer_loop;\n }\n } while (htab[i] >= 0);\n }\n output(ent, outs);\n ent = c;\n if (free_ent < 1 << BITS) {\n codetab[i] = free_ent++; // code -> hashtable\n htab[i] = fcode;\n } else {\n cl_block(outs);\n }\n }\n\n // Put out the final code.\n output(ent, outs);\n output(EOFCode, outs);\n }\n\n function encode(outs) {\n outs.writeByte(initCodeSize); // write \"initial code size\" byte\n remaining = width * height; // reset navigation variables\n curPixel = 0;\n compress(initCodeSize + 1, outs); // compress and write the pixel data\n outs.writeByte(0); // write block terminator\n }\n\n // Flush the packet to disk, and reset the accumulator\n function flush_char(outs) {\n if (a_count > 0) {\n outs.writeByte(a_count);\n outs.writeBytes(accum, 0, a_count);\n a_count = 0;\n }\n }\n\n function MAXCODE(n_bits) {\n return (1 << n_bits) - 1;\n }\n\n // Return the next pixel from the image\n function nextPixel() {\n if (remaining === 0) return EOF;\n --remaining;\n var pix = pixels[curPixel++];\n return pix & 0xff;\n }\n\n function output(code, outs) {\n cur_accum &= masks[cur_bits];\n\n if (cur_bits > 0) cur_accum |= (code << cur_bits);\n else cur_accum = code;\n\n cur_bits += n_bits;\n\n while (cur_bits >= 8) {\n char_out((cur_accum & 0xff), outs);\n cur_accum >>= 8;\n cur_bits -= 8;\n }\n\n // If the next entry is going to be too big for the code size,\n // then increase it, if possible.\n if (free_ent > maxcode || clear_flg) {\n if (clear_flg) {\n maxcode = MAXCODE(n_bits = g_init_bits);\n clear_flg = false;\n } else {\n ++n_bits;\n if (n_bits == BITS) maxcode = 1 << BITS;\n else maxcode = MAXCODE(n_bits);\n }\n }\n\n if (code == EOFCode) {\n // At EOF, write the rest of the buffer.\n while (cur_bits > 0) {\n char_out((cur_accum & 0xff), outs);\n cur_accum >>= 8;\n cur_bits -= 8;\n }\n flush_char(outs);\n }\n }\n\n this.encode = encode;\n}\n\nmodule.exports = LZWEncoder;\n","\n\n// this is an ugly hack since i don't want to\n// refactor the worker for async loads just yet\nvar src = Buffer(\"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\",\"base64\")\nvar wamodule = new WebAssembly.Module(src)\nvar instance\nvar memarray\n\nfunction NeuQuant(pixels, samplefac) {\n if (!instance) {\n var table = new WebAssembly.Table({initial: 0, element: 'anyfunc'})\n var memory = new WebAssembly.Memory({initial: 1})\n memarray = new Uint8Array(memory.buffer)\n\n var env = {}\n env.memoryBase = 0\n env.memory = memory\n env.tableBase = 0\n env.table = table\n\n env.memset = function(){} // instance complains about it missing\n // when compiled with optimizations,\n // seems not to have any effect?\n\n env._grow = function() { memarray = new Uint8Array(memory.buffer) }\n env._abort = function() { throw new Error('Abort') }\n env._exit = function() { throw new Error('Exit') }\n instance = new WebAssembly.Instance(wamodule, {env: env})\n }\n\n var pixelPtr = instance.exports.malloc(pixels.byteLength)\n memarray.set(pixels, pixelPtr)\n\n instance.exports.init(pixelPtr, pixels.length, samplefac)\n\n this.buildColormap = function(){\n instance.exports.learn()\n instance.exports.unbiasnet()\n instance.exports.inxbuild()\n instance.exports.free(pixelPtr)\n }\n\n this.getColormap = function(){\n var map = new Uint8Array(256*3)\n var mapPtr = instance.exports.getColormap()\n map.set(memarray.subarray(mapPtr, mapPtr + map.byteLength))\n return map\n }\n\n this.lookupRGB = instance.exports.inxsearch\n}\n\nmodule.exports = NeuQuant\n","GIFEncoder = require './GIFEncoder.js'\n\nrenderFrame = (frame) ->\n encoder = new GIFEncoder frame.width, frame.height\n\n if frame.index is 0\n encoder.writeHeader()\n else\n encoder.firstFrame = false\n\n encoder.setTransparent frame.transparent\n encoder.setDispose frame.dispose\n encoder.setRepeat frame.repeat\n encoder.setDelay frame.delay\n encoder.setQuality frame.quality\n encoder.setDither frame.dither\n encoder.setGlobalPalette frame.globalPalette\n encoder.addFrame frame.data\n encoder.finish() if frame.last\n if frame.globalPalette == true\n frame.globalPalette = encoder.getGlobalPalette()\n\n stream = encoder.stream()\n frame.data = stream.pages\n frame.cursor = stream.cursor\n frame.pageSize = stream.constructor.pageSize\n\n if frame.canTransfer\n transfer = (page.buffer for page in frame.data)\n self.postMessage frame, transfer\n else\n self.postMessage frame\n\nself.onmessage = (event) -> renderFrame event.data\n"]} \ No newline at end of file diff --git a/submodules/gif.js/gif.worker.js b/submodules/gif.js/gif.worker.js new file mode 100644 index 0000000..269624e --- /dev/null +++ b/submodules/gif.js/gif.worker.js @@ -0,0 +1,3 @@ +// gif.worker.js 0.2.0 - https://github.com/jnordberg/gif.js +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o=ByteArray.pageSize)this.newPage();this.pages[this.page][this.cursor++]=val};ByteArray.prototype.writeUTFBytes=function(string){for(var l=string.length,i=0;i=0)this.dispose=disposalCode};GIFEncoder.prototype.setRepeat=function(repeat){this.repeat=repeat};GIFEncoder.prototype.setTransparent=function(color){this.transparent=color};GIFEncoder.prototype.addFrame=function(imageData){this.image=imageData;this.colorTab=this.globalPalette&&this.globalPalette.slice?this.globalPalette:null;this.getImagePixels();this.analyzePixels();if(this.globalPalette===true)this.globalPalette=this.colorTab;if(this.firstFrame){this.writeLSD();this.writePalette();if(this.repeat>=0){this.writeNetscapeExt()}}this.writeGraphicCtrlExt();this.writeImageDesc();if(!this.firstFrame&&!this.globalPalette)this.writePalette();this.writePixels();this.firstFrame=false};GIFEncoder.prototype.finish=function(){this.out.writeByte(59)};GIFEncoder.prototype.setQuality=function(quality){if(quality<1)quality=1;this.sample=quality};GIFEncoder.prototype.setDither=function(dither){if(dither===true)dither="FloydSteinberg";this.dither=dither};GIFEncoder.prototype.setGlobalPalette=function(palette){this.globalPalette=palette};GIFEncoder.prototype.getGlobalPalette=function(){return this.globalPalette&&this.globalPalette.slice&&this.globalPalette.slice(0)||this.globalPalette};GIFEncoder.prototype.writeHeader=function(){this.out.writeUTFBytes("GIF89a")};GIFEncoder.prototype.analyzePixels=function(){if(!this.colorTab){this.neuQuant=new NeuQuant(this.pixels,this.sample);this.neuQuant.buildColormap();this.colorTab=this.neuQuant.getColormap()}if(this.dither){this.ditherPixels(this.dither.replace("-serpentine",""),this.dither.match(/-serpentine/)!==null)}else{this.indexPixels()}this.pixels=null;this.colorDepth=8;this.palSize=7;if(this.transparent!==null){this.transIndex=this.findClosest(this.transparent,true)}};GIFEncoder.prototype.indexPixels=function(imgq){var nPix=this.pixels.length/3;this.indexedPixels=new Uint8Array(nPix);var k=0;for(var j=0;j=0&&x1+x=0&&y1+y>16,(c&65280)>>8,c&255,used)};GIFEncoder.prototype.findClosestRGB=function(r,g,b,used){if(this.colorTab===null)return-1;if(this.neuQuant&&!used){return this.neuQuant.lookupRGB(r,g,b)}var c=b|g<<8|r<<16;var minpos=0;var dmin=256*256*256;var len=this.colorTab.length;for(var i=0,index=0;i=0){disp=dispose&7}disp<<=2;this.out.writeByte(0|disp|0|transp);this.writeShort(this.delay);this.out.writeByte(this.transIndex);this.out.writeByte(0)};GIFEncoder.prototype.writeImageDesc=function(){this.out.writeByte(44);this.writeShort(0);this.writeShort(0);this.writeShort(this.width);this.writeShort(this.height);if(this.firstFrame||this.globalPalette){this.out.writeByte(0)}else{this.out.writeByte(128|0|0|0|this.palSize)}};GIFEncoder.prototype.writeLSD=function(){this.writeShort(this.width);this.writeShort(this.height);this.out.writeByte(128|112|0|this.palSize);this.out.writeByte(0);this.out.writeByte(0)};GIFEncoder.prototype.writeNetscapeExt=function(){this.out.writeByte(33);this.out.writeByte(255);this.out.writeByte(11);this.out.writeUTFBytes("NETSCAPE2.0");this.out.writeByte(3);this.out.writeByte(1);this.writeShort(this.repeat);this.out.writeByte(0)};GIFEncoder.prototype.writePalette=function(){this.out.writeBytes(this.colorTab);var n=3*256-this.colorTab.length;for(var i=0;i>8&255)};GIFEncoder.prototype.writePixels=function(){var enc=new LZWEncoder(this.width,this.height,this.indexedPixels,this.colorDepth);enc.encode(this.out)};GIFEncoder.prototype.stream=function(){return this.out};module.exports=GIFEncoder},{"./LZWEncoder.js":2,"./TypedNeuQuant.js":3}],2:[function(require,module,exports){var EOF=-1;var BITS=12;var HSIZE=5003;var masks=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535];function LZWEncoder(width,height,pixels,colorDepth){var initCodeSize=Math.max(2,colorDepth);var accum=new Uint8Array(256);var htab=new Int32Array(HSIZE);var codetab=new Int32Array(HSIZE);var cur_accum,cur_bits=0;var a_count;var free_ent=0;var maxcode;var clear_flg=false;var g_init_bits,ClearCode,EOFCode;function char_out(c,outs){accum[a_count++]=c;if(a_count>=254)flush_char(outs)}function cl_block(outs){cl_hash(HSIZE);free_ent=ClearCode+2;clear_flg=true;output(ClearCode,outs)}function cl_hash(hsize){for(var i=0;i=0){disp=hsize_reg-i;if(i===0)disp=1;do{if((i-=disp)<0)i+=hsize_reg;if(htab[i]===fcode){ent=codetab[i];continue outer_loop}}while(htab[i]>=0)}output(ent,outs);ent=c;if(free_ent<1<0){outs.writeByte(a_count);outs.writeBytes(accum,0,a_count);a_count=0}}function MAXCODE(n_bits){return(1<0)cur_accum|=code<=8){char_out(cur_accum&255,outs);cur_accum>>=8;cur_bits-=8}if(free_ent>maxcode||clear_flg){if(clear_flg){maxcode=MAXCODE(n_bits=g_init_bits);clear_flg=false}else{++n_bits;if(n_bits==BITS)maxcode=1<0){char_out(cur_accum&255,outs);cur_accum>>=8;cur_bits-=8}flush_char(outs)}}this.encode=encode}module.exports=LZWEncoder},{}],3:[function(require,module,exports){var ncycles=100;var netsize=256;var maxnetpos=netsize-1;var netbiasshift=4;var intbiasshift=16;var intbias=1<>betashift;var betagamma=intbias<>3;var radiusbiasshift=6;var radiusbias=1<>3);var i,v;for(i=0;i>=netbiasshift;network[i][1]>>=netbiasshift;network[i][2]>>=netbiasshift;network[i][3]=i}}function altersingle(alpha,i,b,g,r){network[i][0]-=alpha*(network[i][0]-b)/initalpha;network[i][1]-=alpha*(network[i][1]-g)/initalpha;network[i][2]-=alpha*(network[i][2]-r)/initalpha}function alterneigh(radius,i,b,g,r){var lo=Math.abs(i-radius);var hi=Math.min(i+radius,netsize);var j=i+1;var k=i-1;var m=1;var p,a;while(jlo){a=radpower[m++];if(jlo){p=network[k--];p[0]-=a*(p[0]-b)/alpharadbias;p[1]-=a*(p[1]-g)/alpharadbias;p[2]-=a*(p[2]-r)/alpharadbias}}}function contest(b,g,r){var bestd=~(1<<31);var bestbiasd=bestd;var bestpos=-1;var bestbiaspos=bestpos;var i,n,dist,biasdist,betafreq;for(i=0;i>intbiasshift-netbiasshift);if(biasdist>betashift;freq[i]-=betafreq;bias[i]+=betafreq<>1;for(j=previouscol+1;j>1;for(j=previouscol+1;j<256;j++)netindex[j]=maxnetpos}function inxsearch(b,g,r){var a,p,dist;var bestd=1e3;var best=-1;var i=netindex[g];var j=i-1;while(i=0){if(i=bestd)i=netsize;else{i++;if(dist<0)dist=-dist;a=p[0]-b;if(a<0)a=-a;dist+=a;if(dist=0){p=network[j];dist=g-p[1];if(dist>=bestd)j=-1;else{j--;if(dist<0)dist=-dist;a=p[0]-b;if(a<0)a=-a;dist+=a;if(dist>radiusbiasshift;if(rad<=1)rad=0;for(i=0;i=lengthcount)pix-=lengthcount;i++;if(delta===0)delta=1;if(i%delta===0){alpha-=alpha/alphadec;radius-=radius/radiusdec;rad=radius>>radiusbiasshift;if(rad<=1)rad=0;for(j=0;j= ByteArray.pageSize) this.newPage();\n this.pages[this.page][this.cursor++] = val;\n};\n\nByteArray.prototype.writeUTFBytes = function(string) {\n for (var l = string.length, i = 0; i < l; i++)\n this.writeByte(string.charCodeAt(i));\n};\n\nByteArray.prototype.writeBytes = function(array, offset, length) {\n for (var l = length || array.length, i = offset || 0; i < l; i++)\n this.writeByte(array[i]);\n};\n\nfunction GIFEncoder(width, height) {\n // image size\n this.width = ~~width;\n this.height = ~~height;\n\n // transparent color if given\n this.transparent = null;\n\n // transparent index in color table\n this.transIndex = 0;\n\n // -1 = no repeat, 0 = forever. anything else is repeat count\n this.repeat = -1;\n\n // frame delay (hundredths)\n this.delay = 0;\n\n this.image = null; // current frame\n this.pixels = null; // BGR byte array from frame\n this.indexedPixels = null; // converted frame indexed to palette\n this.colorDepth = null; // number of bit planes\n this.colorTab = null; // RGB palette\n this.neuQuant = null; // NeuQuant instance that was used to generate this.colorTab.\n this.usedEntry = new Array(); // active palette entries\n this.palSize = 7; // color table size (bits-1)\n this.dispose = -1; // disposal code (-1 = use default)\n this.firstFrame = true;\n this.sample = 10; // default sample interval for quantizer\n this.dither = false; // default dithering\n this.globalPalette = false;\n\n this.out = new ByteArray();\n}\n\n/*\n Sets the delay time between each frame, or changes it for subsequent frames\n (applies to last frame added)\n*/\nGIFEncoder.prototype.setDelay = function(milliseconds) {\n this.delay = Math.round(milliseconds / 10);\n};\n\n/*\n Sets frame rate in frames per second.\n*/\nGIFEncoder.prototype.setFrameRate = function(fps) {\n this.delay = Math.round(100 / fps);\n};\n\n/*\n Sets the GIF frame disposal code for the last added frame and any\n subsequent frames.\n\n Default is 0 if no transparent color has been set, otherwise 2.\n*/\nGIFEncoder.prototype.setDispose = function(disposalCode) {\n if (disposalCode >= 0) this.dispose = disposalCode;\n};\n\n/*\n Sets the number of times the set of GIF frames should be played.\n\n -1 = play once\n 0 = repeat indefinitely\n\n Default is -1\n\n Must be invoked before the first image is added\n*/\n\nGIFEncoder.prototype.setRepeat = function(repeat) {\n this.repeat = repeat;\n};\n\n/*\n Sets the transparent color for the last added frame and any subsequent\n frames. Since all colors are subject to modification in the quantization\n process, the color in the final palette for each frame closest to the given\n color becomes the transparent color for that frame. May be set to null to\n indicate no transparent color.\n*/\nGIFEncoder.prototype.setTransparent = function(color) {\n this.transparent = color;\n};\n\n/*\n Adds next GIF frame. The frame is not written immediately, but is\n actually deferred until the next frame is received so that timing\n data can be inserted. Invoking finish() flushes all frames.\n*/\nGIFEncoder.prototype.addFrame = function(imageData) {\n this.image = imageData;\n\n this.colorTab = this.globalPalette && this.globalPalette.slice ? this.globalPalette : null;\n\n this.getImagePixels(); // convert to correct format if necessary\n this.analyzePixels(); // build color table & map pixels\n\n if (this.globalPalette === true) this.globalPalette = this.colorTab;\n\n if (this.firstFrame) {\n this.writeLSD(); // logical screen descriptior\n this.writePalette(); // global color table\n if (this.repeat >= 0) {\n // use NS app extension to indicate reps\n this.writeNetscapeExt();\n }\n }\n\n this.writeGraphicCtrlExt(); // write graphic control extension\n this.writeImageDesc(); // image descriptor\n if (!this.firstFrame && !this.globalPalette) this.writePalette(); // local color table\n this.writePixels(); // encode and write pixel data\n\n this.firstFrame = false;\n};\n\n/*\n Adds final trailer to the GIF stream, if you don't call the finish method\n the GIF stream will not be valid.\n*/\nGIFEncoder.prototype.finish = function() {\n this.out.writeByte(0x3b); // gif trailer\n};\n\n/*\n Sets quality of color quantization (conversion of images to the maximum 256\n colors allowed by the GIF specification). Lower values (minimum = 1)\n produce better colors, but slow processing significantly. 10 is the\n default, and produces good color mapping at reasonable speeds. Values\n greater than 20 do not yield significant improvements in speed.\n*/\nGIFEncoder.prototype.setQuality = function(quality) {\n if (quality < 1) quality = 1;\n this.sample = quality;\n};\n\n/*\n Sets dithering method. Available are:\n - FALSE no dithering\n - TRUE or FloydSteinberg\n - FalseFloydSteinberg\n - Stucki\n - Atkinson\n You can add '-serpentine' to use serpentine scanning\n*/\nGIFEncoder.prototype.setDither = function(dither) {\n if (dither === true) dither = 'FloydSteinberg';\n this.dither = dither;\n};\n\n/*\n Sets global palette for all frames.\n You can provide TRUE to create global palette from first picture.\n Or an array of r,g,b,r,g,b,...\n*/\nGIFEncoder.prototype.setGlobalPalette = function(palette) {\n this.globalPalette = palette;\n};\n\n/*\n Returns global palette used for all frames.\n If setGlobalPalette(true) was used, then this function will return\n calculated palette after the first frame is added.\n*/\nGIFEncoder.prototype.getGlobalPalette = function() {\n return (this.globalPalette && this.globalPalette.slice && this.globalPalette.slice(0)) || this.globalPalette;\n};\n\n/*\n Writes GIF file header\n*/\nGIFEncoder.prototype.writeHeader = function() {\n this.out.writeUTFBytes(\"GIF89a\");\n};\n\n/*\n Analyzes current frame colors and creates color map.\n*/\nGIFEncoder.prototype.analyzePixels = function() {\n if (!this.colorTab) {\n this.neuQuant = new NeuQuant(this.pixels, this.sample);\n this.neuQuant.buildColormap(); // create reduced palette\n this.colorTab = this.neuQuant.getColormap();\n }\n\n // map image pixels to new palette\n if (this.dither) {\n this.ditherPixels(this.dither.replace('-serpentine', ''), this.dither.match(/-serpentine/) !== null);\n } else {\n this.indexPixels();\n }\n\n this.pixels = null;\n this.colorDepth = 8;\n this.palSize = 7;\n\n // get closest match to transparent color if specified\n if (this.transparent !== null) {\n this.transIndex = this.findClosest(this.transparent, true);\n }\n};\n\n/*\n Index pixels, without dithering\n*/\nGIFEncoder.prototype.indexPixels = function(imgq) {\n var nPix = this.pixels.length / 3;\n this.indexedPixels = new Uint8Array(nPix);\n var k = 0;\n for (var j = 0; j < nPix; j++) {\n var index = this.findClosestRGB(\n this.pixels[k++] & 0xff,\n this.pixels[k++] & 0xff,\n this.pixels[k++] & 0xff\n );\n this.usedEntry[index] = true;\n this.indexedPixels[j] = index;\n }\n};\n\n/*\n Taken from http://jsbin.com/iXofIji/2/edit by PAEz\n*/\nGIFEncoder.prototype.ditherPixels = function(kernel, serpentine) {\n var kernels = {\n FalseFloydSteinberg: [\n [3 / 8, 1, 0],\n [3 / 8, 0, 1],\n [2 / 8, 1, 1]\n ],\n FloydSteinberg: [\n [7 / 16, 1, 0],\n [3 / 16, -1, 1],\n [5 / 16, 0, 1],\n [1 / 16, 1, 1]\n ],\n Stucki: [\n [8 / 42, 1, 0],\n [4 / 42, 2, 0],\n [2 / 42, -2, 1],\n [4 / 42, -1, 1],\n [8 / 42, 0, 1],\n [4 / 42, 1, 1],\n [2 / 42, 2, 1],\n [1 / 42, -2, 2],\n [2 / 42, -1, 2],\n [4 / 42, 0, 2],\n [2 / 42, 1, 2],\n [1 / 42, 2, 2]\n ],\n Atkinson: [\n [1 / 8, 1, 0],\n [1 / 8, 2, 0],\n [1 / 8, -1, 1],\n [1 / 8, 0, 1],\n [1 / 8, 1, 1],\n [1 / 8, 0, 2]\n ]\n };\n\n if (!kernel || !kernels[kernel]) {\n throw 'Unknown dithering kernel: ' + kernel;\n }\n\n var ds = kernels[kernel];\n var index = 0,\n height = this.height,\n width = this.width,\n data = this.pixels;\n var direction = serpentine ? -1 : 1;\n\n this.indexedPixels = new Uint8Array(this.pixels.length / 3);\n\n for (var y = 0; y < height; y++) {\n\n if (serpentine) direction = direction * -1;\n\n for (var x = (direction == 1 ? 0 : width - 1), xend = (direction == 1 ? width : 0); x !== xend; x += direction) {\n\n index = (y * width) + x;\n // Get original colour\n var idx = index * 3;\n var r1 = data[idx];\n var g1 = data[idx + 1];\n var b1 = data[idx + 2];\n\n // Get converted colour\n idx = this.findClosestRGB(r1, g1, b1);\n this.usedEntry[idx] = true;\n this.indexedPixels[index] = idx;\n idx *= 3;\n var r2 = this.colorTab[idx];\n var g2 = this.colorTab[idx + 1];\n var b2 = this.colorTab[idx + 2];\n\n var er = r1 - r2;\n var eg = g1 - g2;\n var eb = b1 - b2;\n\n for (var i = (direction == 1 ? 0: ds.length - 1), end = (direction == 1 ? ds.length : 0); i !== end; i += direction) {\n var x1 = ds[i][1]; // *direction; // Should this by timesd by direction?..to make the kernel go in the opposite direction....got no idea....\n var y1 = ds[i][2];\n if (x1 + x >= 0 && x1 + x < width && y1 + y >= 0 && y1 + y < height) {\n var d = ds[i][0];\n idx = index + x1 + (y1 * width);\n idx *= 3;\n\n data[idx] = Math.max(0, Math.min(255, data[idx] + er * d));\n data[idx + 1] = Math.max(0, Math.min(255, data[idx + 1] + eg * d));\n data[idx + 2] = Math.max(0, Math.min(255, data[idx + 2] + eb * d));\n }\n }\n }\n }\n};\n\n/*\n Returns index of palette color closest to c\n*/\nGIFEncoder.prototype.findClosest = function(c, used) {\n return this.findClosestRGB((c & 0xFF0000) >> 16, (c & 0x00FF00) >> 8, (c & 0x0000FF), used);\n};\n\nGIFEncoder.prototype.findClosestRGB = function(r, g, b, used) {\n if (this.colorTab === null) return -1;\n\n if (this.neuQuant && !used) {\n return this.neuQuant.lookupRGB(r, g, b);\n }\n \n var c = b | (g << 8) | (r << 16);\n\n var minpos = 0;\n var dmin = 256 * 256 * 256;\n var len = this.colorTab.length;\n\n for (var i = 0, index = 0; i < len; index++) {\n var dr = r - (this.colorTab[i++] & 0xff);\n var dg = g - (this.colorTab[i++] & 0xff);\n var db = b - (this.colorTab[i++] & 0xff);\n var d = dr * dr + dg * dg + db * db;\n if ((!used || this.usedEntry[index]) && (d < dmin)) {\n dmin = d;\n minpos = index;\n }\n }\n\n return minpos;\n};\n\n/*\n Extracts image pixels into byte array pixels\n (removes alphachannel from canvas imagedata)\n*/\nGIFEncoder.prototype.getImagePixels = function() {\n var w = this.width;\n var h = this.height;\n this.pixels = new Uint8Array(w * h * 3);\n\n var data = this.image;\n var srcPos = 0;\n var count = 0;\n\n for (var i = 0; i < h; i++) {\n for (var j = 0; j < w; j++) {\n this.pixels[count++] = data[srcPos++];\n this.pixels[count++] = data[srcPos++];\n this.pixels[count++] = data[srcPos++];\n srcPos++;\n }\n }\n};\n\n/*\n Writes Graphic Control Extension\n*/\nGIFEncoder.prototype.writeGraphicCtrlExt = function() {\n this.out.writeByte(0x21); // extension introducer\n this.out.writeByte(0xf9); // GCE label\n this.out.writeByte(4); // data block size\n\n var transp, disp;\n if (this.transparent === null) {\n transp = 0;\n disp = 0; // dispose = no action\n } else {\n transp = 1;\n disp = 2; // force clear if using transparent color\n }\n\n if (this.dispose >= 0) {\n disp = dispose & 7; // user override\n }\n disp <<= 2;\n\n // packed fields\n this.out.writeByte(\n 0 | // 1:3 reserved\n disp | // 4:6 disposal\n 0 | // 7 user input - 0 = none\n transp // 8 transparency flag\n );\n\n this.writeShort(this.delay); // delay x 1/100 sec\n this.out.writeByte(this.transIndex); // transparent color index\n this.out.writeByte(0); // block terminator\n};\n\n/*\n Writes Image Descriptor\n*/\nGIFEncoder.prototype.writeImageDesc = function() {\n this.out.writeByte(0x2c); // image separator\n this.writeShort(0); // image position x,y = 0,0\n this.writeShort(0);\n this.writeShort(this.width); // image size\n this.writeShort(this.height);\n\n // packed fields\n if (this.firstFrame || this.globalPalette) {\n // no LCT - GCT is used for first (or only) frame\n this.out.writeByte(0);\n } else {\n // specify normal LCT\n this.out.writeByte(\n 0x80 | // 1 local color table 1=yes\n 0 | // 2 interlace - 0=no\n 0 | // 3 sorted - 0=no\n 0 | // 4-5 reserved\n this.palSize // 6-8 size of color table\n );\n }\n};\n\n/*\n Writes Logical Screen Descriptor\n*/\nGIFEncoder.prototype.writeLSD = function() {\n // logical screen size\n this.writeShort(this.width);\n this.writeShort(this.height);\n\n // packed fields\n this.out.writeByte(\n 0x80 | // 1 : global color table flag = 1 (gct used)\n 0x70 | // 2-4 : color resolution = 7\n 0x00 | // 5 : gct sort flag = 0\n this.palSize // 6-8 : gct size\n );\n\n this.out.writeByte(0); // background color index\n this.out.writeByte(0); // pixel aspect ratio - assume 1:1\n};\n\n/*\n Writes Netscape application extension to define repeat count.\n*/\nGIFEncoder.prototype.writeNetscapeExt = function() {\n this.out.writeByte(0x21); // extension introducer\n this.out.writeByte(0xff); // app extension label\n this.out.writeByte(11); // block size\n this.out.writeUTFBytes('NETSCAPE2.0'); // app id + auth code\n this.out.writeByte(3); // sub-block size\n this.out.writeByte(1); // loop sub-block id\n this.writeShort(this.repeat); // loop count (extra iterations, 0=repeat forever)\n this.out.writeByte(0); // block terminator\n};\n\n/*\n Writes color table\n*/\nGIFEncoder.prototype.writePalette = function() {\n this.out.writeBytes(this.colorTab);\n var n = (3 * 256) - this.colorTab.length;\n for (var i = 0; i < n; i++)\n this.out.writeByte(0);\n};\n\nGIFEncoder.prototype.writeShort = function(pValue) {\n this.out.writeByte(pValue & 0xFF);\n this.out.writeByte((pValue >> 8) & 0xFF);\n};\n\n/*\n Encodes and writes pixel data\n*/\nGIFEncoder.prototype.writePixels = function() {\n var enc = new LZWEncoder(this.width, this.height, this.indexedPixels, this.colorDepth);\n enc.encode(this.out);\n};\n\n/*\n Retrieves the GIF stream\n*/\nGIFEncoder.prototype.stream = function() {\n return this.out;\n};\n\nmodule.exports = GIFEncoder;\n","/*\n LZWEncoder.js\n\n Authors\n Kevin Weiner (original Java version - kweiner@fmsware.com)\n Thibault Imbert (AS3 version - bytearray.org)\n Johan Nordberg (JS version - code@johan-nordberg.com)\n\n Acknowledgements\n GIFCOMPR.C - GIF Image compression routines\n Lempel-Ziv compression based on 'compress'. GIF modifications by\n David Rowley (mgardi@watdcsu.waterloo.edu)\n GIF Image compression - modified 'compress'\n Based on: compress.c - File compression ala IEEE Computer, June 1984.\n By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)\n Jim McKie (decvax!mcvax!jim)\n Steve Davies (decvax!vax135!petsd!peora!srd)\n Ken Turkowski (decvax!decwrl!turtlevax!ken)\n James A. Woods (decvax!ihnp4!ames!jaw)\n Joe Orost (decvax!vax135!petsd!joe)\n*/\n\nvar EOF = -1;\nvar BITS = 12;\nvar HSIZE = 5003; // 80% occupancy\nvar masks = [0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F,\n 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF,\n 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF];\n\nfunction LZWEncoder(width, height, pixels, colorDepth) {\n var initCodeSize = Math.max(2, colorDepth);\n\n var accum = new Uint8Array(256);\n var htab = new Int32Array(HSIZE);\n var codetab = new Int32Array(HSIZE);\n\n var cur_accum, cur_bits = 0;\n var a_count;\n var free_ent = 0; // first unused entry\n var maxcode;\n\n // block compression parameters -- after all codes are used up,\n // and compression rate changes, start over.\n var clear_flg = false;\n\n // Algorithm: use open addressing double hashing (no chaining) on the\n // prefix code / next character combination. We do a variant of Knuth's\n // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime\n // secondary probe. Here, the modular division first probe is gives way\n // to a faster exclusive-or manipulation. Also do block compression with\n // an adaptive reset, whereby the code table is cleared when the compression\n // ratio decreases, but after the table fills. The variable-length output\n // codes are re-sized at this point, and a special CLEAR code is generated\n // for the decompressor. Late addition: construct the table according to\n // file size for noticeable speed improvement on small files. Please direct\n // questions about this implementation to ames!jaw.\n var g_init_bits, ClearCode, EOFCode;\n\n // Add a character to the end of the current packet, and if it is 254\n // characters, flush the packet to disk.\n function char_out(c, outs) {\n accum[a_count++] = c;\n if (a_count >= 254) flush_char(outs);\n }\n\n // Clear out the hash table\n // table clear for block compress\n function cl_block(outs) {\n cl_hash(HSIZE);\n free_ent = ClearCode + 2;\n clear_flg = true;\n output(ClearCode, outs);\n }\n\n // Reset code table\n function cl_hash(hsize) {\n for (var i = 0; i < hsize; ++i) htab[i] = -1;\n }\n\n function compress(init_bits, outs) {\n var fcode, c, i, ent, disp, hsize_reg, hshift;\n\n // Set up the globals: g_init_bits - initial number of bits\n g_init_bits = init_bits;\n\n // Set up the necessary values\n clear_flg = false;\n n_bits = g_init_bits;\n maxcode = MAXCODE(n_bits);\n\n ClearCode = 1 << (init_bits - 1);\n EOFCode = ClearCode + 1;\n free_ent = ClearCode + 2;\n\n a_count = 0; // clear packet\n\n ent = nextPixel();\n\n hshift = 0;\n for (fcode = HSIZE; fcode < 65536; fcode *= 2) ++hshift;\n hshift = 8 - hshift; // set hash code range bound\n hsize_reg = HSIZE;\n cl_hash(hsize_reg); // clear hash table\n\n output(ClearCode, outs);\n\n outer_loop: while ((c = nextPixel()) != EOF) {\n fcode = (c << BITS) + ent;\n i = (c << hshift) ^ ent; // xor hashing\n if (htab[i] === fcode) {\n ent = codetab[i];\n continue;\n } else if (htab[i] >= 0) { // non-empty slot\n disp = hsize_reg - i; // secondary hash (after G. Knott)\n if (i === 0) disp = 1;\n do {\n if ((i -= disp) < 0) i += hsize_reg;\n if (htab[i] === fcode) {\n ent = codetab[i];\n continue outer_loop;\n }\n } while (htab[i] >= 0);\n }\n output(ent, outs);\n ent = c;\n if (free_ent < 1 << BITS) {\n codetab[i] = free_ent++; // code -> hashtable\n htab[i] = fcode;\n } else {\n cl_block(outs);\n }\n }\n\n // Put out the final code.\n output(ent, outs);\n output(EOFCode, outs);\n }\n\n function encode(outs) {\n outs.writeByte(initCodeSize); // write \"initial code size\" byte\n remaining = width * height; // reset navigation variables\n curPixel = 0;\n compress(initCodeSize + 1, outs); // compress and write the pixel data\n outs.writeByte(0); // write block terminator\n }\n\n // Flush the packet to disk, and reset the accumulator\n function flush_char(outs) {\n if (a_count > 0) {\n outs.writeByte(a_count);\n outs.writeBytes(accum, 0, a_count);\n a_count = 0;\n }\n }\n\n function MAXCODE(n_bits) {\n return (1 << n_bits) - 1;\n }\n\n // Return the next pixel from the image\n function nextPixel() {\n if (remaining === 0) return EOF;\n --remaining;\n var pix = pixels[curPixel++];\n return pix & 0xff;\n }\n\n function output(code, outs) {\n cur_accum &= masks[cur_bits];\n\n if (cur_bits > 0) cur_accum |= (code << cur_bits);\n else cur_accum = code;\n\n cur_bits += n_bits;\n\n while (cur_bits >= 8) {\n char_out((cur_accum & 0xff), outs);\n cur_accum >>= 8;\n cur_bits -= 8;\n }\n\n // If the next entry is going to be too big for the code size,\n // then increase it, if possible.\n if (free_ent > maxcode || clear_flg) {\n if (clear_flg) {\n maxcode = MAXCODE(n_bits = g_init_bits);\n clear_flg = false;\n } else {\n ++n_bits;\n if (n_bits == BITS) maxcode = 1 << BITS;\n else maxcode = MAXCODE(n_bits);\n }\n }\n\n if (code == EOFCode) {\n // At EOF, write the rest of the buffer.\n while (cur_bits > 0) {\n char_out((cur_accum & 0xff), outs);\n cur_accum >>= 8;\n cur_bits -= 8;\n }\n flush_char(outs);\n }\n }\n\n this.encode = encode;\n}\n\nmodule.exports = LZWEncoder;\n","/* NeuQuant Neural-Net Quantization Algorithm\n * ------------------------------------------\n *\n * Copyright (c) 1994 Anthony Dekker\n *\n * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994.\n * See \"Kohonen neural networks for optimal colour quantization\"\n * in \"Network: Computation in Neural Systems\" Vol. 5 (1994) pp 351-367.\n * for a discussion of the algorithm.\n * See also http://members.ozemail.com.au/~dekker/NEUQUANT.HTML\n *\n * Any party obtaining a copy of these files from the author, directly or\n * indirectly, is granted, free of charge, a full and unrestricted irrevocable,\n * world-wide, paid up, royalty-free, nonexclusive right and license to deal\n * in this software and documentation files (the \"Software\"), including without\n * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons who receive\n * copies from any such party to do so, with the only requirement being\n * that this copyright notice remain intact.\n *\n * (JavaScript port 2012 by Johan Nordberg)\n */\n\nvar ncycles = 100; // number of learning cycles\nvar netsize = 256; // number of colors used\nvar maxnetpos = netsize - 1;\n\n// defs for freq and bias\nvar netbiasshift = 4; // bias for colour values\nvar intbiasshift = 16; // bias for fractions\nvar intbias = (1 << intbiasshift);\nvar gammashift = 10;\nvar gamma = (1 << gammashift);\nvar betashift = 10;\nvar beta = (intbias >> betashift); /* beta = 1/1024 */\nvar betagamma = (intbias << (gammashift - betashift));\n\n// defs for decreasing radius factor\nvar initrad = (netsize >> 3); // for 256 cols, radius starts\nvar radiusbiasshift = 6; // at 32.0 biased by 6 bits\nvar radiusbias = (1 << radiusbiasshift);\nvar initradius = (initrad * radiusbias); //and decreases by a\nvar radiusdec = 30; // factor of 1/30 each cycle\n\n// defs for decreasing alpha factor\nvar alphabiasshift = 10; // alpha starts at 1.0\nvar initalpha = (1 << alphabiasshift);\nvar alphadec; // biased by 10 bits\n\n/* radbias and alpharadbias used for radpower calculation */\nvar radbiasshift = 8;\nvar radbias = (1 << radbiasshift);\nvar alpharadbshift = (alphabiasshift + radbiasshift);\nvar alpharadbias = (1 << alpharadbshift);\n\n// four primes near 500 - assume no image has a length so large that it is\n// divisible by all four primes\nvar prime1 = 499;\nvar prime2 = 491;\nvar prime3 = 487;\nvar prime4 = 503;\nvar minpicturebytes = (3 * prime4);\n\n/*\n Constructor: NeuQuant\n\n Arguments:\n\n pixels - array of pixels in RGB format\n samplefac - sampling factor 1 to 30 where lower is better quality\n\n >\n > pixels = [r, g, b, r, g, b, r, g, b, ..]\n >\n*/\nfunction NeuQuant(pixels, samplefac) {\n var network; // int[netsize][4]\n var netindex; // for network lookup - really 256\n\n // bias and freq arrays for learning\n var bias;\n var freq;\n var radpower;\n\n /*\n Private Method: init\n\n sets up arrays\n */\n function init() {\n network = [];\n netindex = new Int32Array(256);\n bias = new Int32Array(netsize);\n freq = new Int32Array(netsize);\n radpower = new Int32Array(netsize >> 3);\n\n var i, v;\n for (i = 0; i < netsize; i++) {\n v = (i << (netbiasshift + 8)) / netsize;\n network[i] = new Float64Array([v, v, v, 0]);\n //network[i] = [v, v, v, 0]\n freq[i] = intbias / netsize;\n bias[i] = 0;\n }\n }\n\n /*\n Private Method: unbiasnet\n\n unbiases network to give byte values 0..255 and record position i to prepare for sort\n */\n function unbiasnet() {\n for (var i = 0; i < netsize; i++) {\n network[i][0] >>= netbiasshift;\n network[i][1] >>= netbiasshift;\n network[i][2] >>= netbiasshift;\n network[i][3] = i; // record color number\n }\n }\n\n /*\n Private Method: altersingle\n\n moves neuron *i* towards biased (b,g,r) by factor *alpha*\n */\n function altersingle(alpha, i, b, g, r) {\n network[i][0] -= (alpha * (network[i][0] - b)) / initalpha;\n network[i][1] -= (alpha * (network[i][1] - g)) / initalpha;\n network[i][2] -= (alpha * (network[i][2] - r)) / initalpha;\n }\n\n /*\n Private Method: alterneigh\n\n moves neurons in *radius* around index *i* towards biased (b,g,r) by factor *alpha*\n */\n function alterneigh(radius, i, b, g, r) {\n var lo = Math.abs(i - radius);\n var hi = Math.min(i + radius, netsize);\n\n var j = i + 1;\n var k = i - 1;\n var m = 1;\n\n var p, a;\n while ((j < hi) || (k > lo)) {\n a = radpower[m++];\n\n if (j < hi) {\n p = network[j++];\n p[0] -= (a * (p[0] - b)) / alpharadbias;\n p[1] -= (a * (p[1] - g)) / alpharadbias;\n p[2] -= (a * (p[2] - r)) / alpharadbias;\n }\n\n if (k > lo) {\n p = network[k--];\n p[0] -= (a * (p[0] - b)) / alpharadbias;\n p[1] -= (a * (p[1] - g)) / alpharadbias;\n p[2] -= (a * (p[2] - r)) / alpharadbias;\n }\n }\n }\n\n /*\n Private Method: contest\n\n searches for biased BGR values\n */\n function contest(b, g, r) {\n /*\n finds closest neuron (min dist) and updates freq\n finds best neuron (min dist-bias) and returns position\n for frequently chosen neurons, freq[i] is high and bias[i] is negative\n bias[i] = gamma * ((1 / netsize) - freq[i])\n */\n\n var bestd = ~(1 << 31);\n var bestbiasd = bestd;\n var bestpos = -1;\n var bestbiaspos = bestpos;\n\n var i, n, dist, biasdist, betafreq;\n for (i = 0; i < netsize; i++) {\n n = network[i];\n\n dist = Math.abs(n[0] - b) + Math.abs(n[1] - g) + Math.abs(n[2] - r);\n if (dist < bestd) {\n bestd = dist;\n bestpos = i;\n }\n\n biasdist = dist - ((bias[i]) >> (intbiasshift - netbiasshift));\n if (biasdist < bestbiasd) {\n bestbiasd = biasdist;\n bestbiaspos = i;\n }\n\n betafreq = (freq[i] >> betashift);\n freq[i] -= betafreq;\n bias[i] += (betafreq << gammashift);\n }\n\n freq[bestpos] += beta;\n bias[bestpos] -= betagamma;\n\n return bestbiaspos;\n }\n\n /*\n Private Method: inxbuild\n\n sorts network and builds netindex[0..255]\n */\n function inxbuild() {\n var i, j, p, q, smallpos, smallval, previouscol = 0, startpos = 0;\n for (i = 0; i < netsize; i++) {\n p = network[i];\n smallpos = i;\n smallval = p[1]; // index on g\n // find smallest in i..netsize-1\n for (j = i + 1; j < netsize; j++) {\n q = network[j];\n if (q[1] < smallval) { // index on g\n smallpos = j;\n smallval = q[1]; // index on g\n }\n }\n q = network[smallpos];\n // swap p (i) and q (smallpos) entries\n if (i != smallpos) {\n j = q[0]; q[0] = p[0]; p[0] = j;\n j = q[1]; q[1] = p[1]; p[1] = j;\n j = q[2]; q[2] = p[2]; p[2] = j;\n j = q[3]; q[3] = p[3]; p[3] = j;\n }\n // smallval entry is now in position i\n\n if (smallval != previouscol) {\n netindex[previouscol] = (startpos + i) >> 1;\n for (j = previouscol + 1; j < smallval; j++)\n netindex[j] = i;\n previouscol = smallval;\n startpos = i;\n }\n }\n netindex[previouscol] = (startpos + maxnetpos) >> 1;\n for (j = previouscol + 1; j < 256; j++)\n netindex[j] = maxnetpos; // really 256\n }\n\n /*\n Private Method: inxsearch\n\n searches for BGR values 0..255 and returns a color index\n */\n function inxsearch(b, g, r) {\n var a, p, dist;\n\n var bestd = 1000; // biggest possible dist is 256*3\n var best = -1;\n\n var i = netindex[g]; // index on g\n var j = i - 1; // start at netindex[g] and work outwards\n\n while ((i < netsize) || (j >= 0)) {\n if (i < netsize) {\n p = network[i];\n dist = p[1] - g; // inx key\n if (dist >= bestd) i = netsize; // stop iter\n else {\n i++;\n if (dist < 0) dist = -dist;\n a = p[0] - b; if (a < 0) a = -a;\n dist += a;\n if (dist < bestd) {\n a = p[2] - r; if (a < 0) a = -a;\n dist += a;\n if (dist < bestd) {\n bestd = dist;\n best = p[3];\n }\n }\n }\n }\n if (j >= 0) {\n p = network[j];\n dist = g - p[1]; // inx key - reverse dif\n if (dist >= bestd) j = -1; // stop iter\n else {\n j--;\n if (dist < 0) dist = -dist;\n a = p[0] - b; if (a < 0) a = -a;\n dist += a;\n if (dist < bestd) {\n a = p[2] - r; if (a < 0) a = -a;\n dist += a;\n if (dist < bestd) {\n bestd = dist;\n best = p[3];\n }\n }\n }\n }\n }\n\n return best;\n }\n\n /*\n Private Method: learn\n\n \"Main Learning Loop\"\n */\n function learn() {\n var i;\n\n var lengthcount = pixels.length;\n var alphadec = 30 + ((samplefac - 1) / 3);\n var samplepixels = lengthcount / (3 * samplefac);\n var delta = ~~(samplepixels / ncycles);\n var alpha = initalpha;\n var radius = initradius;\n\n var rad = radius >> radiusbiasshift;\n\n if (rad <= 1) rad = 0;\n for (i = 0; i < rad; i++)\n radpower[i] = alpha * (((rad * rad - i * i) * radbias) / (rad * rad));\n\n var step;\n if (lengthcount < minpicturebytes) {\n samplefac = 1;\n step = 3;\n } else if ((lengthcount % prime1) !== 0) {\n step = 3 * prime1;\n } else if ((lengthcount % prime2) !== 0) {\n step = 3 * prime2;\n } else if ((lengthcount % prime3) !== 0) {\n step = 3 * prime3;\n } else {\n step = 3 * prime4;\n }\n\n var b, g, r, j;\n var pix = 0; // current pixel\n\n i = 0;\n while (i < samplepixels) {\n b = (pixels[pix] & 0xff) << netbiasshift;\n g = (pixels[pix + 1] & 0xff) << netbiasshift;\n r = (pixels[pix + 2] & 0xff) << netbiasshift;\n\n j = contest(b, g, r);\n\n altersingle(alpha, j, b, g, r);\n if (rad !== 0) alterneigh(rad, j, b, g, r); // alter neighbours\n\n pix += step;\n if (pix >= lengthcount) pix -= lengthcount;\n\n i++;\n\n if (delta === 0) delta = 1;\n if (i % delta === 0) {\n alpha -= alpha / alphadec;\n radius -= radius / radiusdec;\n rad = radius >> radiusbiasshift;\n\n if (rad <= 1) rad = 0;\n for (j = 0; j < rad; j++)\n radpower[j] = alpha * (((rad * rad - j * j) * radbias) / (rad * rad));\n }\n }\n }\n\n /*\n Method: buildColormap\n\n 1. initializes network\n 2. trains it\n 3. removes misconceptions\n 4. builds colorindex\n */\n function buildColormap() {\n init();\n learn();\n unbiasnet();\n inxbuild();\n }\n this.buildColormap = buildColormap;\n\n /*\n Method: getColormap\n\n builds colormap from the index\n\n returns array in the format:\n\n >\n > [r, g, b, r, g, b, r, g, b, ..]\n >\n */\n function getColormap() {\n var map = [];\n var index = [];\n\n for (var i = 0; i < netsize; i++)\n index[network[i][3]] = i;\n\n var k = 0;\n for (var l = 0; l < netsize; l++) {\n var j = index[l];\n map[k++] = (network[j][0]);\n map[k++] = (network[j][1]);\n map[k++] = (network[j][2]);\n }\n return map;\n }\n this.getColormap = getColormap;\n\n /*\n Method: lookupRGB\n\n looks for the closest *r*, *g*, *b* color in the map and\n returns its index\n */\n this.lookupRGB = inxsearch;\n}\n\nmodule.exports = NeuQuant;\n","GIFEncoder = require './GIFEncoder.js'\n\nrenderFrame = (frame) ->\n encoder = new GIFEncoder frame.width, frame.height\n\n if frame.index is 0\n encoder.writeHeader()\n else\n encoder.firstFrame = false\n\n encoder.setTransparent frame.transparent\n encoder.setRepeat frame.repeat\n encoder.setDelay frame.delay\n encoder.setQuality frame.quality\n encoder.setDither frame.dither\n encoder.setGlobalPalette frame.globalPalette\n encoder.addFrame frame.data\n encoder.finish() if frame.last\n if frame.globalPalette == true\n frame.globalPalette = encoder.getGlobalPalette()\n\n stream = encoder.stream()\n frame.data = stream.pages\n frame.cursor = stream.cursor\n frame.pageSize = stream.constructor.pageSize\n\n if frame.canTransfer\n transfer = (page.buffer for page in frame.data)\n self.postMessage frame, transfer\n else\n self.postMessage frame\n\nself.onmessage = (event) -> renderFrame event.data\n"]} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index a4a35ee..839731a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5314,6 +5314,11 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +gif.js@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/gif.js/-/gif.js-0.2.0.tgz#615e6e3788850cd3a20c85fe9f09539e784903e8" + integrity sha1-YV5uN4iFDNOiDIX+nwlTnnhJA+g= + glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"