UNPKG

26.9 kBJavaScriptView Raw
1(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.blobUtil = f()}})(function(){var define,module,exports;return (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<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
2(function (global){
3/**
4 * Create a blob builder even when vendor prefixes exist
5 */
6
7var BlobBuilder = global.BlobBuilder
8 || global.WebKitBlobBuilder
9 || global.MSBlobBuilder
10 || global.MozBlobBuilder;
11
12/**
13 * Check if Blob constructor is supported
14 */
15
16var blobSupported = (function() {
17 try {
18 var a = new Blob(['hi']);
19 return a.size === 2;
20 } catch(e) {
21 return false;
22 }
23})();
24
25/**
26 * Check if Blob constructor supports ArrayBufferViews
27 * Fails in Safari 6, so we need to map to ArrayBuffers there.
28 */
29
30var blobSupportsArrayBufferView = blobSupported && (function() {
31 try {
32 var b = new Blob([new Uint8Array([1,2])]);
33 return b.size === 2;
34 } catch(e) {
35 return false;
36 }
37})();
38
39/**
40 * Check if BlobBuilder is supported
41 */
42
43var blobBuilderSupported = BlobBuilder
44 && BlobBuilder.prototype.append
45 && BlobBuilder.prototype.getBlob;
46
47/**
48 * Helper function that maps ArrayBufferViews to ArrayBuffers
49 * Used by BlobBuilder constructor and old browsers that didn't
50 * support it in the Blob constructor.
51 */
52
53function mapArrayBufferViews(ary) {
54 for (var i = 0; i < ary.length; i++) {
55 var chunk = ary[i];
56 if (chunk.buffer instanceof ArrayBuffer) {
57 var buf = chunk.buffer;
58
59 // if this is a subarray, make a copy so we only
60 // include the subarray region from the underlying buffer
61 if (chunk.byteLength !== buf.byteLength) {
62 var copy = new Uint8Array(chunk.byteLength);
63 copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength));
64 buf = copy.buffer;
65 }
66
67 ary[i] = buf;
68 }
69 }
70}
71
72function BlobBuilderConstructor(ary, options) {
73 options = options || {};
74
75 var bb = new BlobBuilder();
76 mapArrayBufferViews(ary);
77
78 for (var i = 0; i < ary.length; i++) {
79 bb.append(ary[i]);
80 }
81
82 return (options.type) ? bb.getBlob(options.type) : bb.getBlob();
83};
84
85function BlobConstructor(ary, options) {
86 mapArrayBufferViews(ary);
87 return new Blob(ary, options || {});
88};
89
90module.exports = (function() {
91 if (blobSupported) {
92 return blobSupportsArrayBufferView ? global.Blob : BlobConstructor;
93 } else if (blobBuilderSupported) {
94 return BlobBuilderConstructor;
95 } else {
96 return undefined;
97 }
98})();
99
100}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
101},{}],2:[function(_dereq_,module,exports){
102'use strict';
103var types = [
104 _dereq_(5),
105 _dereq_(4),
106 _dereq_(3),
107 _dereq_(6),
108 _dereq_(7)
109];
110var draining;
111var currentQueue;
112var queueIndex = -1;
113var queue = [];
114var scheduled = false;
115function cleanUpNextTick() {
116 draining = false;
117 if (currentQueue && currentQueue.length) {
118 queue = currentQueue.concat(queue);
119 } else {
120 queueIndex = -1;
121 }
122 if (queue.length) {
123 nextTick();
124 }
125}
126
127//named nextTick for less confusing stack traces
128function nextTick() {
129 scheduled = false;
130 draining = true;
131 var len = queue.length;
132 var timeout = setTimeout(cleanUpNextTick);
133 while (len) {
134 currentQueue = queue;
135 queue = [];
136 while (++queueIndex < len) {
137 currentQueue[queueIndex].run();
138 }
139 queueIndex = -1;
140 len = queue.length;
141 }
142 queueIndex = -1;
143 draining = false;
144 clearTimeout(timeout);
145}
146var scheduleDrain;
147var i = -1;
148var len = types.length;
149while (++i < len) {
150 if (types[i] && types[i].test && types[i].test()) {
151 scheduleDrain = types[i].install(nextTick);
152 break;
153 }
154}
155// v8 likes predictible objects
156function Item(fun, array) {
157 this.fun = fun;
158 this.array = array;
159}
160Item.prototype.run = function () {
161 this.fun.apply(null, this.array);
162};
163module.exports = immediate;
164function immediate(task) {
165 var args = new Array(arguments.length - 1);
166 if (arguments.length > 1) {
167 for (var i = 1; i < arguments.length; i++) {
168 args[i - 1] = arguments[i];
169 }
170 }
171 queue.push(new Item(task, args));
172 if (!scheduled && !draining) {
173 scheduled = true;
174 scheduleDrain();
175 }
176}
177
178},{"3":3,"4":4,"5":5,"6":6,"7":7}],3:[function(_dereq_,module,exports){
179(function (global){
180'use strict';
181
182exports.test = function () {
183 if (global.setImmediate) {
184 // we can only get here in IE10
185 // which doesn't handel postMessage well
186 return false;
187 }
188 return typeof global.MessageChannel !== 'undefined';
189};
190
191exports.install = function (func) {
192 var channel = new global.MessageChannel();
193 channel.port1.onmessage = func;
194 return function () {
195 channel.port2.postMessage(0);
196 };
197};
198}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
199},{}],4:[function(_dereq_,module,exports){
200(function (global){
201'use strict';
202//based off rsvp https://github.com/tildeio/rsvp.js
203//license https://github.com/tildeio/rsvp.js/blob/master/LICENSE
204//https://github.com/tildeio/rsvp.js/blob/master/lib/rsvp/asap.js
205
206var Mutation = global.MutationObserver || global.WebKitMutationObserver;
207
208exports.test = function () {
209 return Mutation;
210};
211
212exports.install = function (handle) {
213 var called = 0;
214 var observer = new Mutation(handle);
215 var element = global.document.createTextNode('');
216 observer.observe(element, {
217 characterData: true
218 });
219 return function () {
220 element.data = (called = ++called % 2);
221 };
222};
223}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
224},{}],5:[function(_dereq_,module,exports){
225(function (process){
226'use strict';
227exports.test = function () {
228 // Don't get fooled by e.g. browserify environments.
229 return (typeof process !== 'undefined') && !process.browser;
230};
231
232exports.install = function (func) {
233 return function () {
234 process.nextTick(func);
235 };
236};
237
238}).call(this,_dereq_(21))
239},{"21":21}],6:[function(_dereq_,module,exports){
240(function (global){
241'use strict';
242
243exports.test = function () {
244 return 'document' in global && 'onreadystatechange' in global.document.createElement('script');
245};
246
247exports.install = function (handle) {
248 return function () {
249
250 // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
251 // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
252 var scriptEl = global.document.createElement('script');
253 scriptEl.onreadystatechange = function () {
254 handle();
255
256 scriptEl.onreadystatechange = null;
257 scriptEl.parentNode.removeChild(scriptEl);
258 scriptEl = null;
259 };
260 global.document.documentElement.appendChild(scriptEl);
261
262 return handle;
263 };
264};
265}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
266},{}],7:[function(_dereq_,module,exports){
267'use strict';
268exports.test = function () {
269 return true;
270};
271
272exports.install = function (t) {
273 return function () {
274 setTimeout(t, 0);
275 };
276};
277},{}],8:[function(_dereq_,module,exports){
278'use strict';
279
280module.exports = INTERNAL;
281
282function INTERNAL() {}
283},{}],9:[function(_dereq_,module,exports){
284'use strict';
285var Promise = _dereq_(12);
286var reject = _dereq_(14);
287var resolve = _dereq_(15);
288var INTERNAL = _dereq_(8);
289var handlers = _dereq_(10);
290var noArray = reject(new TypeError('must be an array'));
291module.exports = function all(iterable) {
292 if (Object.prototype.toString.call(iterable) !== '[object Array]') {
293 return noArray;
294 }
295
296 var len = iterable.length;
297 var called = false;
298 if (!len) {
299 return resolve([]);
300 }
301
302 var values = new Array(len);
303 var resolved = 0;
304 var i = -1;
305 var promise = new Promise(INTERNAL);
306
307 while (++i < len) {
308 allResolver(iterable[i], i);
309 }
310 return promise;
311 function allResolver(value, i) {
312 resolve(value).then(resolveFromAll, function (error) {
313 if (!called) {
314 called = true;
315 handlers.reject(promise, error);
316 }
317 });
318 function resolveFromAll(outValue) {
319 values[i] = outValue;
320 if (++resolved === len & !called) {
321 called = true;
322 handlers.resolve(promise, values);
323 }
324 }
325 }
326};
327},{"10":10,"12":12,"14":14,"15":15,"8":8}],10:[function(_dereq_,module,exports){
328'use strict';
329var tryCatch = _dereq_(18);
330var resolveThenable = _dereq_(16);
331var states = _dereq_(17);
332
333exports.resolve = function (self, value) {
334 var result = tryCatch(getThen, value);
335 if (result.status === 'error') {
336 return exports.reject(self, result.value);
337 }
338 var thenable = result.value;
339
340 if (thenable) {
341 resolveThenable.safely(self, thenable);
342 } else {
343 self.state = states.FULFILLED;
344 self.outcome = value;
345 var i = -1;
346 var len = self.queue.length;
347 while (++i < len) {
348 self.queue[i].callFulfilled(value);
349 }
350 }
351 return self;
352};
353exports.reject = function (self, error) {
354 self.state = states.REJECTED;
355 self.outcome = error;
356 var i = -1;
357 var len = self.queue.length;
358 while (++i < len) {
359 self.queue[i].callRejected(error);
360 }
361 return self;
362};
363
364function getThen(obj) {
365 // Make sure we only access the accessor once as required by the spec
366 var then = obj && obj.then;
367 if (obj && typeof obj === 'object' && typeof then === 'function') {
368 return function appyThen() {
369 then.apply(obj, arguments);
370 };
371 }
372}
373},{"16":16,"17":17,"18":18}],11:[function(_dereq_,module,exports){
374module.exports = exports = _dereq_(12);
375
376exports.resolve = _dereq_(15);
377exports.reject = _dereq_(14);
378exports.all = _dereq_(9);
379},{"12":12,"14":14,"15":15,"9":9}],12:[function(_dereq_,module,exports){
380'use strict';
381
382var unwrap = _dereq_(19);
383var INTERNAL = _dereq_(8);
384var resolveThenable = _dereq_(16);
385var states = _dereq_(17);
386var QueueItem = _dereq_(13);
387
388module.exports = Promise;
389function Promise(resolver) {
390 if (!(this instanceof Promise)) {
391 return new Promise(resolver);
392 }
393 if (typeof resolver !== 'function') {
394 throw new TypeError('reslover must be a function');
395 }
396 this.state = states.PENDING;
397 this.queue = [];
398 this.outcome = void 0;
399 if (resolver !== INTERNAL) {
400 resolveThenable.safely(this, resolver);
401 }
402}
403
404Promise.prototype['catch'] = function (onRejected) {
405 return this.then(null, onRejected);
406};
407Promise.prototype.then = function (onFulfilled, onRejected) {
408 if (typeof onFulfilled !== 'function' && this.state === states.FULFILLED ||
409 typeof onRejected !== 'function' && this.state === states.REJECTED) {
410 return this;
411 }
412 var promise = new Promise(INTERNAL);
413
414
415 if (this.state !== states.PENDING) {
416 var resolver = this.state === states.FULFILLED ? onFulfilled: onRejected;
417 unwrap(promise, resolver, this.outcome);
418 } else {
419 this.queue.push(new QueueItem(promise, onFulfilled, onRejected));
420 }
421
422 return promise;
423};
424
425},{"13":13,"16":16,"17":17,"19":19,"8":8}],13:[function(_dereq_,module,exports){
426'use strict';
427var handlers = _dereq_(10);
428var unwrap = _dereq_(19);
429
430module.exports = QueueItem;
431function QueueItem(promise, onFulfilled, onRejected) {
432 this.promise = promise;
433 if (typeof onFulfilled === 'function') {
434 this.onFulfilled = onFulfilled;
435 this.callFulfilled = this.otherCallFulfilled;
436 }
437 if (typeof onRejected === 'function') {
438 this.onRejected = onRejected;
439 this.callRejected = this.otherCallRejected;
440 }
441}
442QueueItem.prototype.callFulfilled = function (value) {
443 handlers.resolve(this.promise, value);
444};
445QueueItem.prototype.otherCallFulfilled = function (value) {
446 unwrap(this.promise, this.onFulfilled, value);
447};
448QueueItem.prototype.callRejected = function (value) {
449 handlers.reject(this.promise, value);
450};
451QueueItem.prototype.otherCallRejected = function (value) {
452 unwrap(this.promise, this.onRejected, value);
453};
454},{"10":10,"19":19}],14:[function(_dereq_,module,exports){
455'use strict';
456
457var Promise = _dereq_(12);
458var INTERNAL = _dereq_(8);
459var handlers = _dereq_(10);
460module.exports = reject;
461
462function reject(reason) {
463 var promise = new Promise(INTERNAL);
464 return handlers.reject(promise, reason);
465}
466},{"10":10,"12":12,"8":8}],15:[function(_dereq_,module,exports){
467'use strict';
468
469var Promise = _dereq_(12);
470var INTERNAL = _dereq_(8);
471var handlers = _dereq_(10);
472module.exports = resolve;
473
474var FALSE = handlers.resolve(new Promise(INTERNAL), false);
475var NULL = handlers.resolve(new Promise(INTERNAL), null);
476var UNDEFINED = handlers.resolve(new Promise(INTERNAL), void 0);
477var ZERO = handlers.resolve(new Promise(INTERNAL), 0);
478var EMPTYSTRING = handlers.resolve(new Promise(INTERNAL), '');
479
480function resolve(value) {
481 if (value) {
482 if (value instanceof Promise) {
483 return value;
484 }
485 return handlers.resolve(new Promise(INTERNAL), value);
486 }
487 var valueType = typeof value;
488 switch (valueType) {
489 case 'boolean':
490 return FALSE;
491 case 'undefined':
492 return UNDEFINED;
493 case 'object':
494 return NULL;
495 case 'number':
496 return ZERO;
497 case 'string':
498 return EMPTYSTRING;
499 }
500}
501},{"10":10,"12":12,"8":8}],16:[function(_dereq_,module,exports){
502'use strict';
503var handlers = _dereq_(10);
504var tryCatch = _dereq_(18);
505function safelyResolveThenable(self, thenable) {
506 // Either fulfill, reject or reject with error
507 var called = false;
508 function onError(value) {
509 if (called) {
510 return;
511 }
512 called = true;
513 handlers.reject(self, value);
514 }
515
516 function onSuccess(value) {
517 if (called) {
518 return;
519 }
520 called = true;
521 handlers.resolve(self, value);
522 }
523
524 function tryToUnwrap() {
525 thenable(onSuccess, onError);
526 }
527
528 var result = tryCatch(tryToUnwrap);
529 if (result.status === 'error') {
530 onError(result.value);
531 }
532}
533exports.safely = safelyResolveThenable;
534},{"10":10,"18":18}],17:[function(_dereq_,module,exports){
535// Lazy man's symbols for states
536
537exports.REJECTED = ['REJECTED'];
538exports.FULFILLED = ['FULFILLED'];
539exports.PENDING = ['PENDING'];
540},{}],18:[function(_dereq_,module,exports){
541'use strict';
542
543module.exports = tryCatch;
544
545function tryCatch(func, value) {
546 var out = {};
547 try {
548 out.value = func(value);
549 out.status = 'success';
550 } catch (e) {
551 out.status = 'error';
552 out.value = e;
553 }
554 return out;
555}
556},{}],19:[function(_dereq_,module,exports){
557'use strict';
558
559var immediate = _dereq_(2);
560var handlers = _dereq_(10);
561module.exports = unwrap;
562
563function unwrap(promise, func, value) {
564 immediate(function () {
565 var returnValue;
566 try {
567 returnValue = func(value);
568 } catch (e) {
569 return handlers.reject(promise, e);
570 }
571 if (returnValue === promise) {
572 handlers.reject(promise, new TypeError('Cannot resolve promise with itself'));
573 } else {
574 handlers.resolve(promise, returnValue);
575 }
576 });
577}
578},{"10":10,"2":2}],20:[function(_dereq_,module,exports){
579(function (global){
580if (typeof global.Promise === 'function') {
581 module.exports = global.Promise;
582} else {
583 module.exports = _dereq_(11);
584}
585}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
586},{"11":11}],21:[function(_dereq_,module,exports){
587// shim for using process in browser
588
589var process = module.exports = {};
590var queue = [];
591var draining = false;
592
593function drainQueue() {
594 if (draining) {
595 return;
596 }
597 draining = true;
598 var currentQueue;
599 var len = queue.length;
600 while(len) {
601 currentQueue = queue;
602 queue = [];
603 var i = -1;
604 while (++i < len) {
605 currentQueue[i]();
606 }
607 len = queue.length;
608 }
609 draining = false;
610}
611process.nextTick = function (fun) {
612 queue.push(fun);
613 if (!draining) {
614 setTimeout(drainQueue, 0);
615 }
616};
617
618process.title = 'browser';
619process.browser = true;
620process.env = {};
621process.argv = [];
622process.version = ''; // empty string to avoid regexp issues
623process.versions = {};
624
625function noop() {}
626
627process.on = noop;
628process.addListener = noop;
629process.once = noop;
630process.off = noop;
631process.removeListener = noop;
632process.removeAllListeners = noop;
633process.emit = noop;
634
635process.binding = function (name) {
636 throw new Error('process.binding is not supported');
637};
638
639// TODO(shtylman)
640process.cwd = function () { return '/' };
641process.chdir = function (dir) {
642 throw new Error('process.chdir is not supported');
643};
644process.umask = function() { return 0; };
645
646},{}],22:[function(_dereq_,module,exports){
647'use strict';
648
649/* jshint -W079 */
650var Blob = _dereq_(1);
651var Promise = _dereq_(20);
652
653//
654// PRIVATE
655//
656
657// From http://stackoverflow.com/questions/14967647/ (continues on next line)
658// encode-decode-image-with-base64-breaks-image (2013-04-21)
659function binaryStringToArrayBuffer(binary) {
660 var length = binary.length;
661 var buf = new ArrayBuffer(length);
662 var arr = new Uint8Array(buf);
663 var i = -1;
664 while (++i < length) {
665 arr[i] = binary.charCodeAt(i);
666 }
667 return buf;
668}
669
670// Can't find original post, but this is close
671// http://stackoverflow.com/questions/6965107/ (continues on next line)
672// converting-between-strings-and-arraybuffers
673function arrayBufferToBinaryString(buffer) {
674 var binary = '';
675 var bytes = new Uint8Array(buffer);
676 var length = bytes.byteLength;
677 var i = -1;
678 while (++i < length) {
679 binary += String.fromCharCode(bytes[i]);
680 }
681 return binary;
682}
683
684// doesn't download the image more than once, because
685// browsers aren't dumb. uses the cache
686function loadImage(src, crossOrigin) {
687 return new Promise(function (resolve, reject) {
688 var img = new Image();
689 if (crossOrigin) {
690 img.crossOrigin = crossOrigin;
691 }
692 img.onload = function () {
693 resolve(img);
694 };
695 img.onerror = reject;
696 img.src = src;
697 });
698}
699
700function imgToCanvas(img) {
701 var canvas = document.createElement('canvas');
702
703 canvas.width = img.width;
704 canvas.height = img.height;
705
706 // copy the image contents to the canvas
707 var context = canvas.getContext('2d');
708 context.drawImage(
709 img,
710 0, 0,
711 img.width, img.height,
712 0, 0,
713 img.width, img.height);
714
715 return canvas;
716}
717
718//
719// PUBLIC
720//
721
722/**
723 * Shim for
724 * [new Blob()]{@link https://developer.mozilla.org/en-US/docs/Web/API/Blob.Blob}
725 * to support
726 * [older browsers that use the deprecated <code>BlobBuilder</code> API]{@link http://caniuse.com/blob}.
727 *
728 * @param {Array} parts - content of the <code>Blob</code>
729 * @param {Object} options - usually just <code>{type: myContentType}</code>
730 * @returns {Blob}
731 */
732function createBlob(parts, options) {
733 options = options || {};
734 if (typeof options === 'string') {
735 options = {type: options}; // do you a solid here
736 }
737 return new Blob(parts, options);
738}
739
740/**
741 * Shim for
742 * [URL.createObjectURL()]{@link https://developer.mozilla.org/en-US/docs/Web/API/URL.createObjectURL}
743 * to support browsers that only have the prefixed
744 * <code>webkitURL</code> (e.g. Android <4.4).
745 * @param {Blob} blob
746 * @returns {string} url
747 */
748function createObjectURL(blob) {
749 return (window.URL || window.webkitURL).createObjectURL(blob);
750}
751
752/**
753 * Shim for
754 * [URL.revokeObjectURL()]{@link https://developer.mozilla.org/en-US/docs/Web/API/URL.revokeObjectURL}
755 * to support browsers that only have the prefixed
756 * <code>webkitURL</code> (e.g. Android <4.4).
757 * @param {string} url
758 */
759function revokeObjectURL(url) {
760 return (window.URL || window.webkitURL).revokeObjectURL(url);
761}
762
763/**
764 * Convert a <code>Blob</code> to a binary string. Returns a Promise.
765 *
766 * @param {Blob} blob
767 * @returns {Promise} Promise that resolves with the binary string
768 */
769function blobToBinaryString(blob) {
770 return new Promise(function (resolve, reject) {
771 var reader = new FileReader();
772 var hasBinaryString = typeof reader.readAsBinaryString === 'function';
773 reader.onloadend = function (e) {
774 var result = e.target.result || '';
775 if (hasBinaryString) {
776 return resolve(result);
777 }
778 resolve(arrayBufferToBinaryString(result));
779 };
780 reader.onerror = reject;
781 if (hasBinaryString) {
782 reader.readAsBinaryString(blob);
783 } else {
784 reader.readAsArrayBuffer(blob);
785 }
786 });
787}
788
789/**
790 * Convert a base64-encoded string to a <code>Blob</code>. Returns a Promise.
791 * @param {string} base64
792 * @param {string|undefined} type - the content type (optional)
793 * @returns {Promise} Promise that resolves with the <code>Blob</code>
794 */
795function base64StringToBlob(base64, type) {
796 return Promise.resolve().then(function () {
797 var parts = [binaryStringToArrayBuffer(atob(base64))];
798 return type ? createBlob(parts, {type: type}) : createBlob(parts);
799 });
800}
801
802/**
803 * Convert a binary string to a <code>Blob</code>. Returns a Promise.
804 * @param {string} binary
805 * @param {string|undefined} type - the content type (optional)
806 * @returns {Promise} Promise that resolves with the <code>Blob</code>
807 */
808function binaryStringToBlob(binary, type) {
809 return Promise.resolve().then(function () {
810 return base64StringToBlob(btoa(binary), type);
811 });
812}
813
814/**
815 * Convert a <code>Blob</code> to a binary string. Returns a Promise.
816 * @param {Blob} blob
817 * @returns {Promise} Promise that resolves with the binary string
818 */
819function blobToBase64String(blob) {
820 return blobToBinaryString(blob).then(function (binary) {
821 return btoa(binary);
822 });
823}
824
825/**
826 * Convert a data URL string
827 * (e.g. <code>'data:image/png;base64,iVBORw0KG...'</code>)
828 * to a <code>Blob</code>. Returns a Promise.
829 * @param {string} dataURL
830 * @returns {Promise} Promise that resolves with the <code>Blob</code>
831 */
832function dataURLToBlob(dataURL) {
833 return Promise.resolve().then(function () {
834 var type = dataURL.match(/data:([^;]+)/)[1];
835 var base64 = dataURL.replace(/^[^,]+,/, '');
836
837 var buff = binaryStringToArrayBuffer(atob(base64));
838 return createBlob([buff], {type: type});
839 });
840}
841
842/**
843 * Convert an image's <code>src</code> URL to a data URL by loading the image and painting
844 * it to a <code>canvas</code>. Returns a Promise.
845 *
846 * <p/>Note: this will coerce the image to the desired content type, and it
847 * will only paint the first frame of an animated GIF.
848 *
849 * @param {string} src
850 * @param {string|undefined} type - the content type (optional, defaults to 'image/png')
851 * @param {string|undefined} crossOrigin - for CORS-enabled images, set this to
852 * 'Anonymous' to avoid "tainted canvas" errors
853 * @param {number|undefined} quality - a number between 0 and 1 indicating image quality
854 * if the requested type is 'image/jpeg' or 'image/webp'
855 * @returns {Promise} Promise that resolves with the data URL string
856 */
857function imgSrcToDataURL(src, type, crossOrigin, quality) {
858 type = type || 'image/png';
859
860 return loadImage(src, crossOrigin).then(function (img) {
861 return imgToCanvas(img);
862 }).then(function (canvas) {
863 return canvas.toDataURL(type, quality);
864 });
865}
866
867/**
868 * Convert a <code>canvas</code> to a <code>Blob</code>. Returns a Promise.
869 * @param {string} canvas
870 * @param {string|undefined} type - the content type (optional, defaults to 'image/png')
871 * @param {number|undefined} quality - a number between 0 and 1 indicating image quality
872 * if the requested type is 'image/jpeg' or 'image/webp'
873 * @returns {Promise} Promise that resolves with the <code>Blob</code>
874 */
875function canvasToBlob(canvas, type, quality) {
876 return Promise.resolve().then(function () {
877 if (typeof canvas.toBlob === 'function') {
878 return new Promise(function (resolve) {
879 canvas.toBlob(resolve, type, quality);
880 });
881 }
882 return dataURLToBlob(canvas.toDataURL(type, quality));
883 });
884}
885
886/**
887 * Convert an image's <code>src</code> URL to a <code>Blob</code> by loading the image and painting
888 * it to a <code>canvas</code>. Returns a Promise.
889 *
890 * <p/>Note: this will coerce the image to the desired content type, and it
891 * will only paint the first frame of an animated GIF.
892 *
893 * @param {string} src
894 * @param {string|undefined} type - the content type (optional, defaults to 'image/png')
895 * @param {string|undefined} crossOrigin - for CORS-enabled images, set this to
896 * 'Anonymous' to avoid "tainted canvas" errors
897 * @param {number|undefined} quality - a number between 0 and 1 indicating image quality
898 * if the requested type is 'image/jpeg' or 'image/webp'
899 * @returns {Promise} Promise that resolves with the <code>Blob</code>
900 */
901function imgSrcToBlob(src, type, crossOrigin, quality) {
902 type = type || 'image/png';
903
904 return loadImage(src, crossOrigin).then(function (img) {
905 return imgToCanvas(img);
906 }).then(function (canvas) {
907 return canvasToBlob(canvas, type, quality);
908 });
909}
910
911/**
912 * Convert an <code>ArrayBuffer</code> to a <code>Blob</code>. Returns a Promise.
913 *
914 * @param {ArrayBuffer} buffer
915 * @param {string|undefined} type - the content type (optional)
916 * @returns {Promise} Promise that resolves with the <code>Blob</code>
917 */
918function arrayBufferToBlob(buffer, type) {
919 return Promise.resolve().then(function () {
920 return createBlob([buffer], type);
921 });
922}
923
924/**
925 * Convert a <code>Blob</code> to an <code>ArrayBuffer</code>. Returns a Promise.
926 * @param {Blob} blob
927 * @returns {Promise} Promise that resolves with the <code>ArrayBuffer</code>
928 */
929function blobToArrayBuffer(blob) {
930 return new Promise(function (resolve, reject) {
931 var reader = new FileReader();
932 reader.onloadend = function (e) {
933 var result = e.target.result || new ArrayBuffer(0);
934 resolve(result);
935 };
936 reader.onerror = reject;
937 reader.readAsArrayBuffer(blob);
938 });
939}
940
941module.exports = {
942 createBlob : createBlob,
943 createObjectURL : createObjectURL,
944 revokeObjectURL : revokeObjectURL,
945 imgSrcToBlob : imgSrcToBlob,
946 imgSrcToDataURL : imgSrcToDataURL,
947 canvasToBlob : canvasToBlob,
948 dataURLToBlob : dataURLToBlob,
949 blobToBase64String : blobToBase64String,
950 base64StringToBlob : base64StringToBlob,
951 binaryStringToBlob : binaryStringToBlob,
952 blobToBinaryString : blobToBinaryString,
953 arrayBufferToBlob : arrayBufferToBlob,
954 blobToArrayBuffer : blobToArrayBuffer
955};
956
957},{"1":1,"20":20}]},{},[22])(22)
958});
\No newline at end of file