diff --git a/src/modules/addimage.js b/src/modules/addimage.js index ef83a1e74..955087591 100644 --- a/src/modules/addimage.js +++ b/src/modules/addimage.js @@ -43,6 +43,11 @@ import { atob, btoa } from "../libs/AtobBtoa.js"; var UNKNOWN = "UNKNOWN"; + // Heuristic selection of a good batch for large array .apply. Not limiting make the call overflow. + // With too small batch iteration will be slow as more calls are made, + // higher values cause larger and slower garbage collection. + var ARRAY_APPLY_BATCH = 8192; + var imageFileTypeHeaders = { PNG: [[0x89, 0x50, 0x4e, 0x47]], TIFF: [ @@ -731,27 +736,27 @@ import { atob, btoa } from "../libs/AtobBtoa.js"; * @name arrayBufferToBinaryString * @public * @function - * @param {ArrayBuffer} ArrayBuffer with ImageData + * @param {ArrayBuffer|ArrayBufferView} ArrayBuffer buffer or bufferView with ImageData * * @returns {String} */ var arrayBufferToBinaryString = (jsPDFAPI.__addimage__.arrayBufferToBinaryString = function( buffer ) { - try { - return atob(btoa(String.fromCharCode.apply(null, buffer))); - } catch (e) { - if ( - typeof Uint8Array !== "undefined" && - typeof Uint8Array.prototype.reduce !== "undefined" - ) { - return new Uint8Array(buffer) - .reduce(function(data, byte) { - return data.push(String.fromCharCode(byte)), data; - }, []) - .join(""); - } + var out = ""; + // There are calls with both ArrayBuffer and already converted Uint8Array or other BufferView. + // Do not copy the array if input is already an array. + var buf = isArrayBufferView(buffer) ? buffer : new Uint8Array(buffer); + for (var i = 0; i < buf.length; i += ARRAY_APPLY_BATCH) { + // Limit the amount of characters being parsed to prevent overflow. + // Note that while TextDecoder would be faster, it does not have the same + // functionality as fromCharCode with any provided encodings as of 3/2021. + out += String.fromCharCode.apply( + null, + buf.subarray(i, i + ARRAY_APPLY_BATCH) + ); } + return out; }); /**