123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663 |
- ;(function(jsPDFAPI) {
- 'use strict'
- var namespace = 'addImage_',
- supported_image_types = ['jpeg', 'jpg', 'png'];
-
- var putImage = function(img) {
- var objectNumber = this.internal.newObject()
- , out = this.internal.write
- , putStream = this.internal.putStream
- img['n'] = objectNumber
- out('<</Type /XObject')
- out('/Subtype /Image')
- out('/Width ' + img['w'])
- out('/Height ' + img['h'])
- if (img['cs'] === this.color_spaces.INDEXED) {
- out('/ColorSpace [/Indexed /DeviceRGB '
-
- + (img['pal'].length / 3 - 1) + ' ' + ('smask' in img ? objectNumber + 2 : objectNumber + 1)
- + ' 0 R]');
- } else {
- out('/ColorSpace /' + img['cs']);
- if (img['cs'] === this.color_spaces.DEVICE_CMYK) {
- out('/Decode [1 0 1 0 1 0 1 0]');
- }
- }
- out('/BitsPerComponent ' + img['bpc']);
- if ('f' in img) {
- out('/Filter /' + img['f']);
- }
- if ('dp' in img) {
- out('/DecodeParms <<' + img['dp'] + '>>');
- }
- if ('trns' in img && img['trns'].constructor == Array) {
- var trns = '',
- i = 0,
- len = img['trns'].length;
- for (; i < len; i++)
- trns += (img['trns'][i] + ' ' + img['trns'][i] + ' ');
- out('/Mask [' + trns + ']');
- }
- if ('smask' in img) {
- out('/SMask ' + (objectNumber + 1) + ' 0 R');
- }
- out('/Length ' + img['data'].length + '>>');
- putStream(img['data']);
- out('endobj');
-
- if ('smask' in img) {
- var dp = '/Predictor 15 /Colors 1 /BitsPerComponent ' + img['bpc'] + ' /Columns ' + img['w'];
- var smask = {'w': img['w'], 'h': img['h'], 'cs': 'DeviceGray', 'bpc': img['bpc'], 'dp': dp, 'data': img['smask']};
- if ('f' in img)
- smask.f = img['f'];
- putImage.call(this, smask);
- }
-
- if (img['cs'] === this.color_spaces.INDEXED) {
- this.internal.newObject();
-
-
- out('<< /Length ' + img['pal'].length + '>>');
- putStream(this.arrayBufferToBinaryString(new Uint8Array(img['pal'])));
- out('endobj');
- }
- }
- , putResourcesCallback = function() {
- var images = this.internal.collections[namespace + 'images']
- for ( var i in images ) {
- putImage.call(this, images[i])
- }
- }
- , putXObjectsDictCallback = function(){
- var images = this.internal.collections[namespace + 'images']
- , out = this.internal.write
- , image
- for (var i in images) {
- image = images[i]
- out(
- '/I' + image['i']
- , image['n']
- , '0'
- , 'R'
- )
- }
- }
- , checkCompressValue = function(value) {
- if(value && typeof value === 'string')
- value = value.toUpperCase();
- return value in jsPDFAPI.image_compression ? value : jsPDFAPI.image_compression.NONE;
- }
- , getImages = function() {
- var images = this.internal.collections[namespace + 'images'];
-
- if(!images) {
- this.internal.collections[namespace + 'images'] = images = {};
- this.internal.events.subscribe('putResources', putResourcesCallback);
- this.internal.events.subscribe('putXobjectDict', putXObjectsDictCallback);
- }
- return images;
- }
- , getImageIndex = function(images) {
- var imageIndex = 0;
- if (images){
-
- imageIndex = Object.keys ?
- Object.keys(images).length :
- (function(o){
- var i = 0
- for (var e in o){if(o.hasOwnProperty(e)){ i++ }}
- return i
- })(images)
- }
- return imageIndex;
- }
- , notDefined = function(value) {
- return typeof value === 'undefined' || value === null;
- }
- , generateAliasFromData = function(data) {
-
- return undefined;
- }
- , doesNotSupportImageType = function(type) {
- return supported_image_types.indexOf(type) === -1;
- }
- , processMethodNotEnabled = function(type) {
- return typeof jsPDFAPI['process' + type.toUpperCase()] !== 'function';
- }
- , isDOMElement = function(object) {
- return typeof object === 'object' && object.nodeType === 1;
- }
- , createDataURIFromElement = function(element, format) {
-
- if (element.nodeName === 'IMG' && element.hasAttribute('src')) {
- var src = ''+element.getAttribute('src');
- if (src.indexOf('data:image/') === 0) return src;
-
- if (!format && /\.png(?:[?#].*)?$/i.test(src)) format = 'png';
- }
- if(element.nodeName === 'CANVAS') {
- var canvas = element;
- } else {
- var canvas = document.createElement('canvas');
- canvas.width = element.clientWidth || element.width;
- canvas.height = element.clientHeight || element.height;
- var ctx = canvas.getContext('2d');
- if (!ctx) {
- throw ('addImage requires canvas to be supported by browser.');
- }
- ctx.drawImage(element, 0, 0, canvas.width, canvas.height);
- }
- return canvas.toDataURL((''+format).toLowerCase() == 'png' ? 'image/png' : 'image/jpeg');
- }
- ,checkImagesForAlias = function(imageData, images) {
- var cached_info;
- if(images) {
- for(var e in images) {
- if(imageData === images[e].alias) {
- cached_info = images[e];
- break;
- }
- }
- }
- return cached_info;
- }
- ,determineWidthAndHeight = function(w, h, info) {
- if (!w && !h) {
- w = -96;
- h = -96;
- }
- if (w < 0) {
- w = (-1) * info['w'] * 72 / w / this.internal.scaleFactor;
- }
- if (h < 0) {
- h = (-1) * info['h'] * 72 / h / this.internal.scaleFactor;
- }
- if (w === 0) {
- w = h * info['w'] / info['h'];
- }
- if (h === 0) {
- h = w * info['h'] / info['w'];
- }
- return [w, h];
- }
- , writeImageToPDF = function(x, y, w, h, info, index, images) {
- var dims = determineWidthAndHeight.call(this, w, h, info),
- coord = this.internal.getCoordinateString,
- vcoord = this.internal.getVerticalCoordinateString;
- w = dims[0];
- h = dims[1];
- images[index] = info;
- this.internal.write(
- 'q'
- , coord(w)
- , '0 0'
- , coord(h)
- , coord(x)
- , vcoord(y + h)
- , 'cm /I'+info['i']
- , 'Do Q'
- )
- };
-
- jsPDFAPI.color_spaces = {
- DEVICE_RGB:'DeviceRGB',
- DEVICE_GRAY:'DeviceGray',
- DEVICE_CMYK:'DeviceCMYK',
- CAL_GREY:'CalGray',
- CAL_RGB:'CalRGB',
- LAB:'Lab',
- ICC_BASED:'ICCBased',
- INDEXED:'Indexed',
- PATTERN:'Pattern',
- SEPERATION:'Seperation',
- DEVICE_N:'DeviceN'
- };
-
- jsPDFAPI.decode = {
- DCT_DECODE:'DCTDecode',
- FLATE_DECODE:'FlateDecode',
- LZW_DECODE:'LZWDecode',
- JPX_DECODE:'JPXDecode',
- JBIG2_DECODE:'JBIG2Decode',
- ASCII85_DECODE:'ASCII85Decode',
- ASCII_HEX_DECODE:'ASCIIHexDecode',
- RUN_LENGTH_DECODE:'RunLengthDecode',
- CCITT_FAX_DECODE:'CCITTFaxDecode'
- };
-
- jsPDFAPI.image_compression = {
- NONE: 'NONE',
- FAST: 'FAST',
- MEDIUM: 'MEDIUM',
- SLOW: 'SLOW'
- };
- jsPDFAPI.isString = function(object) {
- return typeof object === 'string';
- };
-
- jsPDFAPI.extractInfoFromBase64DataURI = function(dataURI) {
- return /^data:([\w]+?\/([\w]+?));base64,(.+?)$/g.exec(dataURI);
- };
-
- jsPDFAPI.supportsArrayBuffer = function() {
- return typeof ArrayBuffer !== 'undefined' && typeof Uint8Array !== 'undefined';
- };
-
- jsPDFAPI.isArrayBuffer = function(object) {
- if(!this.supportsArrayBuffer())
- return false;
- return object instanceof ArrayBuffer;
- };
-
- jsPDFAPI.isArrayBufferView = function(object) {
- if(!this.supportsArrayBuffer())
- return false;
- if(typeof Uint32Array === 'undefined')
- return false;
- return (object instanceof Int8Array ||
- object instanceof Uint8Array ||
- (typeof Uint8ClampedArray !== 'undefined' && object instanceof Uint8ClampedArray) ||
- object instanceof Int16Array ||
- object instanceof Uint16Array ||
- object instanceof Int32Array ||
- object instanceof Uint32Array ||
- object instanceof Float32Array ||
- object instanceof Float64Array );
- };
-
- jsPDFAPI.binaryStringToUint8Array = function(binary_string) {
-
- var len = binary_string.length;
- var bytes = new Uint8Array( len );
- for (var i = 0; i < len; i++) {
- bytes[i] = binary_string.charCodeAt(i);
- }
- return bytes;
- };
-
- jsPDFAPI.arrayBufferToBinaryString = function(buffer) {
- if(this.isArrayBuffer(buffer))
- buffer = new Uint8Array(buffer);
- var binary_string = '';
- var len = buffer.byteLength;
- for (var i = 0; i < len; i++) {
- binary_string += String.fromCharCode(buffer[i]);
- }
- return binary_string;
-
-
- };
-
- jsPDFAPI.arrayBufferToBase64 = function(arrayBuffer) {
- var base64 = ''
- var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
- var bytes = new Uint8Array(arrayBuffer)
- var byteLength = bytes.byteLength
- var byteRemainder = byteLength % 3
- var mainLength = byteLength - byteRemainder
- var a, b, c, d
- var chunk
-
- for (var i = 0; i < mainLength; i = i + 3) {
-
- chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]
-
- a = (chunk & 16515072) >> 18
- b = (chunk & 258048) >> 12
- c = (chunk & 4032) >> 6
- d = chunk & 63
-
- base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]
- }
-
- if (byteRemainder == 1) {
- chunk = bytes[mainLength]
- a = (chunk & 252) >> 2
-
- b = (chunk & 3) << 4
- base64 += encodings[a] + encodings[b] + '=='
- } else if (byteRemainder == 2) {
- chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]
- a = (chunk & 64512) >> 10
- b = (chunk & 1008) >> 4
-
- c = (chunk & 15) << 2
- base64 += encodings[a] + encodings[b] + encodings[c] + '='
- }
- return base64
- };
- jsPDFAPI.createImageInfo = function(data, wd, ht, cs, bpc, f, imageIndex, alias, dp, trns, pal, smask) {
- var info = {
- alias:alias,
- w : wd,
- h : ht,
- cs : cs,
- bpc : bpc,
- i : imageIndex,
- data : data
-
- };
- if(f) info.f = f;
- if(dp) info.dp = dp;
- if(trns) info.trns = trns;
- if(pal) info.pal = pal;
- if(smask) info.smask = smask;
- return info;
- };
- jsPDFAPI.addImage = function(imageData, format, x, y, w, h, alias, compression) {
- 'use strict'
- if(typeof format === 'number') {
- var tmp = h;
- h = w;
- w = y;
- y = x;
- x = format;
- format = tmp;
- }
- var images = getImages.call(this),
- dataAsBinaryString;
- compression = checkCompressValue(compression);
- if(notDefined(alias))
- alias = generateAliasFromData(imageData);
- if(isDOMElement(imageData))
- imageData = createDataURIFromElement(imageData, format);
- if(this.isString(imageData)) {
- var base64Info = this.extractInfoFromBase64DataURI(imageData);
- if(base64Info) {
- format = base64Info[2];
- imageData = atob(base64Info[3]);
- } else {
- if (imgData.charCodeAt(0) === 0x89 &&
- imgData.charCodeAt(1) === 0x50 &&
- imgData.charCodeAt(2) === 0x4e &&
- imgData.charCodeAt(3) === 0x47 ) format = 'png';
- }
- }
- format = (format || 'JPEG').toLowerCase();
- if(doesNotSupportImageType(format))
- throw new Error('addImage currently only supports formats ' + supported_image_types + ', not \''+format+'\'');
- if(processMethodNotEnabled(format))
- throw new Error('please ensure that the plugin for \''+format+'\' support is added');
-
- if(this.supportsArrayBuffer()) {
- dataAsBinaryString = imageData;
- imageData = this.binaryStringToUint8Array(imageData);
- }
- var imageIndex = getImageIndex(images),
- info = checkImagesForAlias(dataAsBinaryString || imageData, images);
- if(!info)
- info = this['process' + format.toUpperCase()](imageData, imageIndex, alias, compression, dataAsBinaryString);
- if(!info)
- throw new Error('An unkwown error occurred whilst processing the image');
- writeImageToPDF.call(this, x, y, w, h, info, imageIndex, images);
- return this
- };
-
-
-
-
- var getJpegSize = function(imgData) {
- 'use strict'
- var width, height, numcomponents;
-
- if (!imgData.charCodeAt(0) === 0xff ||
- !imgData.charCodeAt(1) === 0xd8 ||
- !imgData.charCodeAt(2) === 0xff ||
- !imgData.charCodeAt(3) === 0xe0 ||
- !imgData.charCodeAt(6) === 'J'.charCodeAt(0) ||
- !imgData.charCodeAt(7) === 'F'.charCodeAt(0) ||
- !imgData.charCodeAt(8) === 'I'.charCodeAt(0) ||
- !imgData.charCodeAt(9) === 'F'.charCodeAt(0) ||
- !imgData.charCodeAt(10) === 0x00) {
- throw new Error('getJpegSize requires a binary string jpeg file')
- }
- var blockLength = imgData.charCodeAt(4)*256 + imgData.charCodeAt(5);
- var i = 4, len = imgData.length;
- while ( i < len ) {
- i += blockLength;
- if (imgData.charCodeAt(i) !== 0xff) {
- throw new Error('getJpegSize could not find the size of the image');
- }
- if (imgData.charCodeAt(i+1) === 0xc0 ||
- imgData.charCodeAt(i+1) === 0xc1 ||
- imgData.charCodeAt(i+1) === 0xc2 ||
- imgData.charCodeAt(i+1) === 0xc3 ||
- imgData.charCodeAt(i+1) === 0xc4 ||
- imgData.charCodeAt(i+1) === 0xc5 ||
- imgData.charCodeAt(i+1) === 0xc6 ||
- imgData.charCodeAt(i+1) === 0xc7) {
- height = imgData.charCodeAt(i+5)*256 + imgData.charCodeAt(i+6);
- width = imgData.charCodeAt(i+7)*256 + imgData.charCodeAt(i+8);
- numcomponents = imgData.charCodeAt(i+9);
- return [width, height, numcomponents];
- } else {
- i += 2;
- blockLength = imgData.charCodeAt(i)*256 + imgData.charCodeAt(i+1)
- }
- }
- }
- , getJpegSizeFromBytes = function(data) {
- var hdr = (data[0] << 8) | data[1];
- if(hdr !== 0xFFD8)
- throw new Error('Supplied data is not a JPEG');
- var len = data.length,
- block = (data[4] << 8) + data[5],
- pos = 4,
- bytes, width, height, numcomponents;
- while(pos < len) {
- pos += block;
- bytes = readBytes(data, pos);
- block = (bytes[2] << 8) + bytes[3];
- if((bytes[1] === 0xC0 || bytes[1] === 0xC2) && bytes[0] === 0xFF && block > 7) {
- bytes = readBytes(data, pos + 5);
- width = (bytes[2] << 8) + bytes[3];
- height = (bytes[0] << 8) + bytes[1];
- numcomponents = bytes[4];
- return {width:width, height:height, numcomponents: numcomponents};
- }
- pos+=2;
- }
- throw new Error('getJpegSizeFromBytes could not find the size of the image');
- }
- , readBytes = function(data, offset) {
- return data.subarray(offset, offset+ 5);
- };
- jsPDFAPI.processJPEG = function(data, index, alias, compression, dataAsBinaryString) {
- 'use strict'
- var colorSpace = this.color_spaces.DEVICE_RGB,
- filter = this.decode.DCT_DECODE,
- bpc = 8,
- dims;
- if(this.isString(data)) {
- dims = getJpegSize(data);
- return this.createImageInfo(data, dims[0], dims[1], dims[3] == 1 ? this.color_spaces.DEVICE_GRAY:colorSpace, bpc, filter, index, alias);
- }
- if(this.isArrayBuffer(data))
- data = new Uint8Array(data);
- if(this.isArrayBufferView(data)) {
- dims = getJpegSizeFromBytes(data);
-
- data = dataAsBinaryString || this.arrayBufferToBinaryString(data);
- return this.createImageInfo(data, dims.width, dims.height, dims.numcomponents == 1 ? this.color_spaces.DEVICE_GRAY:colorSpace, bpc, filter, index, alias);
- }
- return null;
- };
- jsPDFAPI.processJPG = function() {
- return this.processJPEG.apply(this, arguments);
- }
- })(jsPDF.API);
|